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 | |
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.
45 files changed, 3041 insertions, 4087 deletions
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<Anope::string> 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<Anope::string> &); -E int m_whois(const Anope::string &source, const Anope::string &who); -E bool m_time(const Anope::string &source, const std::vector<Anope::string> &); -E bool m_version(const Anope::string &source, const std::vector<Anope::string> &); +/**** messages.cpp ****/ + E void init_core_messages(); +E bool OnStats(const Anope::string &source, const std::vector<Anope::string> &); +E bool OnTime(const Anope::string &source, const std::vector<Anope::string> &); +E bool OnVersion(const Anope::string &source, const std::vector<Anope::string> &); + +E bool On436(const Anope::string &, const std::vector<Anope::string> &); +E bool OnAway(const Anope::string &, const std::vector<Anope::string> &); +E bool OnJoin(const Anope::string &, const std::vector<Anope::string> &); +E bool OnKick(const Anope::string &, const std::vector<Anope::string> &); +E bool OnKill(const Anope::string &, const std::vector<Anope::string> &); +E bool OnMode(const Anope::string &, const std::vector<Anope::string> &); +E bool OnNick(const Anope::string &, const std::vector<Anope::string> &); +E bool OnUID(const Anope::string &, const std::vector<Anope::string> &); +E bool OnPart(const Anope::string &, const std::vector<Anope::string> &); +E bool OnPing(const Anope::string &, const std::vector<Anope::string> &); +E bool OnPrivmsg(const Anope::string &, const std::vector<Anope::string> &); +E bool OnQuit(const Anope::string &, const std::vector<Anope::string> &); +E bool OnServer(const Anope::string &, const std::vector<Anope::string> &); +E bool OnSQuit(const Anope::string &, const std::vector<Anope::string> &); +E bool OnTopic(const Anope::string &, const std::vector<Anope::string> &); +E bool OnWhois(const Anope::string &, const std::vector<Anope::string> &); +E bool OnCapab(const Anope::string &, const std::vector<Anope::string> &); +E bool OnSJoin(const Anope::string &, const std::vector<Anope::string> &); +E bool OnError(const Anope::string &, const std::vector<Anope::string> &); + /**** 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<Exception *> 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<Anope::string> ¶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<Anope::string> &); + virtual bool OnAway(const Anope::string &, const std::vector<Anope::string> &); + virtual bool OnJoin(const Anope::string &, const std::vector<Anope::string> &); + virtual bool OnKick(const Anope::string &, const std::vector<Anope::string> &); + virtual bool OnKill(const Anope::string &, const std::vector<Anope::string> &); + virtual bool OnMode(const Anope::string &, const std::vector<Anope::string> &) = 0; + virtual bool OnUID(const Anope::string &, const std::vector<Anope::string> &); + virtual bool OnNick(const Anope::string &, const std::vector<Anope::string> &) = 0; + virtual bool OnPart(const Anope::string &, const std::vector<Anope::string> &); + virtual bool OnPing(const Anope::string &, const std::vector<Anope::string> &); + virtual bool OnPrivmsg(const Anope::string &, const std::vector<Anope::string> &); + virtual bool OnQuit(const Anope::string &, const std::vector<Anope::string> &); + virtual bool OnServer(const Anope::string &, const std::vector<Anope::string> &) = 0; + virtual bool OnSQuit(const Anope::string &, const std::vector<Anope::string> &); + virtual bool OnTopic(const Anope::string &, const std::vector<Anope::string> &) = 0; + virtual bool OnWhois(const Anope::string &, const std::vector<Anope::string> &); + virtual bool OnCapab(const Anope::string &, const std::vector<Anope::string> &); + virtual bool OnSJoin(const Anope::string &, const std::vector<Anope::string> &) = 0; + virtual bool OnError(const Anope::string &, const std::vector<Anope::string> &); +}; + /*************************************************************************/ 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<std::pair<Anope::string, Anope::string> >::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<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); } diff --git a/src/actions.cpp b/src/actions.cpp index 6b3a96a24..b583cafae 100644 --- a/src/actions.cpp +++ b/src/actions.cpp @@ -30,7 +30,7 @@ bool bad_password(User *u) u->invalid_pw_time = Anope::CurTime; if (u->invalid_pw_count >= Config->BadPassLimit) { - kill_user("", u->nick, "Too many invalid passwords"); + kill_user("", u, "Too many invalid passwords"); return true; } @@ -41,48 +41,41 @@ bool bad_password(User *u) /** * Remove a user from the IRC network. - * @param source is the nick which should generate the kill, or NULL for a server-generated kill. + * @param source is the nick which should generate the kill, or empty for a server-generated kill. * @param user to remove * @param reason for the kill * @return void */ -void kill_user(const Anope::string &source, const Anope::string &user, const Anope::string &reason) +void kill_user(const Anope::string &source, User *user, const Anope::string &reason) { - if (user.empty()) + if (!user) return; Anope::string real_source = source.empty() ? Config->ServerName : source; Anope::string buf = real_source + " (" + reason + ")"; - ircdproto->SendSVSKill(findbot(source), finduser(user), "%s", buf.c_str()); + ircdproto->SendSVSKill(findbot(source), user, "%s", buf.c_str()); - if (!ircd->quitonkill && finduser(user)) + if (!ircd->quitonkill) do_kill(user, buf); } /*************************************************************************/ /** - * Unban the nick from a channel + * Unban the user from a channel * @param ci channel info for the channel - * @param nick to remove the ban for + * @param u The user to unban * @return void */ -void common_unban(ChannelInfo *ci, const Anope::string &nick) +void common_unban(ChannelInfo *ci, User *u) { - if (!ci || !ci->c || nick.empty()) - return; - - User *u = finduser(nick); - if (!u) - return; - - if (!ci->c->HasMode(CMODE_BAN)) + if (!u || !ci || !ci->c || !ci->c->HasMode(CMODE_BAN)) return; if (ircd->svsmode_unban) - ircdproto->SendBanDel(ci->c, nick); + ircdproto->SendBanDel(ci->c, u->nick); else { std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> bans = ci->c->GetModeList(CMODE_BAN); diff --git a/src/botserv.cpp b/src/botserv.cpp index 32b6a42a3..ddd8dc15f 100644 --- a/src/botserv.cpp +++ b/src/botserv.cpp @@ -504,13 +504,14 @@ static void bot_kick(ChannelInfo *ci, User *u, LanguageString message, ...) /*************************************************************************/ -/* Makes a simple ban and kicks the target */ - -void bot_raw_ban(User *requester, ChannelInfo *ci, const Anope::string &nick, const Anope::string &reason) +/* Makes a simple ban and kicks the target + * @param requester The user requesting the kickban + * @param ci The channel + * @param u The user being kicked + * @param reason The reason + */ +void bot_raw_ban(User *requester, ChannelInfo *ci, User *u, const Anope::string &reason) { - Anope::string mask; - User *u = finduser(nick); - if (!u || !ci) return; @@ -522,7 +523,7 @@ void bot_raw_ban(User *requester, ChannelInfo *ci, const Anope::string &nick, co ChanAccess *u_access = ci->GetAccess(u), *req_access = ci->GetAccess(requester); int16 u_level = u_access ? u_access->level : 0, req_level = req_access ? req_access->level : 0; - if (ci->HasFlag(CI_PEACE) && !requester->nick.equals_ci(nick) && u_level >= req_level) + if (ci->HasFlag(CI_PEACE) && !requester->nick.equals_ci(u->nick) && u_level >= req_level) return; if (ModeManager::FindChannelModeByName(CMODE_EXCEPT) && is_excepted(ci, u) == 1) @@ -531,6 +532,7 @@ void bot_raw_ban(User *requester, ChannelInfo *ci, const Anope::string &nick, co return; } + Anope::string mask; get_idealban(ci, u, mask); ci->c->SetMode(NULL, CMODE_BAN, mask); @@ -544,12 +546,14 @@ void bot_raw_ban(User *requester, ChannelInfo *ci, const Anope::string &nick, co /*************************************************************************/ -/* Makes a kick with a "dynamic" reason ;) */ - -void bot_raw_kick(User *requester, ChannelInfo *ci, const Anope::string &nick, const Anope::string &reason) +/* Makes a kick with a "dynamic" reason ;) + * @param requester The user requesting the kick + * @param ci The channel + * @param u The user being kicked + * @param reason The reason for the kick + */ +void bot_raw_kick(User *requester, ChannelInfo *ci, User *u, const Anope::string &reason) { - User *u = finduser(nick); - if (!u || !ci || !ci->c || !ci->c->FindUser(u)) return; @@ -561,7 +565,7 @@ void bot_raw_kick(User *requester, ChannelInfo *ci, const Anope::string &nick, c ChanAccess *u_access = ci->GetAccess(u), *req_access = ci->GetAccess(requester); int16 u_level = u_access ? u_access->level : 0, req_level = req_access ? req_access->level : 0; - if (ci->HasFlag(CI_PEACE) && !requester->nick.equals_ci(nick) && u_level >= req_level) + if (ci->HasFlag(CI_PEACE) && !requester->nick.equals_ci(u->nick) && u_level >= req_level) return; if (ci->HasFlag(CI_SIGNKICK) || (ci->HasFlag(CI_SIGNKICK_LEVEL) && !check_access(requester, ci, CA_SIGNKICK))) @@ -572,35 +576,6 @@ void bot_raw_kick(User *requester, ChannelInfo *ci, const Anope::string &nick, c /*************************************************************************/ -/* Makes a mode operation on a channel for a nick */ - -void bot_raw_mode(User *requester, ChannelInfo *ci, const Anope::string &mode, const Anope::string &nick) -{ - char buf[BUFSIZE] = ""; - User *u; - - u = finduser(nick); - - if (!u || !ci || !ci->c || !ci->c->FindUser(u)) - return; - - snprintf(buf, BUFSIZE - 1, "%ld", static_cast<long>(Anope::CurTime)); - - if (ModeManager::FindUserModeByName(UMODE_PROTECTED) && u->IsProtected() && mode[0] == '-' && requester != u) - { - ircdproto->SendPrivmsg(ci->bi, ci->name, "%s", GetString(requester, ACCESS_DENIED).c_str()); - return; - } - - ChanAccess *u_access = ci->GetAccess(u), *req_access = ci->GetAccess(requester); - int16 u_level = u_access ? u_access->level : 0, req_level = req_access ? req_access->level : 0; - if (mode[0] == '-' && ci->HasFlag(CI_PEACE) && !requester->nick.equals_ci(nick) && u_level >= req_level) - return; - - ci->c->SetModes(NULL, "%s %s", mode.c_str(), nick.c_str()); -} - -/*************************************************************************/ /** * Normalize buffer stripping control characters and colors * @param A string to be parsed for control and color codes diff --git a/src/command.cpp b/src/command.cpp index f7edbfaa2..290f74d1f 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -16,7 +16,7 @@ CommandSource::~CommandSource() // Send to the user if the reply is more than one line if (!this->fantasy || !this->ci || this->reply.size() > 1) - u->SendMessage(this->service->nick, message); + u->SendMessage(this->service, message); else if (this->ci->botflags.HasFlag(BS_MSG_PRIVMSG)) ircdproto->SendPrivmsg(this->service, this->ci->name, message.c_str()); else if (this->ci->botflags.HasFlag(BS_MSG_NOTICE)) @@ -24,7 +24,7 @@ CommandSource::~CommandSource() else if (this->ci->botflags.HasFlag(BS_MSG_NOTICEOPS)) ircdproto->SendNoticeChanops(this->service, this->ci->c, message.c_str()); else - u->SendMessage(this->service->nick, message); + u->SendMessage(this->service, message); } } @@ -60,7 +60,7 @@ void CommandSource::Reply(const char *message, ...) va_start(args, message); vsnprintf(buf, BUFSIZE - 1, message, args); - this->reply.push_back(message); + this->reply.push_back(buf); va_end(args); } diff --git a/src/commands.cpp b/src/commands.cpp index e9671f3bd..6c5c556e5 100644 --- a/src/commands.cpp +++ b/src/commands.cpp @@ -187,7 +187,7 @@ void mod_help_cmd(BotInfo *bi, User *u, ChannelInfo *ci, const Anope::string &cm u->SendMessage(bi, NO_HELP_AVAILABLE, cmd.c_str()); else { - u->SendMessage(bi->nick, " "); + u->SendMessage(bi, " "); /* Inform the user what permission is required to use the command */ if (!c->permission.empty()) diff --git a/src/ircd.cpp b/src/ircd.cpp deleted file mode 100644 index edab02be4..000000000 --- a/src/ircd.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* Main ircd 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. - */ - -#include "services.h" -#include "extern.h" - -IRCDProto *ircdproto; - -/** - * Globals we want from the protocol file - **/ -IRCDVar *ircd; - -void pmodule_ircd_proto(IRCDProto *proto) -{ - ircdproto = proto; -} - -/** - * Set routines for modules to set the prefered function for dealing with things. - **/ -void pmodule_ircd_var(IRCDVar *ircdvar) -{ - ircd = ircdvar; -} - diff --git a/src/messages.cpp b/src/messages.cpp index 945414f05..0f3e7f1a1 100644 --- a/src/messages.cpp +++ b/src/messages.cpp @@ -12,207 +12,7 @@ #include "services.h" #include "modules.h" -/*************************************************************************/ - -int m_nickcoll(const Anope::string &user) -{ - introduce_user(user); - return MOD_CONT; -} - -/*************************************************************************/ - -int m_away(const Anope::string &source, const Anope::string &msg) -{ - User *u = finduser(source); - - if (u && msg.empty()) /* un-away */ - check_memos(u); - return MOD_CONT; -} - -/*************************************************************************/ - -int m_kill(const Anope::string &nick, const Anope::string &msg) -{ - BotInfo *bi; - - /* Recover if someone kills us. */ - if (!Config->s_BotServ.empty() && (bi = findbot(nick))) - { - introduce_user(nick); - bi->RejoinAll(); - } - else - do_kill(nick, msg); - - return MOD_CONT; -} - -/*************************************************************************/ - -bool m_time(const Anope::string &source, const std::vector<Anope::string> &) -{ - if (source.empty()) - return MOD_CONT; - - time_t t; - time(&t); - struct tm *tm = localtime(&t); - char buf[64]; - strftime(buf, sizeof(buf), "%a %b %d %H:%M:%S %Y %Z", tm); - ircdproto->SendNumeric(Config->ServerName, 391, source, "%s :%s", Config->ServerName.c_str(), buf); - return MOD_CONT; -} - -/*************************************************************************/ - -int m_motd(const Anope::string &source) -{ - if (source.empty()) - return MOD_CONT; - - FILE *f = fopen(Config->MOTDFilename.c_str(), "r"); - if (f) - { - ircdproto->SendNumeric(Config->ServerName, 375, source, ":- %s Message of the Day", Config->ServerName.c_str()); - char buf[BUFSIZE]; - while (fgets(buf, sizeof(buf), f)) - { - buf[strlen(buf) - 1] = 0; - ircdproto->SendNumeric(Config->ServerName, 372, source, ":- %s", buf); - } - fclose(f); - ircdproto->SendNumeric(Config->ServerName, 376, source, ":End of /MOTD command."); - } - else - ircdproto->SendNumeric(Config->ServerName, 422, source, ":- MOTD file not found! Please contact your IRC administrator."); - return MOD_CONT; -} - -/*************************************************************************/ - -int m_privmsg(const Anope::string &source, const Anope::string &receiver, const Anope::string &message) -{ - if (source.empty() || receiver.empty() || message.empty()) - return MOD_CONT; - - User *u = finduser(source); - - if (!u) - { - Log() << message << ": user record for " << source << " not found"; - - BotInfo *bi = findbot(receiver); - if (bi) - ircdproto->SendMessage(bi, source, "%s", GetString(USER_RECORD_NOT_FOUND).c_str()); - - return MOD_CONT; - } - - if (receiver[0] == '#' && !Config->s_BotServ.empty()) - { - ChannelInfo *ci = cs_findchan(receiver); - if (ci) - { - /* Some paranoia checks */ - if (!ci->HasFlag(CI_FORBIDDEN) && ci->c && ci->bi) - botchanmsgs(u, ci, message); - } - } - else - { - /* Check if we should ignore. Operators always get through. */ - if (allow_ignore && !is_oper(u)) - { - if (get_ignore(source)) - { - Anope::string target = myStrGetToken(message, ' ', 0); - BotInfo *bi = findbot(target); - if (bi) - Log(bi) << "Ignored message from " << source << " using command " << target; - return MOD_CONT; - } - } - - /* If a server is specified (nick@server format), make sure it matches - * us, and strip it off. */ - Anope::string botname = receiver; - size_t s = receiver.find('@'); - if (s != Anope::string::npos) - { - Anope::string servername(receiver.begin() + s + 1, receiver.end()); - botname = botname.substr(0, s); - if (!servername.equals_ci(Config->ServerName)) - return MOD_CONT; - } - else if (Config->UseStrictPrivMsg) - { - BotInfo *bi = findbot(receiver); - if (!bi) - return MOD_CONT; - Log(LOG_DEBUG) << "Ignored PRIVMSG without @ from " << source; - u->SendMessage(bi, INVALID_TARGET, receiver.c_str(), receiver.c_str(), Config->ServerName.c_str(), receiver.c_str()); - return MOD_CONT; - } - - BotInfo *bi = findbot(botname); - - if (bi) - { - if (message[0] == '\1' && message[message.length() - 1] == '\1') - { - if (message.substr(0, 6).equals_ci("\1PING ")) - { - Anope::string buf = message; - buf.erase(buf.begin()); - buf.erase(buf.end() - 1); - ircdproto->SendCTCP(bi, u->nick, "%s", buf.c_str()); - } - else if (message.substr(0, 9).equals_ci("\1VERSION\1")) - { - ircdproto->SendCTCP(bi, u->nick, "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()); - } - } - if (bi == NickServ || bi == MemoServ || bi == BotServ) - mod_run_cmd(bi, u, message, false); - else if (bi == ChanServ) - { - if (!is_oper(u) && Config->CSOpersOnly) - u->SendMessage(ChanServ, ACCESS_DENIED); - else - mod_run_cmd(bi, u, message, false); - } - else if (bi == HostServ) - { - if (!ircd->vhost) - u->SendMessage(HostServ, SERVICE_OFFLINE, Config->s_HostServ.c_str()); - else - mod_run_cmd(bi, u, message, false); - } - else if (bi == OperServ) - { - if (!is_oper(u) && Config->OSOpersOnly) - { - u->SendMessage(OperServ, ACCESS_DENIED); - if (Config->WallBadOS) - ircdproto->SendGlobops(OperServ, "Denied access to %s from %s!%s@%s (non-oper)", Config->s_OperServ.c_str(), u->nick.c_str(), u->GetIdent().c_str(), u->host.c_str()); - } - else - { - Log(OperServ) << u->nick << ": " << message; - mod_run_cmd(bi, u, message, false); - } - } - } - } - - return MOD_CONT; -} - -/*************************************************************************/ - -bool m_stats(const Anope::string &source, const std::vector<Anope::string> ¶ms) +bool OnStats(const Anope::string &source, const std::vector<Anope::string> ¶ms) { if (params.size() < 1) return true; @@ -222,7 +22,7 @@ bool m_stats(const Anope::string &source, const std::vector<Anope::string> ¶ switch (params[0][0]) { case 'l': - if (u && is_oper(u)) + if (u && u->HasMode(UMODE_OPER)) { ircdproto->SendNumeric(Config->ServerName, 211, source, "Server SendBuf SentBytes SentMsgs RecvBuf RecvBytes RecvMsgs ConnTime"); ircdproto->SendNumeric(Config->ServerName, 211, source, "%s %d %d %d %d %d %d %ld", uplink_server->host.c_str(), UplinkSock->WriteBufferLen(), TotalWritten, -1, UplinkSock->ReadBufferLen(), TotalRead, -1, static_cast<long>(Anope::CurTime - start_time)); @@ -233,7 +33,7 @@ bool m_stats(const Anope::string &source, const std::vector<Anope::string> ¶ case 'o': case 'O': /* Check whether the user is an operator */ - if (u && !is_oper(u) && Config->HideStatsO) + if (u && !u->HasMode(UMODE_OPER) && Config->HideStatsO) ircdproto->SendNumeric(Config->ServerName, 219, source, "%c :End of /STATS report.", params[0][0]); else { @@ -269,45 +69,103 @@ bool m_stats(const Anope::string &source, const std::vector<Anope::string> ¶ return true; } -bool m_version(const Anope::string &source, const std::vector<Anope::string> &) +bool OnTime(const Anope::string &source, const std::vector<Anope::string> &) +{ + if (source.empty()) + return true; + + time_t t; + time(&t); + struct tm *tm = localtime(&t); + char buf[64]; + strftime(buf, sizeof(buf), "%a %b %d %H:%M:%S %Y %Z", tm); + ircdproto->SendNumeric(Config->ServerName, 391, source, "%s :%s", Config->ServerName.c_str(), buf); + return true; +} + +bool OnVersion(const Anope::string &source, const std::vector<Anope::string> &) { if (!source.empty()) ircdproto->SendNumeric(Config->ServerName, 351, source, "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()); - return MOD_CONT; + return true; } -/*************************************************************************/ - -int m_whois(const Anope::string &source, const Anope::string &who) +/* XXX We should cache the file somewhere not open/read/close it on every request */ +bool OnMotd(const Anope::string &source, const std::vector<Anope::string> &) { - if (!source.empty() && !who.empty()) + if (source.empty()) + return true; + + FILE *f = fopen(Config->MOTDFilename.c_str(), "r"); + if (f) { - User *u; - BotInfo *bi = findbot(who); - if (bi) - { - ircdproto->SendNumeric(Config->ServerName, 311, source, "%s %s %s * :%s", bi->nick.c_str(), bi->GetIdent().c_str(), bi->host.c_str(), bi->realname.c_str()); - ircdproto->SendNumeric(Config->ServerName, 307, source, "%s :is a registered nick", bi->nick.c_str()); - ircdproto->SendNumeric(Config->ServerName, 312, source, "%s %s :%s", bi->nick.c_str(), Config->ServerName.c_str(), Config->ServerDesc.c_str()); - ircdproto->SendNumeric(Config->ServerName, 317, source, "%s %ld %ld :seconds idle, signon time", bi->nick.c_str(), static_cast<long>(Anope::CurTime - bi->lastmsg), static_cast<long>(start_time)); - ircdproto->SendNumeric(Config->ServerName, 318, source, "%s :End of /WHOIS list.", who.c_str()); - } - else if (!ircd->svshold && (u = finduser(who)) && u->server == Me) + ircdproto->SendNumeric(Config->ServerName, 375, source, ":- %s Message of the Day", Config->ServerName.c_str()); + char buf[BUFSIZE]; + while (fgets(buf, sizeof(buf), f)) { - ircdproto->SendNumeric(Config->ServerName, 311, source, "%s %s %s * :%s", u->nick.c_str(), u->GetIdent().c_str(), u->host.c_str(), u->realname.c_str()); - ircdproto->SendNumeric(Config->ServerName, 312, source, "%s %s :%s", u->nick.c_str(), Config->ServerName.c_str(), Config->ServerDesc.c_str()); - ircdproto->SendNumeric(Config->ServerName, 318, source, "%s :End of /WHOIS list.", u->nick.c_str()); + buf[strlen(buf) - 1] = 0; + ircdproto->SendNumeric(Config->ServerName, 372, source, ":- %s", buf); } - else - ircdproto->SendNumeric(Config->ServerName, 401, source, "%s :No such service.", who.c_str()); + fclose(f); + ircdproto->SendNumeric(Config->ServerName, 376, source, ":End of /MOTD command."); } - return MOD_CONT; + else + ircdproto->SendNumeric(Config->ServerName, 422, source, ":- MOTD file not found! Please contact your IRC administrator."); + + return true; } +#define ProtocolFunc(x) \ + inline bool x(const Anope::string &source, const std::vector<Anope::string> ¶ms) \ + { \ + return ircdmessage->x(source, params); \ + } + +ProtocolFunc(On436) +ProtocolFunc(OnAway) +ProtocolFunc(OnJoin) +ProtocolFunc(OnKick) +ProtocolFunc(OnKill) +ProtocolFunc(OnMode) +ProtocolFunc(OnNick) +ProtocolFunc(OnUID) +ProtocolFunc(OnPart) +ProtocolFunc(OnPing) +ProtocolFunc(OnPrivmsg) +ProtocolFunc(OnQuit) +ProtocolFunc(OnServer) +ProtocolFunc(OnSQuit) +ProtocolFunc(OnTopic) +ProtocolFunc(OnWhois) +ProtocolFunc(OnCapab) +ProtocolFunc(OnSJoin) +ProtocolFunc(OnError) + void init_core_messages() { - static Message message_stats("STATS", m_stats); - static Message message_time("TIME", m_time); - static Message message_verssion("VERSION", m_version); + static Message message_stats("STATS", OnStats); + static Message message_time("TIME", OnTime); + static Message message_verssion("VERSION", OnVersion); + static Message message_motd("MOTD", OnMotd); + + static Message message_436("436", On436); + static Message message_away("AWAY", OnAway); + static Message message_join("JOIN", OnJoin); + static Message message_kick("KICK", OnKick); + static Message message_kill("KILL", OnKill); + static Message message_mode("MODE", OnMode); + static Message message_nick("NICK", OnNick); + static Message message_uid("UID", OnUID); + static Message message_part("PART", OnPart); + static Message message_ping("PING", OnPing); + static Message message_privmsg("PRIVMSG", OnPrivmsg); + static Message message_quit("QUIT", OnQuit); + static Message message_server("SERVER", OnServer); + static Message message_squit("SQUIT", OnSQuit); + static Message message_topic("TOPIC", OnTopic); + static Message message_whois("WHOIS", OnWhois); + static Message message_capab("CAPAB", OnCapab); + static Message message_sjoin("SJOIN", OnSJoin); + static Message message_error("ERROR", OnError); } diff --git a/src/misc.cpp b/src/misc.cpp index c885188f8..51899270b 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -70,68 +70,6 @@ int tolower(char c) /*************************************************************************/ /** - * strscpy: Copy at most len-1 characters from a string to a buffer, and - * add a null terminator after the last character copied. - * @param d Buffer to copy into - * @param s Data to copy int - * @param len Length of data - * @return updated buffer - */ -char *strscpy(char *d, const char *s, size_t len) -{ - char *d_orig = d; - - if (!len) - return d; - while (--len && (*d++ = *s++)); - *d = '\0'; - return d_orig; -} - -/*************************************************************************/ - -/** - * strnrepl: Replace occurrences of `old' with `new' in string `s'. Stop - * replacing if a replacement would cause the string to exceed - * `size' bytes (including the null terminator). Return the - * string. - * @param s String - * @param size size of s - * @param old character to replace - * @param newstr character to replace with - * @return updated s - */ -char *strnrepl(char *s, int32 size, const char *old, const char *newstr) -{ - char *ptr = s; - int32 left = strlen(s); - int32 avail = size - (left + 1); - int32 oldlen = strlen(old); - int32 newlen = strlen(newstr); - int32 diff = newlen - oldlen; - - while (left >= oldlen) - { - if (strncmp(ptr, old, oldlen)) - { - --left; - ++ptr; - continue; - } - if (diff > avail) - break; - if (diff) - memmove(ptr + oldlen + diff, ptr + oldlen, left + 1 - oldlen); - strncpy(ptr, newstr, newlen); - ptr += newlen; - left -= oldlen; - } - return s; -} - -/*************************************************************************/ - -/** * merge_args: Take an argument count and argument vector and merge them * into a single string in which each argument is separated by * a space. @@ -576,7 +514,7 @@ void EnforceQlinedNick(const Anope::string &nick, const Anope::string &killer) if (u2) { Log(LOG_NORMAL, "xline") << "Killed Q-lined nick: " << u2->GetMask(); - kill_user(killer, u2->nick, "This nick is reserved for Services. Please use a non Q-Lined nick."); + kill_user(killer, u2, "This nick is reserved for Services. Please use a non Q-Lined nick."); } } diff --git a/src/modes.cpp b/src/modes.cpp index 7439c852c..1daea86b3 100644 --- a/src/modes.cpp +++ b/src/modes.cpp @@ -256,7 +256,7 @@ bool ChannelModeKey::IsValid(const Anope::string &value) const */ bool ChannelModeAdmin::CanSet(User *u) const { - if (u && is_oper(u)) + if (u && u->HasMode(UMODE_OPER)) return true; return false; @@ -268,7 +268,7 @@ bool ChannelModeAdmin::CanSet(User *u) const */ bool ChannelModeOper::CanSet(User *u) const { - if (u && is_oper(u)) + if (u && u->HasMode(UMODE_OPER)) return true; return false; diff --git a/src/operserv.cpp b/src/operserv.cpp index e7de407bd..911384e79 100644 --- a/src/operserv.cpp +++ b/src/operserv.cpp @@ -587,8 +587,8 @@ XLine *SNLineManager::Add(BotInfo *bi, User *u, const Anope::string &mask, time_ User *user = *it; ++it; - if (!is_oper(user) && Anope::Match(user->realname, x->Mask)) - kill_user(Config->ServerName, user->nick, rreason); + if (!user->HasMode(UMODE_OPER) && Anope::Match(user->realname, x->Mask)) + kill_user(Config->ServerName, user, rreason); } } @@ -605,7 +605,7 @@ void SNLineManager::OnMatch(User *u, XLine *x) ircdproto->SendSGLine(x); Anope::string reason = "G-Lined: " + x->Reason; - kill_user(Config->s_OperServ, u->nick, reason); + kill_user(Config->s_OperServ, u, reason); } void SNLineManager::OnExpire(XLine *x) @@ -675,7 +675,7 @@ XLine *SQLineManager::Add(BotInfo *bi, User *u, const Anope::string &mask, time_ UserContainer *uc = *it; ++it; - if (is_oper(uc->user)) + if (uc->user->HasMode(UMODE_OPER)) continue; c->Kick(NULL, uc->user, "%s", reason.c_str()); } @@ -688,8 +688,8 @@ XLine *SQLineManager::Add(BotInfo *bi, User *u, const Anope::string &mask, time_ User *user = *it; ++it; - if (!is_oper(user) && Anope::Match(user->nick, x->Mask)) - kill_user(Config->ServerName, user->nick, rreason); + if (!user->HasMode(UMODE_OPER) && Anope::Match(user->nick, x->Mask)) + kill_user(Config->ServerName, user, rreason); } } } @@ -709,7 +709,7 @@ void SQLineManager::OnMatch(User *u, XLine *x) ircdproto->SendSQLine(x); Anope::string reason = "Q-Lined: " + x->Reason; - kill_user(Config->s_OperServ, u->nick, reason); + kill_user(Config->s_OperServ, u, reason); } void SQLineManager::OnExpire(XLine *x) diff --git a/src/process.cpp b/src/process.cpp index 285c4ae6b..4a7811c69 100644 --- a/src/process.cpp +++ b/src/process.cpp @@ -101,7 +101,7 @@ IgnoreData *get_ignore(const Anope::string &nick) if (u) { /* Opers are not ignored, even if a matching entry may be present. */ - if (is_oper(u)) + if (u->HasMode(UMODE_OPER)) return NULL; for (; ign != ign_end; ++ign) if (match_usermask((*ign)->mask, u)) diff --git a/src/protocol.cpp b/src/protocol.cpp index 545824681..cc4112970 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -1,4 +1,24 @@ #include "services.h" +#include "modules.h" + +IRCDProto *ircdproto; +IRCDVar *ircd; +IRCdMessage *ircdmessage; + +void pmodule_ircd_proto(IRCDProto *proto) +{ + ircdproto = proto; +} + +void pmodule_ircd_var(IRCDVar *ircdvar) +{ + ircd = ircdvar; +} + +void pmodule_ircd_message(IRCdMessage *message) +{ + ircdmessage = message; +} void IRCDProto::SendMessageInternal(const BotInfo *bi, const Anope::string &dest, const Anope::string &buf) { @@ -269,3 +289,312 @@ bool IRCDProto::IsChannelValid(const Anope::string &chan) return true; } + +bool IRCdMessage::On436(const Anope::string &, const std::vector<Anope::string> ¶ms) +{ + if (!params.empty()) + introduce_user(params[0]); + return true; +} + +bool IRCdMessage::OnAway(const Anope::string &source, const std::vector<Anope::string> ¶ms) +{ + User *u = finduser(source); + if (u && params.empty()) /* un-away */ + check_memos(u); + return true; +} + +bool IRCdMessage::OnJoin(const Anope::string &source, const std::vector<Anope::string> ¶ms) +{ + if (!params.empty()) + do_join(source, params[0], params.size() > 1 ? params[1] : ""); + return true; +} + +bool IRCdMessage::OnKick(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; +} + +/** Called on KILL + * @params[0] The nick + * @params[1] The reason + */ +bool IRCdMessage::OnKill(const Anope::string &source, const std::vector<Anope::string> ¶ms) +{ + User *u = finduser(params[0]); + BotInfo *bi; + + if (!u) + return true; + + /* Recover if someone kills us. */ + if (!Config->s_BotServ.empty() && u->server == Me && (bi = dynamic_cast<BotInfo *>(u))) + { + introduce_user(bi->nick); + bi->RejoinAll(); + } + else + do_kill(u, params[1]); + + + return true; +} + +bool IRCdMessage::OnUID(const Anope::string &source, const std::vector<Anope::string> ¶ms) +{ + return true; +} + +bool IRCdMessage::OnPart(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 IRCdMessage::OnPing(const Anope::string &, const std::vector<Anope::string> ¶ms) +{ + if (!params.empty()) + ircdproto->SendPong(params.size() > 1 ? params[1] : Config->ServerName, params[0]); + return true; +} + +bool IRCdMessage::OnPrivmsg(const Anope::string &source, const std::vector<Anope::string> ¶ms) +{ + const Anope::string &receiver = params.size() > 0 ? params[0] : ""; + const Anope::string &message = params.size() > 1 ? params[1] : ""; + + /* Messages from servers can happen on some IRCds, check for . */ + if (source.empty() || receiver.empty() || message.empty() || source.find('.') != Anope::string::npos) + return true; + + User *u = finduser(source); + + if (!u) + { + Log() << message << ": user record for " << source << " not found"; + + BotInfo *bi = findbot(receiver); + if (bi) + ircdproto->SendMessage(bi, source, "%s", GetString(USER_RECORD_NOT_FOUND).c_str()); + + return MOD_CONT; + } + + if (receiver[0] == '#' && !Config->s_BotServ.empty()) + { + ChannelInfo *ci = cs_findchan(receiver); + /* Some paranoia checks */ + if (ci && !ci->HasFlag(CI_FORBIDDEN) && ci->c && ci->bi) + botchanmsgs(u, ci, message); + } + else + { + /* Check if we should ignore. Operators always get through. */ + if (allow_ignore && !u->HasMode(UMODE_OPER)) + { + if (get_ignore(source)) + { + Anope::string target = myStrGetToken(message, ' ', 0); + BotInfo *bi = findbot(target); + if (bi) + Log(bi) << "Ignored message from " << source << " using command " << target; + return MOD_CONT; + } + } + + /* If a server is specified (nick@server format), make sure it matches + * us, and strip it off. */ + Anope::string botname = receiver; + size_t s = receiver.find('@'); + if (s != Anope::string::npos) + { + Anope::string servername(receiver.begin() + s + 1, receiver.end()); + botname = botname.substr(0, s); + if (!servername.equals_ci(Config->ServerName)) + return MOD_CONT; + } + else if (Config->UseStrictPrivMsg) + { + BotInfo *bi = findbot(receiver); + if (!bi) + return MOD_CONT; + Log(LOG_DEBUG) << "Ignored PRIVMSG without @ from " << source; + u->SendMessage(bi, INVALID_TARGET, receiver.c_str(), receiver.c_str(), Config->ServerName.c_str(), receiver.c_str()); + return MOD_CONT; + } + + BotInfo *bi = findbot(botname); + + if (bi) + { + if (message[0] == '\1' && message[message.length() - 1] == '\1') + { + if (message.substr(0, 6).equals_ci("\1PING ")) + { + Anope::string buf = message; + buf.erase(buf.begin()); + buf.erase(buf.end() - 1); + ircdproto->SendCTCP(bi, u->nick, "%s", buf.c_str()); + } + else if (message.substr(0, 9).equals_ci("\1VERSION\1")) + { + ircdproto->SendCTCP(bi, u->nick, "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()); + } + } + else if (bi == ChanServ) + { + if (!u->HasMode(UMODE_OPER) && Config->CSOpersOnly) + u->SendMessage(ChanServ, ACCESS_DENIED); + else + mod_run_cmd(bi, u, message, false); + } + else if (bi == HostServ) + { + if (!ircd->vhost) + u->SendMessage(HostServ, SERVICE_OFFLINE, Config->s_HostServ.c_str()); + else + mod_run_cmd(bi, u, message, false); + } + else if (bi == OperServ) + { + if (!u->HasMode(UMODE_OPER) && Config->OSOpersOnly) + { + u->SendMessage(OperServ, ACCESS_DENIED); + if (Config->WallBadOS) + ircdproto->SendGlobops(OperServ, "Denied access to %s from %s!%s@%s (non-oper)", Config->s_OperServ.c_str(), u->nick.c_str(), u->GetIdent().c_str(), u->host.c_str()); + } + else + { + Log(OperServ) << u->nick << ": " << message; + mod_run_cmd(bi, u, message, false); + } + } + else + mod_run_cmd(bi, u, message, false); + } + } + + return true; +} + +bool IRCdMessage::OnQuit(const Anope::string &source, const std::vector<Anope::string> ¶ms) +{ + const Anope::string &reason = !params.empty() ? params[0] : ""; + User *user = finduser(source); + if (!user) + { + Log() << "user: QUIT from nonexistent user " << source << " (" << reason << ")"; + return true; + } + + Log(user, "quit") << "quit (Reason: " << (!reason.empty() ? reason : "no reason") << ")"; + + NickAlias *na = findnick(user->nick); + if (na && !na->HasFlag(NS_FORBIDDEN) && !na->nc->HasFlag(NI_SUSPENDED) && (user->IsRecognized() || user->IsIdentified(true))) + { + na->last_seen = Anope::CurTime; + na->last_quit = reason; + } + FOREACH_MOD(I_OnUserQuit, OnUserQuit(user, reason)); + delete user; + + return true; +} + +bool IRCdMessage::OnSQuit(const Anope::string &source, const std::vector<Anope::string> ¶ms) +{ + const Anope::string &server = source; + + Server *s = Server::Find(server); + + if (!s) + { + Log() << "SQUIT for nonexistent server " << server; + return true; + } + + FOREACH_MOD(I_OnServerQuit, OnServerQuit(s)); + + Anope::string buf; + /* If this is a juped server, send a nice global to inform the online + * opers that we received it. + */ + if (s->HasFlag(SERVER_JUPED)) + { + buf = "Received SQUIT for juped server " + s->GetName(); + ircdproto->SendGlobops(OperServ, "%s", buf.c_str()); + } + + buf = s->GetName() + " " + s->GetUplink()->GetName(); + + if (s->GetUplink() == Me && Capab.HasFlag(CAPAB_UNCONNECT)) + { + Log(LOG_DEBUG) << "Sending UNCONNECT SQUIT for " << s->GetName(); + /* need to fix */ + ircdproto->SendSquit(s->GetName(), buf); + } + + s->Delete(buf); + + return true; +} + +bool IRCdMessage::OnWhois(const Anope::string &source, const std::vector<Anope::string> ¶ms) +{ + const Anope::string &who = params[0]; + + if (!source.empty() && !who.empty()) + { + User *u; + BotInfo *bi = findbot(who); + if (bi) + { + ircdproto->SendNumeric(Config->ServerName, 311, source, "%s %s %s * :%s", bi->nick.c_str(), bi->GetIdent().c_str(), bi->host.c_str(), bi->realname.c_str()); + ircdproto->SendNumeric(Config->ServerName, 307, source, "%s :is a registered nick", bi->nick.c_str()); + ircdproto->SendNumeric(Config->ServerName, 312, source, "%s %s :%s", bi->nick.c_str(), Config->ServerName.c_str(), Config->ServerDesc.c_str()); + ircdproto->SendNumeric(Config->ServerName, 317, source, "%s %ld %ld :seconds idle, signon time", bi->nick.c_str(), static_cast<long>(Anope::CurTime - bi->lastmsg), static_cast<long>(start_time)); + ircdproto->SendNumeric(Config->ServerName, 318, source, "%s :End of /WHOIS list.", who.c_str()); + } + else if (!ircd->svshold && (u = finduser(who)) && u->server == Me) + { + ircdproto->SendNumeric(Config->ServerName, 311, source, "%s %s %s * :%s", u->nick.c_str(), u->GetIdent().c_str(), u->host.c_str(), u->realname.c_str()); + ircdproto->SendNumeric(Config->ServerName, 312, source, "%s %s :%s", u->nick.c_str(), Config->ServerName.c_str(), Config->ServerDesc.c_str()); + ircdproto->SendNumeric(Config->ServerName, 318, source, "%s :End of /WHOIS list.", u->nick.c_str()); + } + else + ircdproto->SendNumeric(Config->ServerName, 401, source, "%s :No such service.", who.c_str()); + } + + return true; +} + +bool IRCdMessage::OnCapab(const Anope::string &, const std::vector<Anope::string> ¶ms) +{ + for (unsigned i = 0; i < params.size(); ++i) + { + for (unsigned j = 0; !Capab_Info[j].Token.empty(); ++j) + { + if (Capab_Info[j].Token.equals_ci(params[i])) + { + Capab.SetFlag(Capab_Info[j].Flag); + break; + } + } + } + + return true; +} + +bool IRCdMessage::OnError(const Anope::string &, const std::vector<Anope::string> ¶ms) +{ + if (!params.empty()) + Log(LOG_DEBUG) << params[0]; + + return true; +} + diff --git a/src/regchannel.cpp b/src/regchannel.cpp index e89bbee5c..1932da4e8 100644 --- a/src/regchannel.cpp +++ b/src/regchannel.cpp @@ -729,7 +729,7 @@ bool ChannelInfo::CheckKick(User *user) do_kick = true; Anope::string mask, reason; - if (!is_oper(user) && (this->HasFlag(CI_SUSPENDED) || this->HasFlag(CI_FORBIDDEN))) + if (!user->HasMode(UMODE_OPER) && (this->HasFlag(CI_SUSPENDED) || this->HasFlag(CI_FORBIDDEN))) { get_idealban(this, user, mask); reason = this->forbidreason.empty() ? GetString(user, CHAN_MAY_NOT_BE_USED) : this->forbidreason; diff --git a/src/servers.cpp b/src/servers.cpp index f7bef6ec7..dc5dc4cf0 100644 --- a/src/servers.cpp +++ b/src/servers.cpp @@ -349,67 +349,6 @@ void do_server(const Anope::string &source, const Anope::string &servername, uns /*************************************************************************/ -/** - * Handle removing the server from the Server struct - * @param source Name of the server sending the squit - * @param server Name of the server leaving - * @return void - */ -void do_squit(const Anope::string &source, const Anope::string &server) -{ - Server *s = Server::Find(server); - - if (!s) - { - Log() << "SQUIT for nonexistent server " << server; - return; - } - - FOREACH_MOD(I_OnServerQuit, OnServerQuit(s)); - - Anope::string buf; - /* If this is a juped server, send a nice global to inform the online - * opers that we received it. - */ - if (s->HasFlag(SERVER_JUPED)) - { - buf = "Received SQUIT for juped server " + s->GetName(); - ircdproto->SendGlobops(OperServ, "%s", buf.c_str()); - } - - buf = s->GetName() + " " + s->GetUplink()->GetName(); - - if (s->GetUplink() == Me && Capab.HasFlag(CAPAB_UNCONNECT)) - { - Log(LOG_DEBUG) << "Sending UNCONNECT SQUIT for " << s->GetName(); - /* need to fix */ - ircdproto->SendSquit(s->GetName(), buf); - } - - s->Delete(buf); -} - -/*************************************************************************/ - -/** Handle parsing the CAPAB/PROTOCTL messages - */ -void CapabParse(const std::vector<Anope::string> ¶ms) -{ - for (unsigned i = 0; i < params.size(); ++i) - { - for (unsigned j = 0; !Capab_Info[j].Token.empty(); ++j) - { - if (Capab_Info[j].Token.equals_ci(params[i])) - { - Capab.SetFlag(Capab_Info[j].Flag); - break; - } - } - } -} - -/*************************************************************************/ - /* TS6 UID generator common code. * * Derived from atheme-services, uid.c (hg 2954:116d46894b4c). diff --git a/src/sessions.cpp b/src/sessions.cpp index a90364160..a6032b572 100644 --- a/src/sessions.cpp +++ b/src/sessions.cpp @@ -91,9 +91,10 @@ Session *findsession(const Anope::string &host) * causes the the session limit to be exceeded, kill the connecting user. */ -void add_session(const Anope::string &nick, const Anope::string &host, const Anope::string &hostip) +void add_session(User *u) { - Session *session = findsession(host); + const Anope::string &hostip = u->ip() ? u->ip.addr() : ""; + Session *session = findsession(u->host); if (session) { @@ -101,7 +102,7 @@ void add_session(const Anope::string &nick, const Anope::string &host, const Ano if (Config->DefSessionLimit && session->count >= Config->DefSessionLimit) { kill = true; - Exception *exception = find_hostip_exception(host, hostip); + Exception *exception = find_hostip_exception(u->host, hostip); if (exception) { kill = false; @@ -113,9 +114,9 @@ void add_session(const Anope::string &nick, const Anope::string &host, const Ano if (kill) { if (!Config->SessionLimitExceeded.empty()) - ircdproto->SendMessage(OperServ, nick, Config->SessionLimitExceeded.c_str(), host.c_str()); + u->SendMessage(OperServ, Config->SessionLimitExceeded.c_str(), u->host.c_str()); if (!Config->SessionLimitDetailsLoc.empty()) - ircdproto->SendMessage(OperServ, nick, "%s", Config->SessionLimitDetailsLoc.c_str()); + u->SendMessage(OperServ, "%s", Config->SessionLimitDetailsLoc.c_str()); /* Previously on IRCds that send a QUIT (InspIRCD) when a user is killed, the session for a host was * decremented in do_quit, which caused problems and fixed here @@ -125,12 +126,12 @@ void add_session(const Anope::string &nick, const Anope::string &host, const Ano * decremented in do_kill or in do_quit - Adam */ ++session->count; - kill_user(Config->s_OperServ, nick, "Session limit exceeded"); + kill_user(Config->s_OperServ, u, "Session limit exceeded"); ++session->hits; if (Config->MaxSessionKill && session->hits >= Config->MaxSessionKill && SGLine) { - Anope::string akillmask = "*@" + host; + const Anope::string &akillmask = "*@" + u->host; XLine *x = new XLine(akillmask, Config->s_OperServ, Anope::CurTime + Config->SessionAutoKillExpiry, "Session limit exceeded"); SGLine->AddXLine(x); ircdproto->SendGlobops(OperServ, "Added a temporary AKILL for \2%s\2 due to excessive connections", akillmask.c_str()); @@ -144,7 +145,7 @@ void add_session(const Anope::string &nick, const Anope::string &host, const Ano else { session = new Session(); - session->host = host; + session->host = u->host; session->count = 1; session->hits = 0; @@ -152,7 +153,7 @@ void add_session(const Anope::string &nick, const Anope::string &host, const Ano } } -void del_session(const Anope::string &host) +void del_session(User *u) { if (!Config->LimitSessions) { @@ -160,7 +161,7 @@ void del_session(const Anope::string &host) return; } - if (host.empty()) + if (!u) { Log(LOG_DEBUG) << "del_session called with NULL values"; return; @@ -168,14 +169,14 @@ void del_session(const Anope::string &host) Log(LOG_DEBUG_2) << "del_session() called"; - Session *session = findsession(host); + Session *session = findsession(u->host); if (!session) { if (debug) { - ircdproto->SendGlobops(OperServ, "WARNING: Tried to delete non-existant session: \2%s", host.c_str()); - Log() << "session: Tried to delete non-existant session: " << host; + ircdproto->SendGlobops(OperServ, "WARNING: Tried to delete non-existant session: \2%s", u->host.c_str()); + Log() << "session: Tried to delete non-existant session: " << u->host; } return; } @@ -188,8 +189,6 @@ void del_session(const Anope::string &host) SessionList.erase(session->host); - Log(LOG_DEBUG_2) << "del_session(): free session structure"; - delete session; Log(LOG_DEBUG_2) << "del_session() done"; diff --git a/src/users.cpp b/src/users.cpp index f6c0983ef..0290e9efb 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -198,14 +198,14 @@ User::~User() --usercnt; - if (is_oper(this)) + if (this->HasMode(UMODE_OPER)) --opcnt; while (!this->chans.empty()) this->chans.front()->chan->DeleteUser(this); if (Config->LimitSessions && !this->server->IsULined()) - del_session(this->host); + del_session(this); UserListByNick.erase(this->nick); if (!this->uid.empty()) @@ -218,7 +218,7 @@ User::~User() Log(LOG_DEBUG_2) << "User::~User() done"; } -void User::SendMessage(const Anope::string &source, const char *fmt, ...) +void User::SendMessage(BotInfo *source, const char *fmt, ...) { va_list args; char buf[BUFSIZE] = ""; @@ -234,7 +234,7 @@ void User::SendMessage(const Anope::string &source, const char *fmt, ...) } } -void User::SendMessage(const Anope::string &source, const Anope::string &msg) +void User::SendMessage(BotInfo *source, const Anope::string &msg) { /* Send privmsg instead of notice if: * - UsePrivmsg is enabled @@ -242,9 +242,9 @@ void User::SendMessage(const Anope::string &source, const Anope::string &msg) * - The user is registered and has set /ns set msg on */ if (Config->UsePrivmsg && ((!this->nc && Config->NSDefFlags.HasFlag(NI_MSG)) || (this->nc && this->nc->HasFlag(NI_MSG)))) - ircdproto->SendPrivmsg(findbot(source), this->nick, "%s", msg.c_str()); + ircdproto->SendPrivmsg(source, this->nick, "%s", msg.c_str()); else - ircdproto->SendNotice(findbot(source), this->nick, "%s", msg.c_str()); + ircdproto->SendNotice(source, this->nick, "%s", msg.c_str()); } void User::SendMessage(BotInfo *source, LanguageString message, ...) @@ -272,7 +272,7 @@ void User::SendMessage(BotInfo *source, LanguageString message, ...) Anope::string line; while (sep.GetToken(line)) - this->SendMessage(source->nick, line.empty() ? " " : line); + this->SendMessage(source, line.empty() ? " " : line); } /** Collides a nick. @@ -349,7 +349,7 @@ void User::Collide(NickAlias *na) ircdproto->SendForceNickChange(this, guestnick, Anope::CurTime); } else - kill_user(Config->s_NickServ, this->nick, "Services nickname-enforcer kill"); + kill_user(Config->s_NickServ, this, "Services nickname-enforcer kill"); } /** Login the user to a NickCore @@ -757,7 +757,7 @@ User *do_nick(const Anope::string &source, const Anope::string &nick, const Anop if (user && MOD_RESULT != EVENT_STOP) { if (Config->LimitSessions && !serv->IsULined()) - add_session(nick, host, user->ip() ? user->ip.addr() : ""); + add_session(*user); if (!user) return NULL; @@ -828,7 +828,7 @@ User *do_nick(const Anope::string &source, const Anope::string &nick, const Anop if (ircd->sqline) { - if (!is_oper(user) && SQLine->Check(user)) + if (user->HasMode(UMODE_OPER) && SQLine->Check(user)) return NULL; } } @@ -855,47 +855,13 @@ void do_umode(const Anope::string &, const Anope::string &user, const Anope::str /*************************************************************************/ -/** Handle a QUIT command. - * @param source User quitting - * @param reason Quit reason - */ -void do_quit(const Anope::string &source, const Anope::string &reason) -{ - User *user = finduser(source); - if (!user) - { - Log() << "user: QUIT from nonexistent user " << source << " (" << reason << ")"; - return; - } - - Log(user, "quit") << "quit (Reason: " << (!reason.empty() ? reason : "no reason") << ")"; - - NickAlias *na = findnick(user->nick); - if (na && !na->HasFlag(NS_FORBIDDEN) && !na->nc->HasFlag(NI_SUSPENDED) && (user->IsRecognized() || user->IsIdentified(true))) - { - na->last_seen = Anope::CurTime; - na->last_quit = reason; - } - FOREACH_MOD(I_OnUserQuit, OnUserQuit(user, reason)); - delete user; -} - -/*************************************************************************/ /* Handle a KILL command. - * av[0] = nick being killed - * av[1] = reason + * @param user the user being killed + * @param msg why */ - -void do_kill(const Anope::string &nick, const Anope::string &msg) +void do_kill(User *user, const Anope::string &msg) { - User *user = finduser(nick); - if (!user) - { - Log() << "KILL of nonexistent nick: " << nick; - return; - } - Log(user, "killed") << "was killed (Reason: " << msg << ")"; NickAlias *na = findnick(user->nick); @@ -910,16 +876,6 @@ void do_kill(const Anope::string &nick, const Anope::string &msg) /*************************************************************************/ /*************************************************************************/ -/* Is the given nick an oper? */ - -bool is_oper(User *user) -{ - return user && user->HasMode(UMODE_OPER); -} - -/*************************************************************************/ -/*************************************************************************/ - /* Is the given user ban-excepted? */ bool is_excepted(ChannelInfo *ci, User *user) { |