diff options
author | Adam <Adam@anope.org> | 2012-10-01 01:56:57 -0400 |
---|---|---|
committer | Adam <Adam@anope.org> | 2012-10-01 01:56:57 -0400 |
commit | 89428a9d1032e3c2a6e397629a32862b3e58d708 (patch) | |
tree | d507904b3fa1cc084f0f3e688c839bcdd47f79d7 | |
parent | b937d6310d9a7c0e2434200306b63d513cb2ae61 (diff) |
Cleanup of all of the protocol modules, rewrote message handling system to be a bit more C++ ish
52 files changed, 2664 insertions, 2998 deletions
diff --git a/include/anope.h b/include/anope.h index e67fafc8d..3c13d68ab 100644 --- a/include/anope.h +++ b/include/anope.h @@ -324,12 +324,6 @@ namespace Anope */ extern CoreExport bool Match(const string &str, const string &mask, bool case_sensitive = false, bool use_regex = false); - /** Find a message in the message table - * @param name The name of the message were looking for - * @return NULL if we cant find it, or a pointer to the Message if we can - */ - extern CoreExport std::vector<Message *> FindMessage(const string &name); - /** Converts a string to hex * @param the data to be converted * @return a anope::string containing the hex value diff --git a/include/channels.h b/include/channels.h index b64ae84f4..7dee744c2 100644 --- a/include/channels.h +++ b/include/channels.h @@ -140,7 +140,7 @@ class CoreExport Channel : public virtual Base, public Extensible, public Flags< * @param param The param * @param EnforceMLock true if mlocks should be enforced, false to override mlock */ - void SetModeInternal(User *setter, ChannelMode *cm, const Anope::string ¶m = "", bool EnforceMLock = true); + void SetModeInternal(MessageSource &source, ChannelMode *cm, const Anope::string ¶m = "", bool EnforceMLock = true); /** Remove a mode internally on a channel, this is not sent out to the IRCd * @param setter The Setter @@ -148,7 +148,7 @@ class CoreExport Channel : public virtual Base, public Extensible, public Flags< * @param param The param * @param EnforceMLock true if mlocks should be enforced, false to override mlock */ - void RemoveModeInternal(User *setter, ChannelMode *cm, const Anope::string ¶m = "", bool EnforceMLock = true); + void RemoveModeInternal(MessageSource &source, ChannelMode *cm, const Anope::string ¶m = "", bool EnforceMLock = true); /** Set a mode on a channel * @param bi The client setting the modes @@ -199,18 +199,18 @@ class CoreExport Channel : public virtual Base, public Extensible, public Flags< void SetModes(BotInfo *bi, bool EnforceMLock, const char *cmodes, ...); /** Set a string of modes internally on a channel - * @param setter the setter (if it is a user) + * @param source The setter * @param mode the modes * @param EnforceMLock true to enforce mlock */ - void SetModesInternal(User *setter, const Anope::string &mode, bool EnforceMLock = true); + void SetModesInternal(MessageSource &source, const Anope::string &mode, time_t ts = Anope::CurTime, bool EnforceMLock = true); /** Kick a user from a channel internally * @param source The sender of the kick * @param nick The nick being kicked * @param reason The reason for the kick */ - void KickInternal(const Anope::string &source, const Anope::string &nick, const Anope::string &reason); + void KickInternal(MessageSource &source, const Anope::string &nick, const Anope::string &reason); /** Kick a user from the channel * @param bi The sender, can be NULL for the service bot for this channel @@ -228,7 +228,7 @@ class CoreExport Channel : public virtual Base, public Extensible, public Flags< Anope::string GetModes(bool complete, bool plus); /** Update the topic of the channel internally, and reset it if topiclock etc says to - * @param user THe user setting the new topic + * @param user The user setting the new topic * @param newtopic The new topic * @param ts The time the new topic is being set */ @@ -250,11 +250,6 @@ extern CoreExport Channel *findchan(const Anope::string &chan); extern CoreExport User *nc_on_chan(Channel *c, const NickCore *nc); -extern CoreExport void do_cmode(const Anope::string &source, const Anope::string &channel, const Anope::string &modes, const Anope::string &ts); -extern CoreExport void do_join(const Anope::string &source, const Anope::string &channels, const Anope::string &ts); -extern CoreExport void do_kick(const Anope::string &source, const Anope::string &channel, const Anope::string &users, const Anope::string &reason); -extern CoreExport void do_part(const Anope::string &source, const Anope::string &channels, const Anope::string &reason); - extern CoreExport void chan_set_correct_modes(const User *user, Channel *c, int give_modes, bool check_noop); #endif // CHANNELS_H diff --git a/include/defs.h b/include/defs.h index 2df0a2c15..d58f7fed6 100644 --- a/include/defs.h +++ b/include/defs.h @@ -49,6 +49,7 @@ struct BadWord; struct DNSQuery; struct Exception; struct MemoInfo; +struct MessageSource; struct ModeLock; struct Oper; diff --git a/include/extern.h b/include/extern.h index 5eb7dcb58..e8a47c209 100644 --- a/include/extern.h +++ b/include/extern.h @@ -71,34 +71,6 @@ E int CurrentUplink; E void save_databases(); E void sighandler(int signum); -/**** 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); diff --git a/include/messages.h b/include/messages.h new file mode 100644 index 000000000..115f659af --- /dev/null +++ b/include/messages.h @@ -0,0 +1,119 @@ +#include "protocol.h" + +/* Common IRCD messages. + * Protocol modules may chose to include some, none, or all of these handlers + * as they see fit. + */ + +struct CoreIRCDMessageAway : IRCDMessage +{ + CoreIRCDMessageAway(const Anope::string &mname = "AWAY") : IRCDMessage(mname, 0) { SetFlag(IRCDMESSAGE_REQUIRE_USER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override; +}; + +struct CoreIRCDMessageCapab : IRCDMessage +{ + CoreIRCDMessageCapab(const Anope::string &mname = "CAPAB") : IRCDMessage(mname, 1) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override; +}; + +struct CoreIRCDMessageError : IRCDMessage +{ + CoreIRCDMessageError(const Anope::string &mname = "ERROR") : IRCDMessage(mname, 1) { } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override; +}; + +struct CoreIRCDMessageJoin : IRCDMessage +{ + CoreIRCDMessageJoin(const Anope::string &mname = "JOIN") : IRCDMessage(mname, 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override; +}; + +struct CoreIRCDMessageKill : IRCDMessage +{ + CoreIRCDMessageKill(const Anope::string &mname = "KILL") : IRCDMessage(mname, 2) { } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override; +}; + +struct CoreIRCDMessageMOTD : IRCDMessage +{ + CoreIRCDMessageMOTD(const Anope::string &mname = "MOTD") : IRCDMessage(mname, 1) { } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override; +}; + +struct CoreIRCDMessagePart : IRCDMessage +{ + CoreIRCDMessagePart(const Anope::string &mname = "PART") : IRCDMessage(mname, 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override; +}; + +struct CoreIRCDMessagePing : IRCDMessage +{ + CoreIRCDMessagePing(const Anope::string &mname = "PING") : IRCDMessage(mname, 1) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override; +}; + +struct CoreIRCDMessagePrivmsg : IRCDMessage +{ + CoreIRCDMessagePrivmsg(const Anope::string &mname = "PRIVMSG") : IRCDMessage(mname, 2) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override; +}; + +struct CoreIRCDMessageQuit : IRCDMessage +{ + CoreIRCDMessageQuit(const Anope::string &mname = "QUIT") : IRCDMessage(mname, 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override; +}; + +struct CoreIRCDMessageSQuit : IRCDMessage +{ + CoreIRCDMessageSQuit(const Anope::string &mname = "SQUIT") : IRCDMessage(mname, 1) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override; +}; + +struct CoreIRCDMessageStats : IRCDMessage +{ + CoreIRCDMessageStats(const Anope::string &mname = "STATS") : IRCDMessage(mname, 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override; +}; + +struct CoreIRCDMessageTime : IRCDMessage +{ + CoreIRCDMessageTime(const Anope::string &mname = "TIME") : IRCDMessage(mname, 0) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override; +}; + +struct CoreIRCDMessageTopic : IRCDMessage +{ + CoreIRCDMessageTopic(const Anope::string &mname = "TOPIC") : IRCDMessage(mname, 2) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override; +}; + +struct CoreIRCDMessageVersion : IRCDMessage +{ + CoreIRCDMessageVersion(const Anope::string &mname = "VERSION") : IRCDMessage(mname, 0) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override; +}; + +struct CoreIRCDMessageWhois : IRCDMessage +{ + CoreIRCDMessageWhois(const Anope::string &mname = "WHOIS") : IRCDMessage(mname, 1) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override; +}; + diff --git a/include/module.h b/include/module.h index 6865a2c17..bba901741 100644 --- a/include/module.h +++ b/include/module.h @@ -31,6 +31,7 @@ #include "logger.h" #include "mail.h" #include "memo.h" +#include "messages.h" #include "modes.h" #include "modules.h" #include "oper.h" diff --git a/include/modules.h b/include/modules.h index 939b98b34..9d3d701e3 100644 --- a/include/modules.h +++ b/include/modules.h @@ -141,9 +141,6 @@ enum Priority { PRIORITY_FIRST, PRIORITY_DONTCARE, PRIORITY_LAST, PRIORITY_BEFOR /* Module types, in the order in which they are unloaded. The order these are in is IMPORTANT */ enum ModType { MT_BEGIN, THIRD, SUPPORTED, CORE, DATABASE, ENCRYPTION, PROTOCOL, MT_END }; -typedef std::multimap<Anope::string, Message *> message_map; -extern CoreExport message_map MessageMap; - extern CoreExport std::list<Module *> Modules; class ModuleVersion @@ -268,7 +265,7 @@ class CoreExport Module : public Extensible * @param source The nick of the sender. * @param kickmsg The reason for the kick. */ - virtual void OnUserKicked(Channel *c, User *target, const Anope::string &source, const Anope::string &kickmsg) { } + virtual void OnUserKicked(Channel *c, User *target, MessageSource &source, const Anope::string &kickmsg) { } /** Called when Services' configuration has been loaded. */ @@ -439,7 +436,7 @@ class CoreExport Module : public Extensible * @param setter The user who set the new topic * @param topic The new topic */ - virtual void OnTopicUpdated(Channel *c, User *setter, const Anope::string &topic) { } + virtual void OnTopicUpdated(Channel *c, const Anope::string &user, const Anope::string &topic) { } /** Called before a channel expires * @param ci The channel @@ -828,21 +825,21 @@ class CoreExport Module : public Extensible /** Called when a mode is set on a channel * @param c The channel - * @param setter The user who is setting the mode + * @param setter The user or server that is setting the mode * @param Name The mode name * @param param The mode param, if there is one * @return EVENT_STOP to make mlock/secureops etc checks not happen */ - virtual EventReturn OnChannelModeSet(Channel *c, User *setter, ChannelModeName Name, const Anope::string ¶m) { return EVENT_CONTINUE; } + virtual EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelModeName Name, const Anope::string ¶m) { return EVENT_CONTINUE; } /** Called when a mode is unset on a channel * @param c The channel - * @param setter the user who is unsetting the mode + * @param setter The user or server that is unsetting the mode * @param Name The mode name * @param param The mode param, if there is one * @return EVENT_STOP to make mlock/secureops etc checks not happen */ - virtual EventReturn OnChannelModeUnset(Channel *c, User *setter, ChannelModeName Name, const Anope::string ¶m) { return EVENT_CONTINUE; } + virtual EventReturn OnChannelModeUnset(Channel *c, MessageSource &setter, ChannelModeName Name, const Anope::string ¶m) { return EVENT_CONTINUE; } /** Called when a mode is set on a user * @param u The user @@ -1121,14 +1118,4 @@ class CoreExport CallBack : public Timer virtual ~CallBack(); }; -class CoreExport Message -{ -public: - Anope::string name; - bool (*func)(const Anope::string &source, const std::vector<Anope::string> ¶ms); - - Message(const Anope::string &n, bool (*f)(const Anope::string &, const std::vector<Anope::string> &)); - ~Message(); -}; - #endif // MODULES_H diff --git a/include/protocol.h b/include/protocol.h index 5fb9da403..d4ff79082 100644 --- a/include/protocol.h +++ b/include/protocol.h @@ -17,39 +17,15 @@ #include "services.h" #include "anope.h" -/* Protocol tweaks */ - -struct IRCDVar -{ - const char *name; /* Name of the IRCd command */ - const char *pseudoclient_mode; /* Mode used by BotServ Bots */ - int svsnick; /* Supports SVSNICK */ - int vhost; /* Supports vhost */ - int snline; /* Supports SNline */ - int sqline; /* Supports SQline */ - int szline; /* Supports SZline */ - int join2msg; /* Join 2 Message */ - int chansqline; /* Supports Channel Sqlines */ - int quitonkill; /* IRCD sends QUIT when kill */ - int vident; /* Supports vidents */ - int svshold; /* Supports svshold */ - int tsonmode; /* Timestamp on mode changes */ - int omode; /* On the fly o:lines */ - int umode; /* change user modes */ - int knock_needs_i; /* Check if we needed +i when setting NOKNOCK */ - int svsmode_ucmode; /* Can remove User Channel Modes with SVSMODE */ - int sglineenforce; - int ts6; /* ircd is TS6 */ - const char *globaltldprefix; /* TLD prefix used for Global */ - unsigned maxmodes; /* Max modes to send per line */ - int certfp; /* IRCd sends a SSL users certificate fingerprint */ -}; - - class CoreExport IRCDProto { + Anope::string proto_name; + + IRCDProto() { } protected: - virtual void SendSVSKillInternal(const BotInfo *, const User *, const Anope::string &); + IRCDProto(const Anope::string &proto_name); + + virtual void SendSVSKillInternal(const BotInfo *, User *, const Anope::string &); virtual void SendModeInternal(const BotInfo *, const Channel *, const Anope::string &); virtual void SendModeInternal(const BotInfo *, const User *, const Anope::string &) = 0; virtual void SendKickInternal(const BotInfo *, const Channel *, const User *, const Anope::string &); @@ -62,14 +38,40 @@ class CoreExport IRCDProto virtual void SendCTCPInternal(const BotInfo *bi, const Anope::string &dest, const Anope::string &buf); virtual void SendNumericInternal(int numeric, const Anope::string &dest, const Anope::string &buf); public: - virtual ~IRCDProto() { } + virtual ~IRCDProto(); + + const Anope::string &GetProtocolName(); + /* Modes used by default by our clients */ + Anope::string DefaultPseudoclientModes; + /* Can we force change a users's nick */ + bool CanSVSNick; + /* Can we set vhosts/vidents on users? */ + bool CanSetVHost, CanSetVIdent; + /* Can we ban specific gecos from being used? */ + bool CanSNLine; + /* Can we ban specific nicknames from being used? */ + bool CanSQLine; + /* Can we ban sepcific channel names from being used? */ + bool CanSQLineChannel; + /* Can we ban by IP? */ + bool CanSZLine; + /* Can we place temporary holds on specific nicknames? */ + bool CanSVSHold; + /* See os_oline */ + bool CanSVSO; + /* See ns_cert */ + bool CanCertFP; + /* Whether this IRCd requires unique IDs for each user or server. See TS6/P10. */ + bool RequiresID; + /* The maximum number of modes we are allowed to set with one MODE command */ + unsigned MaxModes; virtual void SendSVSNOOP(const Server *, bool) { } virtual void SendTopic(BotInfo *, Channel *); virtual void SendVhostDel(User *) { } virtual void SendAkill(User *, XLine *) = 0; virtual void SendAkillDel(const XLine *) = 0; - virtual void SendSVSKill(const BotInfo *source, const User *user, const char *fmt, ...); + virtual void SendSVSKill(const BotInfo *source, User *user, const char *fmt, ...); virtual void SendMode(const BotInfo *bi, const Channel *dest, const char *fmt, ...); virtual void SendMode(const BotInfo *bi, const User *u, const char *fmt, ...); virtual void SendClientIntroduction(const User *u) = 0; @@ -78,8 +80,8 @@ class CoreExport IRCDProto virtual void SendNotice(const BotInfo *bi, const Anope::string &dest, const char *fmt, ...); virtual void SendAction(const BotInfo *bi, const Anope::string &dest, const char *fmt, ...); virtual void SendPrivmsg(const BotInfo *bi, const Anope::string &dest, const char *fmt, ...); - virtual void SendGlobalNotice(const BotInfo *bi, const Server *dest, const Anope::string &msg); - virtual void SendGlobalPrivmsg(const BotInfo *bi, const Server *desc, const Anope::string &msg); + virtual void SendGlobalNotice(const BotInfo *bi, const Server *dest, const Anope::string &msg) = 0; + virtual void SendGlobalPrivmsg(const BotInfo *bi, const Server *desc, const Anope::string &msg) = 0; virtual void SendQuit(const User *u, const char *fmt, ...); virtual void SendPing(const Anope::string &servname, const Anope::string &who); @@ -120,36 +122,44 @@ class CoreExport IRCDProto virtual void SendChannel(Channel *c) { } }; -class CoreExport IRCdMessage +enum IRCDMessageFlag { + IRCDMESSAGE_SOFT_LIMIT, + IRCDMESSAGE_REQUIRE_SERVER, + IRCDMESSAGE_REQUIRE_USER +}; + +class CoreExport MessageSource +{ + Anope::string source; + User *u; + Server *s; + 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> &); + MessageSource(const Anope::string &); + MessageSource(User *u); + MessageSource(Server *s); + const Anope::string GetName(); + const Anope::string &GetSource(); + User *GetUser(); + Server *GetServer(); }; -extern CoreExport IRCDVar *ircd; -extern CoreExport IRCDProto *ircdproto; -extern CoreExport IRCdMessage *ircdmessage; +class CoreExport IRCDMessage : public Flags<IRCDMessageFlag, 3> +{ + static std::map<Anope::string, std::vector<IRCDMessage *> > messages; -extern CoreExport void pmodule_ircd_proto(IRCDProto *); -extern CoreExport void pmodule_ircd_var(IRCDVar *ircdvar); -extern CoreExport void pmodule_ircd_message(IRCdMessage *message); + Anope::string name; + unsigned param_count; + public: + static const std::vector<IRCDMessage *> *Find(const Anope::string &name); + + IRCDMessage(const Anope::string &n, unsigned p = 0); + ~IRCDMessage(); + unsigned GetParamCount() const; + virtual bool Run(MessageSource &, const std::vector<Anope::string> ¶ms) = 0; +}; + +extern CoreExport IRCDProto *ircdproto; #endif // PROTOCOL_H diff --git a/include/servers.h b/include/servers.h index 7b85a182a..94dc5491e 100644 --- a/include/servers.h +++ b/include/servers.h @@ -7,8 +7,6 @@ /* Anope */ extern CoreExport Server *Me; -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 const Anope::string ts6_uid_retrieve(); extern CoreExport const Anope::string ts6_sid_retrieve(); @@ -57,12 +55,14 @@ class CoreExport Server : public Flags<ServerFlag> * @param sid Server sid/numeric * @param flag An optional server flag */ - Server(Server *uplink, const Anope::string &name, unsigned hops, const Anope::string &description, const Anope::string &sid, ServerFlag flag = SERVER_NONE); + Server(Server *uplink, const Anope::string &name, unsigned hops, const Anope::string &description, const Anope::string &sid = "", ServerFlag flag = SERVER_NONE); + private: /** Destructor */ ~Server(); + public: /** Delete this server with a reason * @param reason The reason */ @@ -93,7 +93,7 @@ class CoreExport Server : public Flags<ServerFlag> */ void SetSID(const Anope::string &sid); - /** Get the server numeric/SID + /** Get the server numeric/SID, else the server name * @return The numeric/SID */ const Anope::string &GetSID() const; diff --git a/include/users.h b/include/users.h index fab5fa868..502cc0a7c 100644 --- a/include/users.h +++ b/include/users.h @@ -82,9 +82,15 @@ class CoreExport User : public virtual Base, public Extensible, public CommandRe * @param snick The nickname of the user. * @param sident The username of the user * @param shost The hostname of the user + * @param svhost The vhost of the user + * @param sip The ip of the user + * @param sserver The server of the user + * @param srealname The realname/gecos of teh user + * @param ssignon User's timestamp + * @param smodes User's modes * @param suid The unique identifier of the user. */ - User(const Anope::string &snick, const Anope::string &sident, const Anope::string &shost, const Anope::string &suid = ""); + User(const Anope::string &snick, const Anope::string &sident, const Anope::string &shost, const Anope::string &svhost, const Anope::string &sip, Server *sserver, const Anope::string &srealname, time_t ssignon, const Anope::string &smodes, const Anope::string &suid = ""); /** Destroy a user. */ @@ -93,7 +99,7 @@ class CoreExport User : public virtual Base, public Extensible, public CommandRe /** Update the nickname of a user record accordingly, should be * called from ircd protocol. */ - void SetNewNick(const Anope::string &newnick); + void ChangeNick(const Anope::string &newnick); /** Update the displayed (vhost) of a user record. * This is used (if set) instead of real host. @@ -116,8 +122,7 @@ class CoreExport User : public virtual Base, public Extensible, public CommandRe */ const Anope::string &GetCloakedHost() const; - /** Retrieves the UID of the user, where applicable, if set. - * This is not used on some IRCds, but is for a lot e.g. P10, TS6 protocols. + /** Retrieves the UID of the user, if set, else the nick. * @return The UID of the user. */ const Anope::string &GetUID() const; @@ -302,6 +307,12 @@ class CoreExport User : public virtual Base, public Extensible, public CommandRe * @param reason The reason for the kill */ void Kill(const Anope::string &source, const Anope::string &reason); + + /** Process a kill for a user + * @param source The user/server doing the kill + * @param reason The reason for the kill + */ + void KillInternal(const Anope::string &source, const Anope::string &reason); }; extern CoreExport int32_t opcnt; @@ -310,11 +321,6 @@ extern CoreExport time_t maxusertime; extern CoreExport User *finduser(const Anope::string &nick); -extern CoreExport 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); - -extern CoreExport void do_umode(const Anope::string &user, const Anope::string &modes); -extern CoreExport void do_kill(User *user, const Anope::string &reason); - extern CoreExport bool matches_list(Channel *c, User *user, ChannelModeName mode); extern CoreExport Anope::string create_mask(User *u); diff --git a/modules/commands/bs_bot.cpp b/modules/commands/bs_bot.cpp index 0b45ee71c..de7fa1128 100644 --- a/modules/commands/bs_bot.cpp +++ b/modules/commands/bs_bot.cpp @@ -218,11 +218,8 @@ class CommandBSBot : public Command } /* The new nick is really different, so we remove the Q line for the old nick. */ - if (ircd->sqline) - { - XLine x(bi->nick); - ircdproto->SendSQLineDel(&x); - } + XLine x_del(bi->nick); + ircdproto->SendSQLineDel(&x_del); /* Add a Q line for the new nick */ XLine x(nick, "Reserved for services"); diff --git a/modules/commands/cs_seen.cpp b/modules/commands/cs_seen.cpp index 289988867..ce88efa44 100644 --- a/modules/commands/cs_seen.cpp +++ b/modules/commands/cs_seen.cpp @@ -376,9 +376,9 @@ class CSSeen : public Module UpdateUser(u, PART, u->nick, "", channel, msg); } - void OnUserKicked(Channel *c, User *target, const Anope::string &source, const Anope::string &msg) anope_override + void OnUserKicked(Channel *c, User *target, MessageSource &source, const Anope::string &msg) anope_override { - UpdateUser(target, KICK, target->nick, source, c->name, msg); + UpdateUser(target, KICK, target->nick, source.GetSource(), c->name, msg); } private: diff --git a/modules/commands/hs_on.cpp b/modules/commands/hs_on.cpp index 91fcaf10e..d02dd7dfe 100644 --- a/modules/commands/hs_on.cpp +++ b/modules/commands/hs_on.cpp @@ -27,6 +27,8 @@ class CommandHSOn : public Command User *u = source.GetUser(); if (!u) return; + else if (!ircdproto->CanSetVHost) + return; // HostServ wouldn't even be loaded at this point const NickAlias *na = findnick(u->nick); if (na && u->Account() == na->nc && na->HasVhost()) @@ -37,13 +39,9 @@ class CommandHSOn : public Command source.Reply(_("Your vhost of \002%s\002 is now activated."), na->GetVhostHost().c_str()); Log(LOG_COMMAND, source, this) << "to enable their vhost of " << (!na->GetVhostIdent().empty() ? na->GetVhostIdent() + "@" : "") << na->GetVhostHost(); ircdproto->SendVhost(u, na->GetVhostIdent(), na->GetVhostHost()); - if (ircd->vhost) - u->vhost = na->GetVhostHost(); - if (ircd->vident) - { - if (!na->GetVhostIdent().empty()) - u->SetVIdent(na->GetVhostIdent()); - } + u->vhost = na->GetVhostHost(); + if (ircdproto->CanSetVIdent && !na->GetVhostIdent().empty()) + u->SetVIdent(na->GetVhostIdent()); u->UpdateHost(); } else diff --git a/modules/commands/hs_request.cpp b/modules/commands/hs_request.cpp index f4b710b7f..94b181f51 100644 --- a/modules/commands/hs_request.cpp +++ b/modules/commands/hs_request.cpp @@ -121,7 +121,7 @@ class CommandHSRequest : public Command source.Reply(HOST_SET_IDENTTOOLONG, Config->UserLen); return; } - else if (!ircd->vident) + else if (!ircdproto->CanSetVIdent) { source.Reply(HOST_NO_VIDENT); return; @@ -354,6 +354,9 @@ class HSRequest : public Module { this->SetAuthor("Anope"); + if (!ircdproto || !ircdproto->CanSetVHost) + throw ModuleException("Your IRCd does not support vhosts"); + Implementation i[] = { I_OnReload }; ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); diff --git a/modules/commands/hs_set.cpp b/modules/commands/hs_set.cpp index b2509bcea..2189f2483 100644 --- a/modules/commands/hs_set.cpp +++ b/modules/commands/hs_set.cpp @@ -55,7 +55,7 @@ class CommandHSSet : public Command if (!user.empty()) { - if (!ircd->vident) + if (!ircdproto->CanSetVIdent) { source.Reply(HOST_NO_VIDENT); return; @@ -156,7 +156,7 @@ class CommandHSSetAll : public Command if (!user.empty()) { - if (!ircd->vident) + if (!ircdproto->CanSetVIdent) { source.Reply(HOST_NO_VIDENT); return; diff --git a/modules/commands/ns_cert.cpp b/modules/commands/ns_cert.cpp index da3cb2aa1..a06dd1a3a 100644 --- a/modules/commands/ns_cert.cpp +++ b/modules/commands/ns_cert.cpp @@ -225,7 +225,7 @@ class NSCert : public Module { this->SetAuthor("Anope"); - if (!ircd || !ircd->certfp) + if (!ircdproto || !ircdproto->CanCertFP) throw ModuleException("Your IRCd does not support ssl client certificates"); Implementation i[] = { I_OnFingerprint }; diff --git a/modules/commands/ns_info.cpp b/modules/commands/ns_info.cpp index b3b734a39..5daf2357e 100644 --- a/modules/commands/ns_info.cpp +++ b/modules/commands/ns_info.cpp @@ -102,7 +102,7 @@ class CommandNSInfo : public Command { if (na->HasVhost()) { - if (ircd->vident && !na->GetVhostIdent().empty()) + if (ircdproto->CanSetVIdent && !na->GetVhostIdent().empty()) info[_("VHost")] = na->GetVhostIdent() + "@" + na->GetVhostHost(); else info[_("VHost")] = na->GetVhostHost(); diff --git a/modules/commands/os_defcon.cpp b/modules/commands/os_defcon.cpp index 741eb9d43..1d684bc27 100644 --- a/modules/commands/os_defcon.cpp +++ b/modules/commands/os_defcon.cpp @@ -323,14 +323,6 @@ class OSDefcon : public Module Log() << "DefConChanModes must lock mode +l as well to lock mode +L"; } - - /* Some ircd we can't set NOKNOCK without INVITE */ - /* So check if we need there is a NOKNOCK MODE and that we need INVITEONLY */ - if (ircd->knock_needs_i && (cm = ModeManager::FindChannelModeByName(CMODE_NOKNOCK)) && DConfig.DefConModesOn.HasFlag(cm->Name) && !DConfig.DefConModesOn.HasFlag(CMODE_INVITE)) - { - DConfig.DefConModesOn.UnsetFlag(CMODE_NOKNOCK); - Log() << "DefConChanModes must lock mode +i as well to lock mode +K"; - } } public: @@ -437,7 +429,7 @@ class OSDefcon : public Module return EVENT_CONTINUE; } - EventReturn OnChannelModeSet(Channel *c, User *setter, ChannelModeName Name, const Anope::string ¶m) anope_override + EventReturn OnChannelModeSet(Channel *c, MessageSource &, ChannelModeName Name, const Anope::string ¶m) anope_override { ChannelMode *cm = ModeManager::FindChannelModeByName(Name); @@ -451,7 +443,7 @@ class OSDefcon : public Module return EVENT_CONTINUE; } - EventReturn OnChannelModeUnset(Channel *c, User *setter, ChannelModeName Name, const Anope::string &) anope_override + EventReturn OnChannelModeUnset(Channel *c, MessageSource &, ChannelModeName Name, const Anope::string &) anope_override { ChannelMode *cm = ModeManager::FindChannelModeByName(Name); diff --git a/modules/commands/os_forbid.cpp b/modules/commands/os_forbid.cpp index 4862d5ea9..5f1d1d0ed 100644 --- a/modules/commands/os_forbid.cpp +++ b/modules/commands/os_forbid.cpp @@ -278,7 +278,7 @@ class OSForbid : public Module ForbidData *d = this->forbidService.FindForbid(c->name, FT_CHAN); if (bi != NULL && d != NULL) { - if (ircd->chansqline) + if (ircdproto->CanSQLineChannel) { XLine x(c->name, bi->nick, Anope::CurTime + Config->CSInhabit, d->reason); ircdproto->SendSQLine(NULL, &x); diff --git a/modules/commands/os_jupe.cpp b/modules/commands/os_jupe.cpp index 34c28a864..cfe917c13 100644 --- a/modules/commands/os_jupe.cpp +++ b/modules/commands/os_jupe.cpp @@ -37,7 +37,7 @@ class CommandOSJupe : public Command Anope::string rbuf = "Juped by " + source.GetNick() + (!reason.empty() ? ": " + reason : ""); if (server) ircdproto->SendSquit(server, rbuf); - Server *juped_server = new Server(Me, jserver, 1, rbuf, ircd->ts6 ? ts6_sid_retrieve() : "", SERVER_JUPED); + Server *juped_server = new Server(Me, jserver, 1, rbuf, ts6_sid_retrieve(), SERVER_JUPED); ircdproto->SendServer(juped_server); Log(LOG_ADMIN, source, this) << "on " << jserver << " (" << rbuf << ")"; diff --git a/modules/commands/os_oline.cpp b/modules/commands/os_oline.cpp index a468281e0..ccf053f7e 100644 --- a/modules/commands/os_oline.cpp +++ b/modules/commands/os_oline.cpp @@ -72,7 +72,7 @@ class OSOLine : public Module { this->SetAuthor("Anope"); - if (!ircd || !ircd->omode) + if (!ircdproto || !ircdproto->CanSVSO) throw ModuleException("Your IRCd does not support OMODE."); } diff --git a/modules/commands/os_stats.cpp b/modules/commands/os_stats.cpp index 7b593e421..dd5bf9ee0 100644 --- a/modules/commands/os_stats.cpp +++ b/modules/commands/os_stats.cpp @@ -84,7 +84,7 @@ class CommandOSStats : public Command else source.Reply(_("Default AKILL expiry time: \002No expiration\002")); } - if (ircd->snline && snlines) + if (ircdproto->CanSNLine && snlines) { /* SNLINEs */ source.Reply(_("Current number of SNLINEs: \002%d\002"), snlines->GetCount()); @@ -104,7 +104,7 @@ class CommandOSStats : public Command else source.Reply(_("Default SNLINE expiry time: \002No expiration\002")); } - if (ircd->sqline && sqlines) + if (ircdproto->CanSQLine && sqlines) { /* SQLINEs */ source.Reply(_("Current number of SQLINEs: \002%d\002"), sqlines->GetCount()); diff --git a/modules/commands/os_svsnick.cpp b/modules/commands/os_svsnick.cpp index aeaa38a59..4c6329acb 100644 --- a/modules/commands/os_svsnick.cpp +++ b/modules/commands/os_svsnick.cpp @@ -81,7 +81,7 @@ class OSSVSNick : public Module { this->SetAuthor("Anope"); - if (!ircd || !ircd->svsnick) + if (!ircdproto || !ircdproto->CanSVSNick) throw ModuleException("Your IRCd does not support SVSNICK"); } diff --git a/modules/commands/os_sxline.cpp b/modules/commands/os_sxline.cpp index 20e76a94d..8cd3d9f7a 100644 --- a/modules/commands/os_sxline.cpp +++ b/modules/commands/os_sxline.cpp @@ -250,7 +250,7 @@ class CommandOSSNLine : public CommandOSSXLineBase void OnAdd(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override { - if (!this->xlm() ||! ircd->snline) + if (!this->xlm() || !ircdproto->CanSNLine) { source.Reply(_("Your IRCd does not support SNLINE")); return; @@ -384,18 +384,15 @@ class CommandOSSNLine : public CommandOSSXLineBase { this->xlm()->Send(source.GetUser(), x); - if (!ircd->sglineenforce) - { - Anope::string rreason = "G-Lined: " + reason; + Anope::string rreason = "G-Lined: " + reason; - for (Anope::insensitive_map<User *>::const_iterator it = UserListByNick.begin(); it != UserListByNick.end();) - { - User *user = it->second; - ++it; + for (Anope::insensitive_map<User *>::const_iterator it = UserListByNick.begin(); it != UserListByNick.end();) + { + User *user = it->second; + ++it; - if (!user->HasMode(UMODE_OPER) && user->server != Me && Anope::Match(user->realname, x->Mask, false, true)) - user->Kill(Config->ServerName, rreason); - } + if (!user->HasMode(UMODE_OPER) && user->server != Me && Anope::Match(user->realname, x->Mask, false, true)) + user->Kill(Config->ServerName, rreason); } } @@ -474,7 +471,7 @@ class CommandOSSQLine : public CommandOSSXLineBase void OnAdd(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override { - if (!this->xlm() || !ircd->sqline) + if (!this->xlm() || !ircdproto->CanSQLine) { source.Reply(_("Your IRCd does not support SQLINE")); return; diff --git a/modules/extra/m_chanstats.cpp b/modules/extra/m_chanstats.cpp index ed9a5f444..9d9e9dbd8 100644 --- a/modules/extra/m_chanstats.cpp +++ b/modules/extra/m_chanstats.cpp @@ -365,8 +365,9 @@ class MChanstats : public Module else Log() << "Chanstats: no database connection to " << engine; } - void OnTopicUpdated(Channel *c, User *u, const Anope::string &topic) anope_override + void OnTopicUpdated(Channel *c, const Anope::string &user, const Anope::string &topic) anope_override { + User *u = finduser(user); if (!u || !u->Account() || !c->ci || !c->ci->HasFlag(CI_STATS)) return; query = "CALL " + prefix + "chanstats_proc_update(@channel@, @nick@, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);"; @@ -374,16 +375,17 @@ class MChanstats : public Module query.setValue("nick", GetDisplay(u)); this->RunQuery(query); } - EventReturn OnChannelModeSet(Channel *c, User *setter, ChannelModeName Name, const Anope::string ¶m) anope_override + EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelModeName Name, const Anope::string ¶m) anope_override { - this->OnModeChange(c, setter); + this->OnModeChange(c, setter.GetUser()); return EVENT_CONTINUE; } - EventReturn OnChannelModeUnset(Channel *c, User *setter, ChannelModeName Name, const Anope::string ¶m) anope_override + EventReturn OnChannelModeUnset(Channel *c, MessageSource &setter, ChannelModeName Name, const Anope::string ¶m) anope_override { - this->OnModeChange(c, setter); + this->OnModeChange(c, setter.GetUser()); return EVENT_CONTINUE; } + private: void OnModeChange(Channel *c, User *u) { if (!u || !u->Account() || !c->ci || !c->ci->HasFlag(CI_STATS)) @@ -394,7 +396,8 @@ class MChanstats : public Module query.setValue("nick", GetDisplay(u)); this->RunQuery(query); } - void OnUserKicked(Channel *c, User *target, const Anope::string &source, const Anope::string &kickmsg) anope_override + public: + void OnUserKicked(Channel *c, User *target, MessageSource &source, const Anope::string &kickmsg) anope_override { if (!c->ci || !c->ci->HasFlag(CI_STATS)) return; @@ -406,7 +409,7 @@ class MChanstats : public Module query = "CALL " + prefix + "chanstats_proc_update(@channel@, @nick@, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0);"; query.setValue("channel", c->name); - query.setValue("nick", GetDisplay(finduser(source))); + query.setValue("nick", GetDisplay(source.GetUser())); this->RunQuery(query); } void OnPrivmsg(User *u, Channel *c, Anope::string &msg) anope_override diff --git a/modules/extra/m_proxyscan.cpp b/modules/extra/m_proxyscan.cpp index f7fa3fdad..e6ee4008a 100644 --- a/modules/extra/m_proxyscan.cpp +++ b/modules/extra/m_proxyscan.cpp @@ -94,7 +94,7 @@ class ProxyConnect : public ConnectionSocket } else { - if (ircd->szline) + if (ircdproto->CanSZLine) ircdproto->SendSZLine(NULL, x); else ircdproto->SendAkill(NULL, x); diff --git a/modules/extra/webcpanel/webcpanel.cpp b/modules/extra/webcpanel/webcpanel.cpp index 4970845cd..bb65387f2 100644 --- a/modules/extra/webcpanel/webcpanel.cpp +++ b/modules/extra/webcpanel/webcpanel.cpp @@ -73,7 +73,7 @@ class ModuleWebCPanel : public Module s.subsections.push_back(ss); provider->RegisterPage(&this->nickserv_info); - if (ircd && ircd->certfp) + if (ircdproto && ircdproto->CanCertFP) { ss.name = "SSL Certificates"; ss.url = "/nickserv/cert"; diff --git a/modules/protocol/bahamut.cpp b/modules/protocol/bahamut.cpp index 73955149d..8aeee39c8 100644 --- a/modules/protocol/bahamut.cpp +++ b/modules/protocol/bahamut.cpp @@ -13,34 +13,40 @@ #include "module.h" -IRCDVar myIrcd = { - "Bahamut 1.8.x", /* ircd name */ - "+", /* Modes used by pseudoclients */ - 1, /* SVSNICK */ - 0, /* Vhost */ - 1, /* Supports SNlines */ - 1, /* Supports SQlines */ - 1, /* Supports SZlines */ - 0, /* Join 2 Message */ - 1, /* Chan SQlines */ - 1, /* Quit on Kill */ - 0, /* vidents */ - 1, /* svshold */ - 1, /* time stamp on mode */ - 0, /* O:LINE */ - 1, /* UMODE */ - 1, /* No Knock requires +i */ - 0, /* Can remove User Channel Modes with SVSMODE */ - 0, /* Sglines are not enforced until user reconnects */ - 0, /* ts6 */ - "$", /* TLD Prefix for Global */ - 6, /* Max number of modes we can send per line */ - 0 /* IRCd sends a SSL users certificate fingerprint */ -}; +class ChannelModeFlood : public ChannelModeParam +{ + public: + ChannelModeFlood(char modeChar, bool minusNoArg) : ChannelModeParam(CMODE_FLOOD, modeChar, minusNoArg) { } + bool IsValid(const Anope::string &value) const anope_override + { + try + { + Anope::string rest; + if (!value.empty() && value[0] != ':' && convertTo<int>(value[0] == '*' ? value.substr(1) : value, rest, false) > 0 && rest[0] == ':' && rest.length() > 1 && convertTo<int>(rest.substr(1), rest, false) > 0 && rest.empty()) + return true; + } + catch (const ConvertException &) { } + + return false; + } +}; class BahamutIRCdProto : public IRCDProto { + public: + BahamutIRCdProto() : IRCDProto("Bahamut 1.8.x") + { + DefaultPseudoclientModes = "+"; + CanSVSNick = true; + CanSNLine = true; + CanSQLine = true; + CanSQLineChannel = true; + CanSZLine = true; + CanSVSHold = true; + MaxModes = 60; + } + void SendModeInternal(const BotInfo *source, const Channel *dest, const Anope::string &buf) anope_override { if (Capab.count("TSMODE") > 0) @@ -62,6 +68,16 @@ class BahamutIRCdProto : public IRCDProto UplinkSocket::Message(Me) << "SVSMODE " << u->nick << " " << u->timestamp << " " << buf; } + void SendGlobalNotice(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override + { + UplinkSocket::Message(bi) << "NOTICE $" << dest->GetName() << " :" << msg; + } + + void SendGlobalPrivmsg(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override + { + UplinkSocket::Message(bi) << "PRIVMSG $" << dest->GetName() << " :" << msg; + } + /* SVSHOLD - set */ void SendSVSHold(const Anope::string &nick) anope_override { @@ -290,46 +306,82 @@ class BahamutIRCdProto : public IRCDProto } }; -class BahamutIRCdMessage : public IRCdMessage +struct IRCDMessageBurst : IRCDMessage { - public: - bool OnMode(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (params.size() > 2 && (params[0][0] == '#' || params[0][0] == '&')) - do_cmode(source, params[0], params[2], params[1]); - else if (params.size() > 1) - do_umode(params[0], params[1]); + IRCDMessageBurst() : IRCDMessage("BURST", 0) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); } + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + /* If we found a server with the given source, that one just + * finished bursting. If there was no source, then our uplink + * server finished bursting. -GD + */ + Server *s = source.GetServer(); + if (!s) + s = Me->GetLinks().front(); + if (s) + s->Sync(true); return true; } +}; - /* - ** NICK - new - ** source = NULL - ** parv[0] = nickname - ** parv[1] = hopcount - ** parv[2] = timestamp - ** parv[3] = modes - ** parv[4] = username - ** parv[5] = hostname - ** parv[6] = server - ** parv[7] = servicestamp - ** parv[8] = IP - ** parv[9] = info - ** NICK - change - ** source = oldnick - ** parv[0] = new nickname - ** parv[1] = hopcount - */ - bool OnNick(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (params.size() != 2) +struct IRCDMessageMode : IRCDMessage +{ + IRCDMessageMode(const Anope::string &n) : IRCDMessage(n, 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + if (params.size() > 2 && ircdproto->IsChannelValid(params[0])) + { + Channel *c = findchan(params[0]); + time_t ts = Anope::CurTime; + try + { + ts = convertTo<time_t>(params[1]); + } + catch (const ConvertException &) { } + + if (c) + c->SetModesInternal(source, params[2], ts); + } + else { - /* Currently bahamut has no ipv6 support */ - sockaddrs ip; - ip.ntop(AF_INET, params[8].c_str()); + User *u = finduser(params[0]); + if (u) + u->SetModesInternal("%s", params[1].c_str()); + } + + return true; + } +}; + +/* + ** NICK - new + ** source = NULL + ** parv[0] = nickname + ** parv[1] = hopcount + ** parv[2] = timestamp + ** parv[3] = modes + ** parv[4] = username + ** parv[5] = hostname + ** parv[6] = server + ** parv[7] = servicestamp + ** parv[8] = IP + ** parv[9] = info + ** NICK - change + ** source = oldnick + ** parv[0] = new nickname + ** parv[1] = hopcount + */ +struct IRCDMessageNick : IRCDMessage +{ + IRCDMessageNick() : IRCDMessage("NICK", 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } - User *user = do_nick(source, params[0], params[4], params[5], params[6], params[9], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : 0, ip.addr(), "", "", params[3]); + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + if (params.size() == 10) + { + User *user = new User(params[0], params[4], params[5], "", params[8], source.GetServer(), params[9], params[2].is_pos_number_only() ? convertTo<time_t>(params[2]) : 0, params[3]); if (user && nickserv) { const NickAlias *na; @@ -345,35 +397,29 @@ class BahamutIRCdMessage : public IRCdMessage } } else - do_nick(source, params[0], "", "", "", "", Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : 0, "", "", "", ""); + source.GetUser()->ChangeNick(params[0]); return true; } +}; - bool OnServer(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override - { - do_server(source, params[0], Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0, params[2], ""); - return true; - } +struct IRCDMessageServer : IRCDMessage +{ + IRCDMessageServer() : IRCDMessage("SERVER", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } - bool OnTopic(const Anope::string &, const std::vector<Anope::string> ¶ms) anope_override + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - if (params.size() < 4) - return true; - - Channel *c = findchan(params[0]); - if (!c) - { - Log() << "TOPIC for nonexistant channel " << params[0]; - return true; - } - - c->ChangeTopicInternal(params[1], params[3], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : Anope::CurTime); - + unsigned int hops = Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0; + new Server(source.GetServer() == NULL ? Me : source.GetServer(), params[0], hops, params[2]); return true; } +}; - bool OnSJoin(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override +struct IRCDMessageSJoin : IRCDMessage +{ + IRCDMessageSJoin() : IRCDMessage("SJOIN", 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { Channel *c = findchan(params[1]); time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo<time_t>(params[0]) : 0; @@ -403,7 +449,7 @@ class BahamutIRCdMessage : public IRCdMessage modes += " " + params[i]; if (!modes.empty()) modes.erase(modes.begin()); - c->SetModesInternal(NULL, modes); + c->SetModesInternal(source, modes); } /* For some reason, bahamut will send a SJOIN from the user joining a channel @@ -411,28 +457,24 @@ class BahamutIRCdMessage : public IRCdMessage */ if (!c->HasFlag(CH_SYNCING) && params.size() == 2) { - User *u = finduser(source); - if (!u) - Log(LOG_DEBUG) << "SJOIN for nonexistant user " << source << " on " << c->name; - else - { - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnPreJoinChannel, OnPreJoinChannel(u, c)); + User *u = source.GetUser(); - /* Add the user to the channel */ - c->JoinUser(u); + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnPreJoinChannel, OnPreJoinChannel(u, c)); - /* Now set whatever modes this user is allowed to have on the channel */ - chan_set_correct_modes(u, c, 1, true); + /* Add the user to the channel */ + c->JoinUser(u); - /* Check to see if modules want the user to join, if they do - * check to see if they are allowed to join (CheckKick will kick/ban them) - * Don't trigger OnJoinChannel event then as the user will be destroyed - */ - if (MOD_RESULT == EVENT_STOP && (!c->ci || !c->ci->CheckKick(u))) - { - FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(u, c)); - } + /* Now set whatever modes this user is allowed to have on the channel */ + chan_set_correct_modes(u, c, 1, true); + + /* Check to see if modules want the user to join, if they do + * check to see if they are allowed to join (CheckKick will kick/ban them) + * Don't trigger OnJoinChannel event then as the user will be destroyed + */ + if (MOD_RESULT == EVENT_STOP && (!c->ci || !c->ci->CheckKick(u))) + { + FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(u, c)); } } else @@ -476,7 +518,7 @@ class BahamutIRCdMessage : public IRCdMessage * This will enforce secureops etc on the user */ for (std::list<ChannelMode *>::iterator it = Status.begin(), it_end = Status.end(); it != it_end; ++it) - c->SetModeInternal(NULL, *it, buf); + c->SetModeInternal(source, *it, buf); /* Now set whatever modes this user is allowed to have on the channel */ chan_set_correct_modes(u, c, 1, true); @@ -504,53 +546,48 @@ class BahamutIRCdMessage : public IRCdMessage } }; -bool event_burst(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - Server *s = Server::Find(source); - - if (params.empty()) - { - /* for future use - start burst */ - } - else - { - /* If we found a server with the given source, that one just - * finished bursting. If there was no source, then our uplink - * server finished bursting. -GD - */ - if (!s) - s = Me->GetLinks().front(); - if (s) - s->Sync(true); - } - return true; -} - -class ChannelModeFlood : public ChannelModeParam +struct IRCDMessageTopic : IRCDMessage { - public: - ChannelModeFlood(char modeChar, bool minusNoArg) : ChannelModeParam(CMODE_FLOOD, modeChar, minusNoArg) { } + IRCDMessageTopic() : IRCDMessage("TOPIC", 4) { } - bool IsValid(const Anope::string &value) const anope_override + bool Run(MessageSource &, const std::vector<Anope::string> ¶ms) anope_override { - try - { - Anope::string rest; - if (!value.empty() && value[0] != ':' && convertTo<int>(value[0] == '*' ? value.substr(1) : value, rest, false) > 0 && rest[0] == ':' && rest.length() > 1 && convertTo<int>(rest.substr(1), rest, false) > 0 && rest.empty()) - return true; - } - catch (const ConvertException &) { } - - return false; + Channel *c = findchan(params[0]); + if (c) + c->ChangeTopicInternal(params[1], params[3], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : Anope::CurTime); + return true; } }; class ProtoBahamut : public Module { - Message message_svsmode, message_burst; - BahamutIRCdProto ircd_proto; - BahamutIRCdMessage ircd_message; + + /* Core message handlers */ + CoreIRCDMessageAway core_message_away; + CoreIRCDMessageCapab core_message_capab; + CoreIRCDMessageError core_message_error; + CoreIRCDMessageJoin core_message_join; + CoreIRCDMessageKill core_message_kill; + CoreIRCDMessageMOTD core_message_motd; + CoreIRCDMessagePart core_message_part; + CoreIRCDMessagePing core_message_ping; + CoreIRCDMessagePrivmsg core_message_privmsg; + CoreIRCDMessageQuit core_message_quit; + CoreIRCDMessageSQuit core_message_squit; + CoreIRCDMessageStats core_message_stats; + CoreIRCDMessageTime core_message_time; + CoreIRCDMessageTopic core_message_topic; + CoreIRCDMessageVersion core_message_version; + CoreIRCDMessageWhois core_message_whois; + + /* Our message handlers */ + IRCDMessageBurst message_burst; + IRCDMessageMode message_mode, message_svsmode; + IRCDMessageNick message_nick; + IRCDMessageServer message_server; + IRCDMessageSJoin message_sjoin; + IRCDMessageTopic message_topic; void AddModes() { @@ -591,26 +628,15 @@ class ProtoBahamut : public Module public: ProtoBahamut(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL), - message_svsmode("SVSMODE", OnMode), message_burst("BURST", event_burst) + message_mode("MODE"), message_svsmode("SVSMODE") { this->SetAuthor("Anope"); - pmodule_ircd_var(&myIrcd); - pmodule_ircd_proto(&this->ircd_proto); - pmodule_ircd_message(&this->ircd_message); - this->AddModes(); ModuleManager::Attach(I_OnUserNickChange, this); } - ~ProtoBahamut() - { - pmodule_ircd_var(NULL); - pmodule_ircd_proto(NULL); - pmodule_ircd_message(NULL); - } - void OnUserNickChange(User *u, const Anope::string &) anope_override { u->RemoveModeInternal(ModeManager::FindUserModeByName(UMODE_REGISTERED)); diff --git a/modules/protocol/inspircd-ts6.h b/modules/protocol/inspircd-ts6.h index 0ce5be921..f0af01cc9 100644 --- a/modules/protocol/inspircd-ts6.h +++ b/modules/protocol/inspircd-ts6.h @@ -47,7 +47,30 @@ class InspIRCdTS6Proto : public IRCDProto UplinkSocket::Message(Me) << "CHGHOST " << nick << " " << vhost; } - public: + protected: + InspIRCdTS6Proto(const Anope::string &name) : IRCDProto(name) + { + DefaultPseudoclientModes = "+I"; + CanSVSNick = true; + CanSetVHost = true; + CanSetVIdent = true; + CanSQLine = true; + CanSZLine = true; + CanSVSHold = true; + CanCertFP = true; + RequiresID = true; + MaxModes = 20; + } + + void SendGlobalNotice(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override + { + UplinkSocket::Message(bi) << "NOTICE $" << dest->GetName() << " :" << msg; + } + + void SendGlobalPrivmsg(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override + { + UplinkSocket::Message(bi) << "PRIVMSG $" << dest->GetName() << " :" << msg; + } void SendAkillDel(const XLine *x) anope_override { @@ -225,7 +248,7 @@ class InspIRCdTS6Proto : public IRCDProto SendServer(Me); UplinkSocket::Message(Me) << "BURST"; Module *enc = ModuleManager::FindFirstOf(ENCRYPTION); - UplinkSocket::Message(Me) << "VERSION :Anope-" << Anope::Version() << " " << Config->ServerName << " :" << ircd->name << " - (" << (enc ? enc->name : "unknown") << ") -- " << Anope::VersionBuildString(); + UplinkSocket::Message(Me) << "VERSION :Anope-" << Anope::Version() << " " << Config->ServerName << " :" << ircdproto->GetProtocolName() << " - (" << (enc ? enc->name : "unknown") << ") -- " << Anope::VersionBuildString(); } /* SVSHOLD - set */ @@ -319,83 +342,37 @@ class InspIRCdTS6Proto : public IRCDProto } }; -class InspircdIRCdMessage : public IRCdMessage +struct IRCDMessageEndburst : IRCDMessage { - public: - bool OnMode(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (params[0][0] == '#' || params[0][0] == '&') - do_cmode(source, params[0], params[2], params[1]); - else - { - /* InspIRCd lets opers change another - users modes, we have to kludge this - as it slightly breaks RFC1459 - */ - User *u = finduser(source); - // This can happen with server-origin modes. - if (!u) - u = finduser(params[0]); - // if it's still null, drop it like fire. - // most likely situation was that server introduced a nick which we subsequently akilled - if (!u) - return true; + IRCDMessageEndburst() : IRCDMessage("ENDBURST", 0) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } - do_umode(u->nick, params[1]); - } - - return true; - } - - virtual bool OnUID(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override = 0; - - bool OnNick(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - do_nick(source, params[0], "", "", "", "", 0, "", "", "", ""); - return true; - } - - bool OnPrivmsg(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override - { - /* Ignore privmsgs from the server, which can happen. */ - if (Server::Find(source) != NULL) - return true; + Server *s = source.GetServer(); - return IRCdMessage::OnPrivmsg(source, params); - } + Log(LOG_DEBUG) << "Processed ENDBURST for " << s->GetName(); - /* - * [Nov 04 00:08:46.308435 2009] debug: Received: SERVER irc.inspircd.com pass 0 964 :Testnet Central! - * 0: name - * 1: pass - * 2: hops - * 3: numeric - * 4: desc - */ - bool OnServer(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override - { - do_server(source, params[0], Anope::string(params[2]).is_pos_number_only() ? convertTo<unsigned>(params[2]) : 0, params[4], params[3]); + s->Sync(true); return true; } +}; - bool OnTopic(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override - { - Channel *c = findchan(params[0]); - - if (!c) - { - Log() << "TOPIC " << params[1] << " for nonexistent channel " << params[0]; - return true; - } - - c->ChangeTopicInternal(source, (params.size() > 1 ? params[1] : ""), Anope::CurTime); +struct IRCDMessageFHost : IRCDMessage +{ + IRCDMessageFHost(const Anope::string &n) : IRCDMessage(n, 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + source.GetUser()->SetDisplayedHost(params[0]); return true; } +}; - virtual bool OnCapab(const Anope::string &, const std::vector<Anope::string> &) anope_override = 0; +struct IRCDMessageFJoin : IRCDMessage +{ + IRCDMessageFJoin() : IRCDMessage("FJOIN", 2) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); } - bool OnSJoin(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { Channel *c = findchan(params[0]); time_t ts = Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : 0; @@ -425,7 +402,7 @@ class InspircdIRCdMessage : public IRCdMessage if (!modes.empty()) modes.erase(modes.begin()); /* Set the modes internally */ - c->SetModesInternal(NULL, modes); + c->SetModesInternal(source, modes); } spacesepstream sep(params[params.size() - 1]); @@ -468,7 +445,7 @@ class InspircdIRCdMessage : public IRCdMessage * This will enforce secureops etc on the user */ for (std::list<ChannelMode *>::iterator it = Status.begin(), it_end = Status.end(); it != it_end; ++it) - c->SetModeInternal(NULL, *it, buf); + c->SetModeInternal(source, *it, buf); /* Now set whatever modes this user is allowed to have on the channel */ chan_set_correct_modes(u, c, 1, true); @@ -495,33 +472,268 @@ class InspircdIRCdMessage : public IRCdMessage } }; -bool event_idle(const Anope::string &source, const std::vector<Anope::string> ¶ms) +struct IRCDMessageFMode : IRCDMessage +{ + IRCDMessageFMode() : IRCDMessage("FMODE", 3) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + /* :source FMODE #test 12345678 +nto foo */ + + Anope::string modes = params[2]; + for (unsigned n = 3; n < params.size(); ++n) + modes += " " + params[n]; + + Channel *c = findchan(params[0]); + time_t ts; + + try + { + ts = convertTo<time_t>(params[1]); + } + catch (const ConvertException &) + { + ts = Anope::CurTime; + } + + if (c) + c->SetModesInternal(source, modes, ts); + + return true; + } +}; + +struct IRCDMessageFTopic : IRCDMessage +{ + IRCDMessageFTopic() : IRCDMessage("FTOPIC", 4) { } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + /* :source FTOPIC channel ts setby :topic */ + + Channel *c = findchan(params[0]); + if (c) + c->ChangeTopicInternal(params[2], params[3], Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : Anope::CurTime); + + return true; + } +}; + +struct IRCDMessageIdle : IRCDMessage +{ + IRCDMessageIdle() : IRCDMessage("IDLE", 1) { } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + const BotInfo *bi = findbot(params[0]); + if (bi) + UplinkSocket::Message(bi) << "IDLE " << source.GetSource() << " " << start_time << " " << (Anope::CurTime - bi->lastmsg); + return true; + } +}; + +/* + * source = numeric of the sending server + * params[0] = uuid + * params[1] = metadata name + * params[2] = data + */ +struct IRCDMessageMetadata : IRCDMessage +{ + IRCDMessageMetadata() : IRCDMessage("METADATA", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + if (params[1].equals_cs("accountname")) + { + User *u = finduser(params[0]); + NickCore *nc = findcore(params[2]); + if (u && nc) + { + u->Login(nc); + + const NickAlias *user_na = findnick(u->nick); + if (!Config->NoNicknameOwnership && nickserv && user_na && user_na->nc == nc && user_na->nc->HasFlag(NI_UNCONFIRMED) == false) + u->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); + } + } + + /* + * possible incoming ssl_cert messages: + * Received: :409 METADATA 409AAAAAA ssl_cert :vTrSe c38070ce96e41cc144ed6590a68d45a6 <...> <...> + * Received: :409 METADATA 409AAAAAC ssl_cert :vTrSE Could not get peer certificate: error:00000000:lib(0):func(0):reason(0) + */ + else if (params[1].equals_cs("ssl_cert")) + { + User *u = finduser(params[0]); + if (!u) + return true; + std::string data = params[2].c_str(); + size_t pos1 = data.find(' ') + 1; + size_t pos2 = data.find(' ', pos1); + if ((pos2 - pos1) >= 32) // inspircd supports md5 and sha1 fingerprint hashes -> size 32 or 40 bytes. + { + u->fingerprint = data.substr(pos1, pos2 - pos1); + FOREACH_MOD(I_OnFingerprint, OnFingerprint(u)); + } + } + return true; + } +}; + +struct IRCDMessageMode : IRCDMessage +{ + IRCDMessageMode() : IRCDMessage("MODE", 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + if (ircdproto->IsChannelValid(params[0])) + { + Channel *c = findchan(params[0]); + time_t ts; + + try + { + ts = convertTo<time_t>(params[1]); + } + catch (const ConvertException &) + { + ts = Anope::CurTime; + } + + if (c) + c->SetModesInternal(source, params[2], ts); + } + else + { + /* InspIRCd lets opers change another + users modes, we have to kludge this + as it slightly breaks RFC1459 + */ + User *u = source.GetUser(); + // This can happen with server-origin modes. + if (!u) + u = finduser(params[0]); + // if it's still null, drop it like fire. + // most likely situation was that server introduced a nick which we subsequently akilled + if (u) + u->SetModesInternal("%s", params[1].c_str()); + } + + return true; + } +}; + +struct IRCDMessageNick : IRCDMessage +{ + IRCDMessageNick() : IRCDMessage("NICK", 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + source.GetUser()->ChangeNick(params[0]); + return true; + } +}; + +struct IRCDMessageOperType : IRCDMessage +{ + IRCDMessageOperType() : IRCDMessage("OPERTYPE", 0) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); SetFlag(IRCDMESSAGE_REQUIRE_USER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + /* opertype is equivalent to mode +o because servers + dont do this directly */ + User *u = source.GetUser(); + if (!u->HasMode(UMODE_OPER)) + u->SetModesInternal("+o"); + + return true; + } +}; + +struct IRCDMessageRSQuit : IRCDMessage { - const BotInfo *bi = findbot(params[0]); - if (bi) - UplinkSocket::Message(bi) << "IDLE " << source << " " << start_time << " " << (Anope::CurTime - bi->lastmsg); - return true; -} + IRCDMessageRSQuit() : IRCDMessage("RSQUIT", 1) { } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + Server *s = Server::Find(params[0]); + if (!s) + return true; + + /* On InspIRCd we must send a SQUIT when we recieve RSQUIT for a server we have juped */ + if (s->HasFlag(SERVER_JUPED)) + UplinkSocket::Message(Me) << "SQUIT " << s->GetSID() << " :" << (params.size() > 1 ? params[1].c_str() : ""); + + FOREACH_MOD(I_OnServerQuit, OnServerQuit(s)); + + s->Delete(s->GetName() + " " + s->GetUplink()->GetName()); + + return true; + } +}; -bool event_time(const Anope::string &source, const std::vector<Anope::string> ¶ms) +struct IRCDMessageServer : IRCDMessage { - if (params.size() < 2) + IRCDMessageServer() : IRCDMessage("SERVER", 5) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + + /* + * [Nov 04 00:08:46.308435 2009] debug: Received: SERVER irc.inspircd.com pass 0 964 :Testnet Central! + * 0: name + * 1: pass + * 2: hops + * 3: numeric + * 4: desc + */ + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + unsigned int hops = Anope::string(params[2]).is_pos_number_only() ? convertTo<unsigned>(params[2]) : 0; + new Server(source.GetServer() == NULL ? Me : source.GetServer(), params[0], hops, params[4], params[3]); return true; + } +}; - UplinkSocket::Message(Me) << "TIME " << source << " " << params[1] << " " << Anope::CurTime; - return true; -} +struct IRCDMessageTime : IRCDMessage +{ + IRCDMessageTime() : IRCDMessage("TIME", 2) { } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + UplinkSocket::Message(Me) << "TIME " << source.GetSource() << " " << params[1] << " " << Anope::CurTime; + return true; + } +}; -bool event_rsquit(const Anope::string &source, const std::vector<Anope::string> ¶ms) +struct IRCDMessageUID : IRCDMessage { - /* On InspIRCd we must send a SQUIT when we recieve RSQUIT for a server we have juped */ - Server *s = Server::Find(params[0]); - if (s && s->HasFlag(SERVER_JUPED)) - UplinkSocket::Message(Me) << "SQUIT " << s->GetSID() << " :" << (params.size() > 1 ? params[1].c_str() : ""); + IRCDMessageUID() : IRCDMessage("UID", 8) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); } + + /* + * [Nov 03 22:09:58.176252 2009] debug: Received: :964 UID 964AAAAAC 1225746297 w00t2 localhost testnet.user w00t 127.0.0.1 1225746302 +iosw +ACGJKLNOQcdfgjklnoqtx :Robin Burchell <w00t@inspircd.org> + * 0: uid + * 1: ts + * 2: nick + * 3: host + * 4: dhost + * 5: ident + * 6: ip + * 7: signon + * 8+: modes and params -- IMPORTANT, some modes (e.g. +s) may have parameters. So don't assume a fixed position of realname! + * last: realname + */ + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + time_t ts = convertTo<time_t>(params[1]); - ircdmessage->OnSQuit(source, params); + Anope::string modes = params[8]; + for (unsigned i = 9; i < params.size() - 1; ++i) + modes += " " + params[i]; - return true; -} + User *u = new User(params[2], params[5], params[3], params[4], params[6], source.GetServer(), params[params.size() - 1], ts, modes, params[0]); + if (u->server->IsSynced() && nickserv) + nickserv->Validate(u); + return true; + } +}; diff --git a/modules/protocol/inspircd11.cpp b/modules/protocol/inspircd11.cpp index 7470d61aa..1eba8321f 100644 --- a/modules/protocol/inspircd11.cpp +++ b/modules/protocol/inspircd11.cpp @@ -13,31 +13,6 @@ #include "module.h" -IRCDVar myIrcd = { - "InspIRCd 1.1", /* ircd name */ - "+I", /* Modes used by pseudoclients */ - 1, /* SVSNICK */ - 1, /* Vhost */ - 1, /* Supports SNlines */ - 1, /* Supports SQlines */ - 1, /* Supports SZlines */ - 1, /* Join 2 Message */ - 0, /* Chan SQlines */ - 0, /* Quit on Kill */ - 1, /* vidents */ - 1, /* svshold */ - 0, /* time stamp on mode */ - 1, /* O:LINE */ - 1, /* UMODE */ - 1, /* No Knock requires +i */ - 0, /* Can remove User Channel Modes with SVSMODE */ - 0, /* Sglines are not enforced until user reconnects */ - 0, /* ts6 */ - "$", /* TLD Prefix for Global */ - 20, /* Max number of modes we can send per line */ - 0 /* IRCd sends a SSL users certificate fingerprint */ -}; - static bool has_servicesmod = false; static bool has_globopsmod = false; static bool has_svsholdmod = false; @@ -45,40 +20,60 @@ static bool has_chghostmod = false; static bool has_chgidentmod = false; static bool has_hidechansmod = false; -/* CHGHOST */ -void inspircd_cmd_chghost(const Anope::string &nick, const Anope::string &vhost) +class InspIRCdProto : public IRCDProto { - const BotInfo *bi = findbot(Config->OperServ); - if (has_chghostmod) + public: + InspIRCdProto() : IRCDProto("InspIRCd 1.1") { - if (nick.empty() || vhost.empty()) - return; - UplinkSocket::Message(bi) << "CHGHOST " << nick << " " << vhost; + DefaultPseudoclientModes = "+I"; + CanSVSNick = true; + CanSetVHost = true; + CanSetVIdent = true; + CanSNLine = true; + CanSQLine = true; + CanSZLine = true; + CanSVSHold = true; + CanSVSO = true; + MaxModes = 20; } - else + private: + + Anope::string current_pass; + + void inspircd_cmd_chgident(const Anope::string &nick, const Anope::string &vIdent) { - if (bi) - ircdproto->SendGlobops(bi, "CHGHOST not loaded!"); + if (has_chgidentmod) + { + if (nick.empty() || vIdent.empty()) + return; + UplinkSocket::Message(findbot(Config->OperServ)) << "CHGIDENT " << nick << " " << vIdent; + } + else + Log() << "CHGIDENT not loaded!"; } -} -bool event_idle(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - const BotInfo *bi = findbot(params[0]); - UplinkSocket::Message(bi) << "IDLE " << source << " " << start_time << " " << (bi ? Anope::CurTime - bi->lastmsg : 0); - return true; -} + void inspircd_cmd_chghost(const Anope::string &nick, const Anope::string &vhost) + { + if (has_chghostmod) + { + if (nick.empty() || vhost.empty()) + return; + UplinkSocket::Message(findbot(Config->OperServ)) << "CHGHOST " << nick << " " << vhost; + } + else + Log() << "CHGHOST not loaded!"; + } -static Anope::string currentpass; + void SendGlobalNotice(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override + { + UplinkSocket::Message(bi) << "NOTICE $" << dest->GetName() << " :" << msg; + } -/* PASS */ -void inspircd_cmd_pass(const Anope::string &pass) -{ - currentpass = pass; -} + void SendGlobalPrivmsg(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override + { + UplinkSocket::Message(bi) << "PRIVMSG $" << dest->GetName() << " :" << msg; + } -class InspIRCdProto : public IRCDProto -{ void SendAkillDel(const XLine *x) anope_override { if (x->IsRegex() || x->HasNickOrReal()) @@ -159,12 +154,18 @@ class InspIRCdProto : public IRCDProto UplinkSocket::Message(Me) << "ADDLINE G " << x->Mask << " " << x->By << " " << Anope::CurTime << " " << timeleft << " :" << x->GetReason(); } - void SendSVSKillInternal(const BotInfo *source, const User *user, const Anope::string &buf) anope_override + void SendSVSKillInternal(const BotInfo *source, User *user, const Anope::string &buf) anope_override { if (source) + { UplinkSocket::Message(source) << "KILL " << user->nick << " :" << buf; + user->KillInternal(source->nick, buf); + } else + { UplinkSocket::Message(Me) << "KILL " << user->nick << " :" << buf; + user->KillInternal(Me->GetName(), buf); + } } void SendNumericInternal(int numeric, const Anope::string &dest, const Anope::string &buf) anope_override @@ -206,7 +207,7 @@ class InspIRCdProto : public IRCDProto /* SERVER services-dev.chatspike.net password 0 :Description here */ void SendServer(const Server *server) anope_override { - UplinkSocket::Message(Me) << "SERVER " << server->GetName() << " " << currentpass << " " << server->GetHops() << " :" << server->GetDescription(); + UplinkSocket::Message(Me) << "SERVER " << server->GetName() << " " << current_pass << " " << server->GetHops() << " :" << server->GetDescription(); } /* JOIN */ @@ -259,24 +260,11 @@ class InspIRCdProto : public IRCDProto void SendConnect() anope_override { - inspircd_cmd_pass(Config->Uplinks[CurrentUplink]->password); + current_pass = Config->Uplinks[CurrentUplink]->password; SendServer(Me); UplinkSocket::Message() << "BURST"; Module *enc = ModuleManager::FindFirstOf(ENCRYPTION); - UplinkSocket::Message(Me) << "VERSION :Anope-" << Anope::Version() << " " << Me->GetName() << " :" << ircd->name << " - (" << (enc ? enc->name : "unknown") << ") -- " << Anope::VersionBuildString(); - } - - /* CHGIDENT */ - void inspircd_cmd_chgident(const Anope::string &nick, const Anope::string &vIdent) - { - if (has_chgidentmod) - { - if (nick.empty() || vIdent.empty()) - return; - UplinkSocket::Message(findbot(Config->OperServ)) << "CHGIDENT " << nick << " " << vIdent; - } - else - Log() << "CHGIDENT not loaded!"; + UplinkSocket::Message(Me) << "VERSION :Anope-" << Anope::Version() << " " << Me->GetName() << " :" << this->GetProtocolName() << " - (" << (enc ? enc->name : "unknown") << ") -- " << Anope::VersionBuildString(); } /* SVSHOLD - set */ @@ -355,73 +343,11 @@ class ChannelModeFlood : public ChannelModeParam } }; -class InspircdIRCdMessage : public IRCdMessage +struct IRCDMessageCapab : IRCDMessage { - public: - bool OnMode(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (params.size() < 2) - return true; - - if (params[0][0] == '#' || params[0][0] == '&') - do_cmode(source, params[0], params[1], params[2]); - else - do_umode(params[0], params[1]); - - return true; - } - - bool OnNick(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (params.size() == 8) - { - time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo<time_t>(params[0]) : 0; - - User *user = do_nick("", params[1], params[4], params[2], source, params[7], ts, params[6], params[3], "", params[5]); - if (user && nickserv) - { - user->SetCloakedHost(params[3]); - - NickAlias *na = findnick(user->nick); - Anope::string *svidbuf = na ? na->nc->GetExt<ExtensibleItemClass<Anope::string> *>("authenticationtoken") : NULL; - if (na && svidbuf && *svidbuf == params[0]) - { - NickCore *nc = na->nc; - user->Login(nc); - if (!Config->NoNicknameOwnership && na->nc->HasFlag(NI_UNCONFIRMED) == false) - user->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); - } - else if (nickserv) - nickserv->Validate(user); - } - } - else if (params.size() == 1) - do_nick(source, params[0], "", "", "", "", 0, "", "", "", ""); - return true; - } - - bool OnServer(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override - { - do_server(source, params[0], Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0, params[2], ""); - return true; - } - - bool OnTopic(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override - { - Channel *c = findchan(params[0]); - - if (!c) - { - Log() << "TOPIC " << (params.size() > 1 ? params[1] : "") << " for nonexistent channel " << params[0]; - return true; - } + IRCDMessageCapab() : IRCDMessage("CAPAB", 1) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } - c->ChangeTopicInternal(source, (params.size() > 1 ? params[1] : ""), Anope::CurTime); - - return true; - } - - bool OnCapab(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override + bool Run(MessageSource &, const std::vector<Anope::string> ¶ms) anope_override { if (params[0].equals_cs("START")) { @@ -433,7 +359,7 @@ class InspircdIRCdMessage : public IRCdMessage has_chgidentmod = false; has_hidechansmod = false; } - else if (params[0].equals_cs("MODULES")) + else if (params[0].equals_cs("MODULES") && params.size() > 1) { if (params[1].find("m_globops.so") != Anope::string::npos) has_globopsmod = true; @@ -448,7 +374,7 @@ class InspircdIRCdMessage : public IRCdMessage if (params[1].find("m_hidechans.so") != Anope::string::npos) has_hidechansmod = true; } - else if (params[0].equals_cs("CAPABILITIES")) + else if (params[0].equals_cs("CAPABILITIES") && params.size() > 1) { spacesepstream ssep(params[1]); Anope::string capab; @@ -614,7 +540,7 @@ class InspircdIRCdMessage : public IRCdMessage else if (capab.find("MAXMODES=") != Anope::string::npos) { Anope::string maxmodes(capab.begin() + 9, capab.end()); - ircd->maxmodes = maxmodes.is_pos_number_only() ? convertTo<unsigned>(maxmodes) : 3; + ircdproto->MaxModes = maxmodes.is_pos_number_only() ? convertTo<unsigned>(maxmodes) : 3; } } } @@ -647,15 +573,69 @@ class InspircdIRCdMessage : public IRCdMessage Log() << "CHGHOST missing, Usage disabled until module is loaded."; if (!has_chgidentmod) Log() << "CHGIDENT missing, Usage disabled until module is loaded."; - ircd->svshold = has_svsholdmod; + ircdproto->CanSVSHold = has_svsholdmod; } - IRCdMessage::OnCapab(source, params); + return true; + } +}; + +struct IRCDMessageChgIdent : IRCDMessage +{ + IRCDMessageChgIdent(const Anope::string &n) : IRCDMessage(n, 2) { } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + User *u = finduser(params[0]); + if (!u) + { + Log(LOG_DEBUG) << "CHGIDENT for nonexistent user " << params[0]; + return true; + } + + u->SetIdent(params[1]); + return true; + } +}; + +struct IRCDMessageChgName : IRCDMessage +{ + IRCDMessageChgName(const Anope::string &n) : IRCDMessage(n, 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + source.GetUser()->SetRealname(params[0]); + return true; + } +}; + +struct IRCDMessageEndBurst : IRCDMessage +{ + IRCDMessageEndBurst() : IRCDMessage("ENDBURST", 0) { } + bool Run(MessageSource &, const std::vector<Anope::string> ¶ms) anope_override + { + Me->GetLinks().front()->Sync(true); return true; } +}; + +struct IRCDMessageFHost : IRCDMessage +{ + IRCDMessageFHost(const Anope::string &n) : IRCDMessage(n, 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } - bool OnSJoin(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + source.GetUser()->SetDisplayedHost(params[0]); + return true; + } +}; + +struct IRCDMessageFJoin : IRCDMessage +{ + IRCDMessageFJoin() : IRCDMessage("FJOIN", 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { Channel *c = findchan(params[0]); time_t ts = Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : 0; @@ -719,7 +699,7 @@ class InspircdIRCdMessage : public IRCdMessage * This will enforce secureops etc on the user */ for (std::list<ChannelMode *>::iterator it = Status.begin(), it_end = Status.end(); it != it_end; ++it) - c->SetModeInternal(NULL, *it, buf); + c->SetModeInternal(source, *it, buf); /* Now set whatever modes this user is allowed to have on the channel */ chan_set_correct_modes(u, c, 1, true); @@ -746,206 +726,209 @@ class InspircdIRCdMessage : public IRCdMessage } }; -bool event_ftopic(const Anope::string &source, const std::vector<Anope::string> ¶ms) +struct IRCDMessageFMode : IRCDMessage { - /* :source FTOPIC channel ts setby :topic */ - if (params.size() < 4) - return true; - - Channel *c = findchan(params[0]); - if (!c) + IRCDMessageFMode() : IRCDMessage("FMODE", 3) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - Log() << "TOPIC for nonexistant channel " << params[0]; - return true; - } + /* :source FMODE #test 12345678 +nto foo */ - c->ChangeTopicInternal(params[2], params[3], Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : Anope::CurTime); + Channel *c = findchan(params[0]); + if (!c) + return true; + time_t ts = Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : 0; - return true; -} + /* TS's are equal now, so we can proceed with parsing */ + // For fun, modes sometimes get sent without a mode prefix + Anope::string modes = "+" + params[2]; + for (unsigned n = 3; n < params.size(); ++n) + modes += " " + params[n]; -bool event_opertype(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - /* opertype is equivalent to mode +o because servers - dont do this directly */ - User *u = finduser(source); - if (u && !u->HasMode(UMODE_OPER)) - { - std::vector<Anope::string> newparams; - newparams.push_back(source); - newparams.push_back("+o"); - return ircdmessage->OnMode(source, newparams); - } - else + c->SetModesInternal(source, modes, ts); return true; -} + } +}; -bool event_fmode(const Anope::string &source, const std::vector<Anope::string> ¶ms) +struct IRCDMessageFTopic : IRCDMessage { - /* :source FMODE #test 12345678 +nto foo */ - if (params.size() < 3) - return true; + IRCDMessageFTopic() : IRCDMessage("FTOPIC", 4) { } - Channel *c = findchan(params[0]); - /* Checking the TS for validity to avoid desyncs */ - if (c) + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - time_t ts = Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : 0; - if (c->creation_time > ts) - { - /* Our TS is bigger, we should lower it */ - c->creation_time = ts; - c->Reset(); - } - else if (c->creation_time < ts) - /* The TS we got is bigger, we should ignore this message. */ - return true; - } - else - /* Got FMODE for a non-existing channel */ - return true; - - /* TS's are equal now, so we can proceed with parsing */ - std::vector<Anope::string> newparams; // channel, modes, ts - newparams.push_back(params[0]); - // For fun, modes sometimes get sent without a mode prefix - Anope::string modes = "+" + params[2]; - for (unsigned n = 3; n < params.size(); ++n) - modes += " " + params[n]; - newparams.push_back(modes); - newparams.push_back(params[1]); - - return ircdmessage->OnMode(source, newparams); -} + Channel *c = findchan(params[0]); + if (c) + c->ChangeTopicInternal(params[2], params[3], Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : Anope::CurTime); -bool event_rsquit(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.empty() || params.size() > 3) return true; + } +}; - std::vector<Anope::string> p; - /* Horrible workaround to an insp bug (#) in how RSQUITs are sent - mark */ - if (params.size() > 1 && Config->ServerName.equals_cs(params[0])) - p.push_back(params[1]); - else - p.push_back(params[0]); - - ircdmessage->OnSQuit(source, p); - - return true; -} - -bool event_setname(const Anope::string &source, const std::vector<Anope::string> ¶ms) +struct IRCDMessageIdle : IRCDMessage { - if (params.empty()) - return true; + IRCDMessageIdle() : IRCDMessage("IDLE", 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } - User *u = finduser(source); - if (!u) + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - Log(LOG_DEBUG) << "SETNAME for nonexistent user " << source; + const BotInfo *bi = findbot(params[0]); + UplinkSocket::Message(bi) << "IDLE " << source.GetSource() << " " << start_time << " " << (bi ? Anope::CurTime - bi->lastmsg : 0); return true; } +}; - u->SetRealname(params[0]); - return true; -} - -bool event_chgname(const Anope::string &source, const std::vector<Anope::string> ¶ms) +struct IRCDMessageMode : IRCDMessage { - if (params.size() < 2) - return true; + IRCDMessageMode() : IRCDMessage("MODE", 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } - User *u = finduser(source); - if (!u) + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - Log(LOG_DEBUG) << "FNAME for nonexistent user " << source; + if (ircdproto->IsChannelValid(params[0])) + { + Channel *c = findchan(params[0]); + time_t ts; + + try + { + ts = convertTo<time_t>(params[2]); + } + catch (const ConvertException &) + { + ts = Anope::CurTime; + } + + if (c) + c->SetModesInternal(source, params[1], ts); + } + else + { + User *u = finduser(params[0]); + if (u) + u->SetModesInternal("%s", params[1].c_str()); + } + return true; } +}; - u->SetRealname(params[0]); - return true; -} - -bool event_setident(const Anope::string &source, const std::vector<Anope::string> ¶ms) +struct IRCDMessageNick : IRCDMessage { - if (!params.empty()) - return true; + IRCDMessageNick() : IRCDMessage("NICK", 1) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } - User *u = finduser(source); - if (!u) + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - Log(LOG_DEBUG) << "SETIDENT for nonexistent user " << source; + if (params.size() == 8 && source.GetServer()) + { + time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo<time_t>(params[0]) : Anope::CurTime; + + User *user = new User(params[1], params[4], params[2], params[3], params[6], source.GetServer(), params[7], ts, params[5]); + if (nickserv) + { + NickAlias *na = findnick(user->nick); + Anope::string *svidbuf = na ? na->nc->GetExt<ExtensibleItemClass<Anope::string> *>("authenticationtoken") : NULL; + if (na && svidbuf && *svidbuf == params[0]) + { + NickCore *nc = na->nc; + user->Login(nc); + if (!Config->NoNicknameOwnership && na->nc->HasFlag(NI_UNCONFIRMED) == false) + user->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); + } + else if (nickserv) + nickserv->Validate(user); + } + } + else if (params.size() == 1 && source.GetUser()) + source.GetUser()->ChangeNick(params[0]); + return true; } +}; - u->SetIdent(params[0]); - return true; -} - -bool event_chgident(const Anope::string &source, const std::vector<Anope::string> ¶ms) +struct IRCDMessageOperType : IRCDMessage { - if (params.size() < 2) - return true; + IRCDMessageOperType() : IRCDMessage("OPERTYPE", 0) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); SetFlag(IRCDMESSAGE_REQUIRE_USER); } - User *u = finduser(params[0]); - if (!u) + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - Log(LOG_DEBUG) << "CHGIDENT for nonexistent user " << params[0]; + /* opertype is equivalent to mode +o because servers + dont do this directly */ + User *u = source.GetUser(); + if (!u->HasMode(UMODE_OPER)) + u->SetModesInternal("+o"); + return true; } +}; - u->SetIdent(params[1]); - return true; -} - -bool event_sethost(const Anope::string &source, const std::vector<Anope::string> ¶ms) +struct IRCDMessageRSQuit : IRCDMessage { - if (params.empty()) - return true; + IRCDMessageRSQuit() : IRCDMessage("RSQUIT", 0) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } - User *u = finduser(source); - if (!u) + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - Log(LOG_DEBUG) << "SETHOST for nonexistent user " << source; - return true; - } + if (params.empty() || params.size() > 3) + return true; - u->SetDisplayedHost(params[0]); - return true; -} + Server *s; + /* Horrible workaround to an insp bug (#) in how RSQUITs are sent - mark */ + if (params.size() > 1 && Config->ServerName.equals_cs(params[0])) + s = Server::Find(params[1]); + else + s = Server::Find(params[0]); + source.GetServer()->Delete(source.GetServer()->GetName() + " " + source.GetServer()->GetUplink()->GetName()); -bool event_chghost(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.empty()) return true; + } +}; - User *u = finduser(source); - if (!u) +struct IRCDMessageServer : IRCDMessage +{ + IRCDMessageServer() : IRCDMessage("SERVER", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - Log(LOG_DEBUG) << "FHOST for nonexistent user " << source; + unsigned int hops = Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0; + new Server(source.GetServer() == NULL ? Me : source.GetServer(), params[0], hops, params[2]); return true; } - - u->SetDisplayedHost(params[0]); - return true; -} - -bool event_endburst(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - Me->GetLinks().front()->Sync(true); - return true; -} +}; class ProtoInspIRCd : public Module { - Message message_endburst, message_rsquit, message_svsmode, message_chghost, message_chgident, message_chgname, - message_sethost, message_setident, message_setname, message_fmode, message_ftopic, message_opertype, - message_idle, message_fjoin; - InspIRCdProto ircd_proto; - InspircdIRCdMessage ircd_message; + + /* Core message handlers */ + CoreIRCDMessageAway core_message_away; + CoreIRCDMessageCapab core_message_capab; + CoreIRCDMessageError core_message_error; + CoreIRCDMessageJoin core_message_join; + CoreIRCDMessageKill core_message_kill; + CoreIRCDMessageMOTD core_message_motd; + CoreIRCDMessagePart core_message_part; + CoreIRCDMessagePing core_message_ping; + CoreIRCDMessagePrivmsg core_message_privmsg; + CoreIRCDMessageQuit core_message_quit; + CoreIRCDMessageSQuit core_message_squit; + CoreIRCDMessageStats core_message_stats; + CoreIRCDMessageTime core_message_time; + CoreIRCDMessageTopic core_message_topic; + CoreIRCDMessageVersion core_message_version; + + /* Our message handlers */ + IRCDMessageCapab message_capab; + IRCDMessageChgIdent message_chgident, message_setident; + IRCDMessageChgName message_chgname, message_setname; + IRCDMessageEndBurst message_endburst; + IRCDMessageFHost message_fhost, message_sethost; + IRCDMessageFJoin message_fjoin; + IRCDMessageFMode message_fmode; + IRCDMessageFTopic message_ftopic; + IRCDMessageIdle message_idle; + IRCDMessageMode message_mode; + IRCDMessageNick message_nick; + IRCDMessageOperType message_opertype; + IRCDMessageRSQuit message_rsquit; + IRCDMessageServer message_server; void AddModes() { @@ -960,20 +943,12 @@ class ProtoInspIRCd : public Module public: ProtoInspIRCd(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL), - message_endburst("ENDBURST", event_endburst), message_rsquit("RSQUIT", event_rsquit), - message_svsmode("SVSMODE", OnMode), message_chghost("CHGHOST", event_chghost), - message_chgident("CHGIDENT", event_chgident), message_chgname("CHGNAME", event_chgname), - message_sethost("SETHOST", event_sethost), message_setident("SETIDENT", event_setident), - message_setname("SETNAME", event_setname), message_fmode("FMODE", event_fmode), - message_ftopic("FTOPIC", event_ftopic), message_opertype("OPERTYPE", event_opertype), - message_idle("IDLE", event_idle), message_fjoin("FJOIN", OnSJoin) + message_chgident("CHGIDENT"), message_setident("SETIDENT"), + message_chgname("CHGNAME"), message_setname("SETNAME"), + message_fhost("FHOST"), message_sethost("SETHOST") { this->SetAuthor("Anope"); - pmodule_ircd_var(&myIrcd); - pmodule_ircd_proto(&this->ircd_proto); - pmodule_ircd_message(&this->ircd_message); - Capab.insert("NOQUIT"); this->AddModes(); diff --git a/modules/protocol/inspircd12.cpp b/modules/protocol/inspircd12.cpp index e20e9c87d..c780e8299 100644 --- a/modules/protocol/inspircd12.cpp +++ b/modules/protocol/inspircd12.cpp @@ -20,250 +20,15 @@ static bool has_chgidentmod = false; static bool has_rlinemod = false; #include "inspircd-ts6.h" -IRCDVar myIrcd = { - "InspIRCd 1.2", /* ircd name */ - "+I", /* Modes used by pseudoclients */ - 1, /* SVSNICK */ - 1, /* Vhost */ - 0, /* Supports SNlines */ - 1, /* Supports SQlines */ - 1, /* Supports SZlines */ - 0, /* Join 2 Message */ - 0, /* Chan SQlines */ - 0, /* Quit on Kill */ - 1, /* vidents */ - 1, /* svshold */ - 0, /* time stamp on mode */ - 0, /* O:LINE */ - 1, /* UMODE */ - 1, /* No Knock requires +i */ - 0, /* Can remove User Channel Modes with SVSMODE */ - 0, /* Sglines are not enforced until user reconnects */ - 1, /* ts6 */ - "$", /* TLD Prefix for Global */ - 20, /* Max number of modes we can send per line */ - 1, /* IRCd sends a SSL users certificate fingerprint */ -}; - static bool has_servicesmod = false; static bool has_svsholdmod = false; static bool has_hidechansmod = false; -bool event_ftopic(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - /* :source FTOPIC channel ts setby :topic */ - if (params.size() < 4) - return true; - - Channel *c = findchan(params[0]); - if (!c) - { - Log(LOG_DEBUG) << "TOPIC " << params[3] << " for nonexistent channel " << params[0]; - return true; - } - - c->ChangeTopicInternal(params[2], params[3], Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : Anope::CurTime); - - return true; -} - -bool event_opertype(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - /* opertype is equivalent to mode +o because servers - dont do this directly */ - User *u = finduser(source); - if (u && !u->HasMode(UMODE_OPER)) - { - std::vector<Anope::string> newparams; - newparams.push_back(source); - newparams.push_back("+o"); - return ircdmessage->OnMode(source, newparams); - } - - return true; -} - -bool event_fmode(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - /* :source FMODE #test 12345678 +nto foo */ - if (params.size() < 3) - return true; - - Channel *c = findchan(params[0]); - if (!c) - return true; - - /* Checking the TS for validity to avoid desyncs */ - time_t ts = Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : 0; - if (c->creation_time > ts) - { - /* Our TS is bigger, we should lower it */ - c->creation_time = ts; - c->Reset(); - } - else if (c->creation_time < ts) - /* The TS we got is bigger, we should ignore this message. */ - return true; - - /* TS's are equal now, so we can proceed with parsing */ - std::vector<Anope::string> newparams; - newparams.push_back(params[0]); - newparams.push_back(params[1]); - Anope::string modes = params[2]; - for (unsigned n = 3; n < params.size(); ++n) - modes += " " + params[n]; - newparams.push_back(modes); - - return ircdmessage->OnMode(source, newparams); -} - -bool event_setname(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - User *u = finduser(source); - if (!u) - { - Log(LOG_DEBUG) << "SETNAME for nonexistent user " << source; - return true; - } - else if (params.empty()) - return true; - - u->SetRealname(params[0]); - return true; -} - -bool event_chgname(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - User *u = finduser(source); - - if (!u) - { - Log(LOG_DEBUG) << "FNAME for nonexistent user " << source; - return true; - } - else if (params.empty()) - return true; - - u->SetRealname(params[0]); - return true; -} - -bool event_setident(const Anope::string &source, const std::vector<Anope::string> ¶ms) +class InspIRCd12Proto : public InspIRCdTS6Proto { - User *u = finduser(source); - - if (!u) - { - Log(LOG_DEBUG) << "SETIDENT for nonexistent user " << source; - return true; - } - - u->SetIdent(params[0]); - return true; -} - -bool event_chgident(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - User *u = finduser(params[0]); - - if (!u) - { - Log(LOG_DEBUG) << "CHGIDENT for nonexistent user " << params[0]; - return true; - } - - u->SetIdent(params[1]); - return true; -} - -bool event_sethost(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - User *u = finduser(source); - - if (!u) - { - Log(LOG_DEBUG) << "SETHOST for nonexistent user " << source; - return true; - } - - u->SetDisplayedHost(params[0]); - return true; -} - - -bool event_chghost(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - User *u = finduser(source); - - if (!u) - { - Log(LOG_DEBUG) << "FHOST for nonexistent user " << source; - return true; - } - - u->SetDisplayedHost(params[0]); - return true; -} - - -/* - * source = numeric of the sending server - * params[0] = uuid - * params[1] = metadata name - * params[2] = data - */ -bool event_metadata(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() < 3) - return true; - else if (params[1].equals_cs("accountname")) - { - User *u = finduser(params[0]); - NickCore *nc = findcore(params[2]); - if (u && nc) - { - u->Login(nc); - - const NickAlias *user_na = findnick(u->nick); - if (!Config->NoNicknameOwnership && nickserv && user_na && user_na->nc == nc && user_na->nc->HasFlag(NI_UNCONFIRMED) == false) - u->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); - } - } - - /* - * possible incoming ssl_cert messages: - * Received: :409 METADATA 409AAAAAA ssl_cert :vTrSe c38070ce96e41cc144ed6590a68d45a6 <...> <...> - * Received: :409 METADATA 409AAAAAC ssl_cert :vTrSE Could not get peer certificate: error:00000000:lib(0):func(0):reason(0) - */ - else if (params[1].equals_cs("ssl_cert")) - { - User *u = finduser(params[0]); - if (!u) - return true; - std::string data = params[2].c_str(); - size_t pos1 = data.find(' ') + 1; - size_t pos2 = data.find(' ', pos1); - if ((pos2 - pos1) >= 32) // inspircd supports md5 and sha1 fingerprint hashes -> size 32 or 40 bytes. - { - u->fingerprint = data.substr(pos1, pos2 - pos1); - FOREACH_MOD(I_OnFingerprint, OnFingerprint(u)); - } - } - return true; -} - -bool event_endburst(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - Server *s = Server::Find(source); - - if (!s) - throw CoreException("Got ENDBURST without a source"); - - Log(LOG_DEBUG) << "Processed ENDBURST for " << s->GetName(); - - s->Sync(true); - return true; -} + public: + InspIRCd12Proto() : InspIRCdTS6Proto("InspIRCd 1.2") { } +}; class InspIRCdExtBan : public ChannelModeList { @@ -316,37 +81,11 @@ class InspIRCdExtBan : public ChannelModeList } }; -class Inspircd12IRCdMessage : public InspircdIRCdMessage +struct IRCDMessageCapab : IRCDMessage { - public: - /* - * [Nov 03 22:09:58.176252 2009] debug: Received: :964 UID 964AAAAAC 1225746297 w00t2 localhost testnet.user w00t 127.0.0.1 1225746302 +iosw +ACGJKLNOQcdfgjklnoqtx :Robin Burchell <w00t@inspircd.org> - * 0: uid - * 1: ts - * 2: nick - * 3: host - * 4: dhost - * 5: ident - * 6: ip - * 7: signon - * 8+: modes and params -- IMPORTANT, some modes (e.g. +s) may have parameters. So don't assume a fixed position of realname! - * last: realname - */ - bool OnUID(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override - { - time_t ts = convertTo<time_t>(params[1]); + IRCDMessageCapab() : IRCDMessage("CAPAB", 1) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } - Anope::string modes = params[8]; - for (unsigned i = 9; i < params.size() - 1; ++i) - modes += " " + params[i]; - User *user = do_nick("", params[2], params[5], params[3], source, params[params.size() - 1], ts, params[6], params[4], params[0], modes); - if (user && user->server->IsSynced() && nickserv) - nickserv->Validate(user); - - return true; - } - - bool OnCapab(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { if (params[0].equals_cs("START")) { @@ -358,7 +97,7 @@ class Inspircd12IRCdMessage : public InspircdIRCdMessage has_chgidentmod = false; has_hidechansmod = false; } - else if (params[0].equals_cs("MODULES")) + else if (params[0].equals_cs("MODULES") && params.size() > 1) { if (params[1].find("m_globops.so") != Anope::string::npos) has_globopsmod = true; @@ -373,11 +112,11 @@ class Inspircd12IRCdMessage : public InspircdIRCdMessage if (params[1].find("m_hidechans.so") != Anope::string::npos) has_hidechansmod = true; if (params[1].find("m_servprotect.so") != Anope::string::npos) - ircd->pseudoclient_mode = "+Ik"; + ircdproto->DefaultPseudoclientModes = "+Ik"; if (params[1].find("m_rline.so") != Anope::string::npos) has_rlinemod = true; } - else if (params[0].equals_cs("CAPABILITIES")) + else if (params[0].equals_cs("CAPABILITIES") && params.size() > 1) { spacesepstream ssep(params[1]); Anope::string capab; @@ -643,7 +382,7 @@ class Inspircd12IRCdMessage : public InspircdIRCdMessage else if (capab.find("MAXMODES=") != Anope::string::npos) { Anope::string maxmodes(capab.begin() + 9, capab.end()); - ircd->maxmodes = maxmodes.is_pos_number_only() ? convertTo<unsigned>(maxmodes) : 3; + ircdproto->MaxModes = maxmodes.is_pos_number_only() ? convertTo<unsigned>(maxmodes) : 3; } } } @@ -676,43 +415,97 @@ class Inspircd12IRCdMessage : public InspircdIRCdMessage Log() << "CHGHOST missing, Usage disabled until module is loaded."; if (!has_chgidentmod) Log() << "CHGIDENT missing, Usage disabled until module is loaded."; - ircd->svshold = has_svsholdmod; + ircdproto->CanSVSHold = has_svsholdmod; } - IRCdMessage::OnCapab(source, params); + return true; + } +}; + +struct IRCDMessageChgIdent : IRCDMessage +{ + IRCDMessageChgIdent() : IRCDMessage("CHGIDENT", 2) { } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + User *u = finduser(params[0]); + if (u) + u->SetIdent(params[1]); + return true; + } +}; + +struct IRCDMessageChgName : IRCDMessage +{ + IRCDMessageChgName(const Anope::string &n) : IRCDMessage(n, 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + source.GetUser()->SetRealname(params[0]); + return true; + } +}; + +struct IRCDMessageSetIdent : IRCDMessage +{ + IRCDMessageSetIdent() : IRCDMessage("SETIDENT", 0) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + source.GetUser()->SetIdent(params[0]); return true; } }; class ProtoInspIRCd : public Module { - Message message_endburst, message_time, - message_rsquit, message_svsmode, message_fhost, - message_chgident, message_fname, message_sethost, message_setident, message_setname, message_fjoin, message_fmode, - message_ftopic, message_opertype, message_idle, message_metadata; - - InspIRCdTS6Proto ircd_proto; - Inspircd12IRCdMessage ircd_message; + InspIRCd12Proto ircd_proto; + + /* Core message handlers */ + CoreIRCDMessageAway core_message_away; + CoreIRCDMessageCapab core_message_capab; + CoreIRCDMessageError core_message_error; + CoreIRCDMessageJoin core_message_join; + CoreIRCDMessageKill core_message_kill; + CoreIRCDMessageMOTD core_message_motd; + CoreIRCDMessagePart core_message_part; + CoreIRCDMessagePing core_message_ping; + CoreIRCDMessagePrivmsg core_message_privmsg; + CoreIRCDMessageQuit core_message_quit; + CoreIRCDMessageSQuit core_message_squit; + CoreIRCDMessageStats core_message_stats; + CoreIRCDMessageTopic core_message_topic; + CoreIRCDMessageVersion core_message_version; + + /* inspircd-ts6.h message handlers */ + IRCDMessageEndburst message_endburst; + IRCDMessageFHost message_fhost, message_sethost; + IRCDMessageFJoin message_sjoin; + IRCDMessageFMode message_fmode; + IRCDMessageFTopic message_ftopic; + IRCDMessageIdle message_idle; + IRCDMessageMetadata message_metadata; + IRCDMessageMode message_mode; + IRCDMessageNick message_nick; + IRCDMessageOperType message_opertype; + IRCDMessageRSQuit message_rsquit; + IRCDMessageServer message_server; + IRCDMessageTime message_time; + IRCDMessageUID message_uid; + + /* Our message handlers */ + IRCDMessageChgIdent message_chgident; + IRCDMessageChgName message_setname, message_chgname; + IRCDMessageCapab message_capab; + IRCDMessageSetIdent message_setident; public: ProtoInspIRCd(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL), - message_endburst("ENDBURST", event_endburst), - message_time("TIME", event_time), message_rsquit("RSQUIT", event_rsquit), - message_svsmode("SVSMODE", OnMode), message_fhost("FHOST", event_chghost), - message_chgident("CHGIDENT", event_chgident), message_fname("FNAME", event_chgname), - message_sethost("SETHOST", event_sethost), message_setident("SETIDENT", event_setident), - message_setname("SETNAME", event_setname), message_fjoin("FJOIN", OnSJoin), - message_fmode("FMODE", event_fmode), message_ftopic("FTOPIC", event_ftopic), - message_opertype("OPERTYPE", event_opertype), message_idle("IDLE", event_idle), - message_metadata("METADATA", event_metadata) + message_fhost("FHOST"), message_sethost("SETHOST"), + message_setname("SETNAME"), message_chgname("FNAME") { this->SetAuthor("Anope"); - pmodule_ircd_var(&myIrcd); - pmodule_ircd_proto(&this->ircd_proto); - pmodule_ircd_message(&this->ircd_message); - Capab.insert("NOQUIT"); Implementation i[] = { I_OnUserNickChange, I_OnServerSync }; @@ -729,14 +522,6 @@ class ProtoInspIRCd : public Module it->second->GenerateUID(); } - ~ProtoInspIRCd() - { - pmodule_ircd_var(NULL); - pmodule_ircd_proto(NULL); - pmodule_ircd_message(NULL); - } - - void OnUserNickChange(User *u, const Anope::string &) anope_override { /* InspIRCd 1.2 doesn't set -r on nick change, remove -r here. Note that if we have to set +r later diff --git a/modules/protocol/inspircd20.cpp b/modules/protocol/inspircd20.cpp index b1352959c..25d0c9333 100644 --- a/modules/protocol/inspircd20.cpp +++ b/modules/protocol/inspircd20.cpp @@ -20,255 +20,23 @@ static bool has_globopsmod = true; // Not a typo static bool has_rlinemod = false; #include "inspircd-ts6.h" -IRCDVar myIrcd = { - "InspIRCd 2.0", /* ircd name */ - "+I", /* Modes used by pseudoclients */ - 1, /* SVSNICK */ - 1, /* Vhost */ - 0, /* Supports SNlines */ - 1, /* Supports SQlines */ - 1, /* Supports SZlines */ - 0, /* Join 2 Message */ - 0, /* Chan SQlines */ - 0, /* Quit on Kill */ - 1, /* vidents */ - 1, /* svshold */ - 0, /* time stamp on mode */ - 0, /* O:LINE */ - 1, /* UMODE */ - 1, /* No Knock requires +i */ - 0, /* Can remove User Channel Modes with SVSMODE */ - 0, /* Sglines are not enforced until user reconnects */ - 1, /* ts6 */ - "$", /* TLD Prefix for Global */ - 20, /* Max number of modes we can send per line */ - 1, /* IRCd sends a SSL users certificate fingerprint */ -}; - static bool has_servicesmod = false; static bool has_svsholdmod = false; -class InspIRCdProto : public InspIRCdTS6Proto +class InspIRCd20Proto : public InspIRCdTS6Proto { + public: + InspIRCd20Proto() : InspIRCdTS6Proto("InspIRCd 2.0") { } + void SendConnect() anope_override { UplinkSocket::Message() << "CAPAB START 1202"; UplinkSocket::Message() << "CAPAB CAPABILITIES :PROTOCOL=1202"; UplinkSocket::Message() << "CAPAB END"; - SendServer(Me); - UplinkSocket::Message(Me) << "BURST"; - Module *enc = ModuleManager::FindFirstOf(ENCRYPTION); - UplinkSocket::Message(Me) << "VERSION :Anope-" << Anope::Version() << " " << Me->GetName() << " :" << ircd->name <<" - (" << (enc ? enc->name : "unknown") << ") -- " << Anope::VersionBuildString(); + InspIRCdTS6Proto::SendConnect(); } }; -bool event_ftopic(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - /* :source FTOPIC channel ts setby :topic */ - if (params.size() < 4) - return true; - - Channel *c = findchan(params[0]); - if (!c) - { - Log(LOG_DEBUG) << "TOPIC " << params[3] << " for nonexistent channel " << params[0]; - return true; - } - - c->ChangeTopicInternal(params[2], params[3], Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : Anope::CurTime); - - return true; -} - -bool event_opertype(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - /* opertype is equivalent to mode +o because servers - dont do this directly */ - User *u = finduser(source); - if (u && !u->HasMode(UMODE_OPER)) - { - std::vector<Anope::string> newparams; - newparams.push_back(source); - newparams.push_back("+o"); - return ircdmessage->OnMode(source, newparams); - } - return true; -} - -bool event_fmode(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - /* :source FMODE #test 12345678 +nto foo */ - if (params.size() < 3) - return true; - - Channel *c = findchan(params[0]); - if (!c) - return true; - - /* Checking the TS for validity to avoid desyncs */ - time_t ts = Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : 0; - if (c->creation_time > ts) - { - /* Our TS is bigger, we should lower it */ - c->creation_time = ts; - c->Reset(); - } - else if (c->creation_time < ts) - /* The TS we got is bigger, we should ignore this message. */ - return true; - - /* TS's are equal now, so we can proceed with parsing */ - std::vector<Anope::string> newparams; - newparams.push_back(params[0]); - newparams.push_back(params[1]); - Anope::string modes = params[2]; - for (unsigned n = 3; n < params.size(); ++n) - modes += " " + params[n]; - newparams.push_back(modes); - - return ircdmessage->OnMode(source, newparams); -} - -bool event_chgname(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - User *u = finduser(source); - - if (!u) - { - Log(LOG_DEBUG) << "FNAME for nonexistent user " << source; - return true; - } - else if (params.empty()) - return true; - - u->SetRealname(params[0]); - return true; -} - -bool event_chgident(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - User *u = finduser(source); - - if (!u) - { - Log(LOG_DEBUG) << "FIDENT for nonexistent user " << source; - return true; - } - - u->SetIdent(params[0]); - return true; -} - -bool event_chghost(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - User *u = finduser(source); - - if (!u) - { - Log(LOG_DEBUG) << "FHOST for nonexistent user " << source; - return true; - } - - u->SetDisplayedHost(params[0]); - return true; -} - - -/* - * source = numeric of the sending server - * params[0] = uuid - * params[1] = metadata name - * params[2] = data - */ -bool event_metadata(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() < 3) - return true; - else if (params[1].equals_cs("accountname")) - { - User *u = finduser(params[0]); - NickCore *nc = findcore(params[2]); - if (u && nc) - { - u->Login(nc); - - const NickAlias *user_na = findnick(u->nick); - if (!Config->NoNicknameOwnership && nickserv && user_na && user_na->nc == nc && user_na->nc->HasFlag(NI_UNCONFIRMED) == false) - u->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); - } - } - - /* - * possible incoming ssl_cert messages: - * Received: :409 METADATA 409AAAAAA ssl_cert :vTrSe c38070ce96e41cc144ed6590a68d45a6 <...> <...> - * Received: :409 METADATA 409AAAAAC ssl_cert :vTrSE Could not get peer certificate: error:00000000:lib(0):func(0):reason(0) - */ - else if (params[1].equals_cs("ssl_cert")) - { - User *u = finduser(params[0]); - if (!u) - return true; - std::string data = params[2].c_str(); - size_t pos1 = data.find(' ') + 1; - size_t pos2 = data.find(' ', pos1); - if ((pos2 - pos1) >= 32) // inspircd supports md5 and sha1 fingerprint hashes -> size 32 or 40 bytes. - { - u->fingerprint = data.substr(pos1, pos2 - pos1); - FOREACH_MOD(I_OnFingerprint, OnFingerprint(u)); - } - } - return true; -} - -bool event_encap(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() < 2 || Server::Find(params[0]) != Me) - return true; - - if (params[1] == "CHGIDENT" && params.size() > 3) - { - User *u = finduser(params[2]); - if (!u || u->server != Me) - return true; - - u->SetIdent(params[3]); - UplinkSocket::Message(u) << "FIDENT " << params[3]; - } - else if (params[1] == "CHGHOST" && params.size() > 3) - { - User *u = finduser(params[2]); - if (!u || u->server != Me) - return true; - - u->SetDisplayedHost(params[3]); - UplinkSocket::Message(u) << "FHOST " << params[3]; - } - else if (params[1] == "CHGNAME" && params.size() > 3) - { - User *u = finduser(params[2]); - if (!u || u->server != Me) - return true; - - u->SetRealname(params[3]); - UplinkSocket::Message(u) << "FNAME " << params[3]; - } - - return true; -} - -bool event_endburst(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - Server *s = Server::Find(source); - - if (!s) - throw CoreException("Got ENDBURST without a source"); - - Log(LOG_DEBUG) << "Processed ENDBURST for " << s->GetName(); - - s->Sync(true); - return true; -} - class InspIRCdExtBan : public ChannelModeList { public: @@ -342,37 +110,11 @@ class InspIRCdExtBan : public ChannelModeList } }; -class Inspircd20IRCdMessage : public InspircdIRCdMessage +struct IRCDMessageCapab : IRCDMessage { - public: - /* - * [Nov 03 22:09:58.176252 2009] debug: Received: :964 UID 964AAAAAC 1225746297 w00t2 localhost testnet.user w00t 127.0.0.1 1225746302 +iosw +ACGJKLNOQcdfgjklnoqtx :Robin Burchell <w00t@inspircd.org> - * 0: uid - * 1: ts - * 2: nick - * 3: host - * 4: dhost - * 5: ident - * 6: ip - * 7: signon - * 8+: modes and params -- IMPORTANT, some modes (e.g. +s) may have parameters. So don't assume a fixed position of realname! - * last: realname - */ - bool OnUID(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override - { - time_t ts = Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : 0; + IRCDMessageCapab() : IRCDMessage("CAPAB", 1) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } - Anope::string modes = params[8]; - for (unsigned i = 9; i < params.size() - 1; ++i) - modes += Anope::string(" ") + params[i]; - User *user = do_nick("", params[2], params[5], params[3], source, params[params.size() - 1], ts, params[6], params[4], params[0], modes); - if (user && user->server->IsSynced() && nickserv) - nickserv->Validate(user); - - return true; - } - - bool OnCapab(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { if (params[0].equals_cs("START")) { @@ -390,7 +132,7 @@ class Inspircd20IRCdMessage : public InspircdIRCdMessage has_chghostmod = false; has_chgidentmod = false; } - else if (params[0].equals_cs("CHANMODES")) + else if (params[0].equals_cs("CHANMODES") && params.size() > 1) { spacesepstream ssep(params[1]); Anope::string capab; @@ -490,7 +232,7 @@ class Inspircd20IRCdMessage : public InspircdIRCdMessage Log() << "Unrecognized mode string in CAPAB CHANMODES: " << capab; } } - if (params[0].equals_cs("USERMODES")) + if (params[0].equals_cs("USERMODES") && params.size() > 1) { spacesepstream ssep(params[1]); Anope::string capab; @@ -528,7 +270,7 @@ class Inspircd20IRCdMessage : public InspircdIRCdMessage else if (modename.equals_cs("servprotect")) { um = new UserMode(UMODE_PROTECTED, modechar[0]); - ircd->pseudoclient_mode = "+Ik"; // XXX + ircdproto->DefaultPseudoclientModes += "k"; } else if (modename.equals_cs("showwhois")) um = new UserMode(UMODE_WHOIS, modechar[0]); @@ -547,7 +289,7 @@ class Inspircd20IRCdMessage : public InspircdIRCdMessage Log() << "Unrecognized mode string in CAPAB USERMODES: " << capab; } } - else if (params[0].equals_cs("MODULES")) + else if (params[0].equals_cs("MODULES") && params.size() > 1) { spacesepstream ssep(params[1]); Anope::string module; @@ -559,12 +301,12 @@ class Inspircd20IRCdMessage : public InspircdIRCdMessage else if (module.find("m_rline.so") == 0) { has_rlinemod = true; - if (!Config->RegexEngine.empty() && Config->RegexEngine != module.substr(11)) + if (!Config->RegexEngine.empty() && module.length() > 11 && Config->RegexEngine != module.substr(11)) Log() << "Warning: InspIRCd is using regex engine " << module.substr(11) << ", but we have " << Config->RegexEngine << ". This may cause inconsistencies."; } } } - else if (params[0].equals_cs("MODSUPPORT")) + else if (params[0].equals_cs("MODSUPPORT") && params.size() > 1) { spacesepstream ssep(params[1]); Anope::string module; @@ -579,7 +321,7 @@ class Inspircd20IRCdMessage : public InspircdIRCdMessage has_chgidentmod = true; } } - else if (params[0].equals_cs("CAPABILITIES")) + else if (params[0].equals_cs("CAPABILITIES") && params.size() > 1) { spacesepstream ssep(params[1]); Anope::string capab; @@ -643,7 +385,7 @@ class Inspircd20IRCdMessage : public InspircdIRCdMessage else if (capab.find("MAXMODES=") != Anope::string::npos) { Anope::string maxmodes(capab.begin() + 9, capab.end()); - ircd->maxmodes = maxmodes.is_pos_number_only() ? convertTo<unsigned>(maxmodes) : 3; + ircdproto->MaxModes = maxmodes.is_pos_number_only() ? convertTo<unsigned>(maxmodes) : 3; } else if (capab.find("PREFIX=") != Anope::string::npos) { @@ -688,10 +430,49 @@ class Inspircd20IRCdMessage : public InspircdIRCdMessage Log() << "CHGHOST missing, Usage disabled until module is loaded."; if (!has_chgidentmod) Log() << "CHGIDENT missing, Usage disabled until module is loaded."; - ircd->svshold = has_svsholdmod; + ircdproto->CanSVSHold = has_svsholdmod; } - IRCdMessage::OnCapab(source, params); + return true; + } +}; + +struct IRCDMessageEncap : IRCDMessage +{ + IRCDMessageEncap() : IRCDMessage("ENCAP", 4) { } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + if (Anope::Match(Me->GetSID(), params[0]) == false) + return true; + + if (params[1] == "CHGIDENT") + { + User *u = finduser(params[2]); + if (!u || u->server != Me) + return true; + + u->SetIdent(params[3]); + UplinkSocket::Message(u) << "FIDENT " << params[3]; + } + else if (params[1] == "CHGHOST") + { + User *u = finduser(params[2]); + if (!u || u->server != Me) + return true; + + u->SetDisplayedHost(params[3]); + UplinkSocket::Message(u) << "FHOST " << params[3]; + } + else if (params[1] == "CHGNAME") + { + User *u = finduser(params[2]); + if (!u || u->server != Me) + return true; + + u->SetRealname(params[3]); + UplinkSocket::Message(u) << "FNAME " << params[3]; + } return true; } @@ -699,31 +480,50 @@ class Inspircd20IRCdMessage : public InspircdIRCdMessage class ProtoInspIRCd : public Module { - Message message_endburst, message_time, - message_rsquit, message_svsmode, message_fhost, - message_chgident, message_fname, message_fjoin, message_fmode, - message_ftopic, message_opertype, message_idle, message_metadata, - message_encap; - - InspIRCdProto ircd_proto; - Inspircd20IRCdMessage ircd_message; + InspIRCd20Proto ircd_proto; + + /* Core message handlers */ + CoreIRCDMessageAway core_message_away; + CoreIRCDMessageCapab core_message_capab; + CoreIRCDMessageError core_message_error; + CoreIRCDMessageJoin core_message_join; + CoreIRCDMessageKill core_message_kill; + CoreIRCDMessageMOTD core_message_motd; + CoreIRCDMessagePart core_message_part; + CoreIRCDMessagePing core_message_ping; + CoreIRCDMessagePrivmsg core_message_privmsg; + CoreIRCDMessageQuit core_message_quit; + CoreIRCDMessageSQuit core_message_squit; + CoreIRCDMessageStats core_message_stats; + CoreIRCDMessageTopic core_message_topic; + CoreIRCDMessageVersion core_message_version; + + /* inspircd-ts6.h message handlers */ + IRCDMessageEndburst message_endburst; + IRCDMessageFHost message_fhost; + IRCDMessageFJoin message_sjoin; + IRCDMessageFMode message_fmode; + IRCDMessageFTopic message_ftopic; + IRCDMessageIdle message_idle; + IRCDMessageMetadata message_metadata; + IRCDMessageMode message_mode; + IRCDMessageNick message_nick; + IRCDMessageOperType message_opertype; + IRCDMessageRSQuit message_rsquit; + IRCDMessageServer message_server; + IRCDMessageTime message_time; + IRCDMessageUID message_uid; + + /* Our message handlers */ + IRCDMessageCapab message_capab; + IRCDMessageEncap message_encap; + public: ProtoInspIRCd(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL), - message_endburst("ENDBURST", event_endburst), - message_time("TIME", event_time), message_rsquit("RSQUIT", event_rsquit), - message_svsmode("SVSMODE", OnMode), message_fhost("FHOST", event_chghost), - message_chgident("FIDENT", event_chgident), message_fname("FNAME", event_chgname), - message_fjoin("FJOIN", OnSJoin), - message_fmode("FMODE", event_fmode), message_ftopic("FTOPIC", event_ftopic), - message_opertype("OPERTYPE", event_opertype), message_idle("IDLE", event_idle), - message_metadata("METADATA", event_metadata), message_encap("ENCAP", event_encap) + message_fhost("FHOST") { this->SetAuthor("Anope"); - pmodule_ircd_var(&myIrcd); - pmodule_ircd_proto(&this->ircd_proto); - pmodule_ircd_message(&this->ircd_message); - Capab.insert("NOQUIT"); Implementation i[] = { I_OnUserNickChange, I_OnServerSync, I_OnChannelCreate, I_OnChanRegistered, I_OnDelChan, I_OnMLock, I_OnUnMLock }; @@ -740,13 +540,6 @@ class ProtoInspIRCd : public Module it->second->GenerateUID(); } - ~ProtoInspIRCd() - { - pmodule_ircd_var(NULL); - pmodule_ircd_proto(NULL); - pmodule_ircd_message(NULL); - } - void OnUserNickChange(User *u, const Anope::string &) anope_override { u->RemoveModeInternal(ModeManager::FindUserModeByName(UMODE_REGISTERED)); diff --git a/modules/protocol/plexus.cpp b/modules/protocol/plexus.cpp index 5debfa5dc..1ef8adab9 100644 --- a/modules/protocol/plexus.cpp +++ b/modules/protocol/plexus.cpp @@ -11,35 +11,36 @@ #include "module.h" -static Anope::string TS6UPLINK; - -IRCDVar myIrcd = { - "hybrid-7.2.3+plexus-3.0.1", /* ircd name */ - "+oi", /* Modes used by pseudoclients */ - 1, /* SVSNICK */ - 1, /* Vhost */ - 1, /* Supports SNlines */ - 1, /* Supports SQlines */ - 0, /* Supports SZlines */ - 0, /* Join 2 Message */ - 1, /* Chan SQlines */ - 0, /* Quit on Kill */ - 1, /* vidents */ - 1, /* svshold */ - 1, /* time stamp on mode */ - 1, /* UMODE */ - 0, /* O:LINE */ - 0, /* No Knock requires +i */ - 0, /* Can remove User Channel Modes with SVSMODE */ - 0, /* Sglines are not enforced until user reconnects */ - 1, /* ts6 */ - "$$", /* TLD Prefix for Global */ - 4, /* Max number of modes we can send per line */ - 1, /* IRCd sends a SSL users certificate fingerprint */ -}; +static Anope::string UplinkSID; class PlexusProto : public IRCDProto { + public: + PlexusProto() : IRCDProto("hybrid-7.2.3+plexus-3.0.1") + { + DefaultPseudoclientModes = "+oiU"; + CanSVSNick = true; + CanSetVHost = true; + CanSetVIdent = true; + CanSNLine = true; + CanSQLine = true; + CanSQLineChannel = true; + CanSVSHold = true; + CanCertFP = true; + RequiresID = true; + MaxModes = 4; + } + + void SendGlobalNotice(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override + { + UplinkSocket::Message(bi) << "NOTICE $$" << dest->GetName() << " :" << msg; + } + + void SendGlobalPrivmsg(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override + { + UplinkSocket::Message(bi) << "PRIVMSG $$" << dest->GetName() << " :" << msg; + } + void SendGlobopsInternal(const BotInfo *source, const Anope::string &buf) anope_override { UplinkSocket::Message(source) << "OPERWALL :" << buf; @@ -236,108 +237,202 @@ class PlexusProto : public IRCDProto } }; -class PlexusIRCdMessage : public IRCdMessage +struct IRCDMessageBMask : IRCDMessage { - public: - /* - * params[0] = ts - * params[1] = channel - */ - bool OnJoin(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override + IRCDMessageBMask() : IRCDMessage("BMASK", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - if (params.size() < 2) - return IRCdMessage::OnJoin(source, params); - do_join(source, params[1], params[0]); + /* :42X BMASK 1106409026 #ircops b :*!*@*.aol.com */ + /* 0 1 2 3 */ + Channel *c = findchan(params[1]); + + if (c) + { + ChannelMode *ban = ModeManager::FindChannelModeByName(CMODE_BAN), + *except = ModeManager::FindChannelModeByName(CMODE_EXCEPT), + *invex = ModeManager::FindChannelModeByName(CMODE_INVITEOVERRIDE); + + Anope::string bans = params[3]; + int count = myNumToken(bans, ' '), i; + for (i = 0; i < count; ++i) + { + Anope::string b = myStrGetToken(bans, ' ', i); + if (ban && params[2].equals_cs("b")) + c->SetModeInternal(source, ban, b); + else if (except && params[2].equals_cs("e")) + c->SetModeInternal(source, except, b); + if (invex && params[2].equals_cs("I")) + c->SetModeInternal(source, invex, b); + } + } + + return true; + } +}; + +struct IRCDMessageEncap : IRCDMessage +{ + IRCDMessageEncap() : IRCDMessage("ENCAP", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + /* + * Received: :dev.anope.de ENCAP * SU DukePyrolator DukePyrolator + * params[0] = * + * params[1] = SU + * params[2] = nickname + * params[3] = account + */ + if (params[1].equals_cs("SU")) + { + User *u = finduser(params[2]); + const NickAlias *user_na = findnick(params[2]); + NickCore *nc = findcore(params[3]); + if (u && nc) + { + u->Login(nc); + if (!Config->NoNicknameOwnership && user_na && user_na->nc == nc && user_na->nc->HasFlag(NI_UNCONFIRMED) == false) + u->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); + } + } + + /* + * Received: :dev.anope.de ENCAP * CERTFP DukePyrolator :3F122A9CC7811DBAD3566BF2CEC3009007C0868F + * params[0] = * + * params[1] = CERTFP + * params[2] = nickname + * params[3] = fingerprint + */ + else if (params[1].equals_cs("CERTFP")) + { + User *u = finduser(params[2]); + if (u) + { + u->fingerprint = params[3]; + FOREACH_MOD(I_OnFingerprint, OnFingerprint(u)); + } + } + return true; + } +}; + +struct IRCDMessageEOB : IRCDMessage +{ + IRCDMessageEOB() : IRCDMessage("EOB", 0) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + source.GetServer()->Sync(true); return true; } +}; - bool OnMode(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override +struct IRCDMessageJoin : CoreIRCDMessageJoin +{ + IRCDMessageJoin() : CoreIRCDMessageJoin("JOIN") { } + + /* + * params[0] = ts + * params[1] = channel + */ + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { if (params.size() < 2) return true; - if (params[0][0] == '#' || params[0][0] == '&') - do_cmode(source, params[0], params[2], params[1]); - else - do_umode(params[0], params[1]); + std::vector<Anope::string> p = params; + p.erase(p.begin()); - return true; + return CoreIRCDMessageJoin::Run(source, p); } +}; - /* - TS6 - params[0] = nick - params[1] = hop - params[2] = ts - params[3] = modes - params[4] = user - params[5] = host - params[6] = IP - params[7] = UID - params[8] = services stamp - params[9] = realhost - params[10] = info - */ - bool OnUID(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override +struct IRCDMessageMode : IRCDMessage +{ + IRCDMessageMode() : IRCDMessage("MODE", 3) { } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - /* An IP of 0 means the user is spoofed */ - Anope::string ip = params[6]; - if (ip == "0") - ip.clear(); - User *user = do_nick("", params[0], params[4], params[9], source, params[10], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : 0, ip, params[5], params[7], params[3]); - if (nickserv && user && user->server->IsSynced()) - nickserv->Validate(user); + if (ircdproto->IsChannelValid(params[0])) + { + // 0 = channel, 1 = ts, 2 = modes + Channel *c = findchan(params[0]); + time_t ts = Anope::CurTime; + try + { + ts = convertTo<time_t>(params[1]); + } + catch (const ConvertException &) { } + + if (c) + c->SetModesInternal(source, params[2], ts); + } + else + { + User *u = finduser(params[0]); + if (u) + u->SetModesInternal("%s", params[1].c_str()); + } return true; } +}; + +struct IRCDMessageNick : IRCDMessage +{ + IRCDMessageNick() : IRCDMessage("NICK", 2) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } - bool OnNick(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - do_nick(source, params[0], "", "", "", "", Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : 0, "", "", "", ""); + source.GetUser()->ChangeNick(params[0]); return true; } +}; + +struct IRCDMessagePass : IRCDMessage +{ + IRCDMessagePass() : IRCDMessage("PASS", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } - bool OnServer(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - if (params[1].equals_cs("1")) - do_server(source, params[0], Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0, params[2], TS6UPLINK); - else - do_server(source, params[0], Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0, params[2], ""); + UplinkSID = params[3]; return true; } +}; - /* - TS6 - params[0] = nick - params[1] = hop - params[2] = ts - params[3] = modes - params[4] = user - params[5] = host - params[6] = IP - params[7] = UID - params[8] = services stamp - params[9] = realhost - params[10] = info - */ - bool OnTopic(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override +struct IRCDMessageServer : IRCDMessage +{ + IRCDMessageServer() : IRCDMessage("SERVER", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - Channel *c = findchan(params[0]); - if (!c) - { - Log() << "TOPIC for nonexistant channel " << params[0]; + // Servers other then our immediate uplink are introduced via SID + if (params[1] != "1") return true; - } + new Server(source.GetServer() == NULL ? Me : source.GetServer(), params[0], 1, params[2], UplinkSID); + return true; + } +}; - if (params.size() == 4) - c->ChangeTopicInternal(params[1], params[3], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : Anope::CurTime); - else - c->ChangeTopicInternal(source, (params.size() > 1 ? params[1] : "")); +struct IRCDMessageSID : IRCDMessage +{ + IRCDMessageSID() : IRCDMessage("SID", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + /* :42X SID trystan.nomadirc.net 2 43X :ircd-plexus test server */ + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + unsigned int hops = params[1].is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0; + new Server(source.GetServer() == NULL ? Me : source.GetServer(), params[0], hops, params[3], params[2]); return true; } +}; + +struct IRCDMessageSJoin : IRCDMessage +{ + IRCDMessageSJoin() : IRCDMessage("SJOIN", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); } - bool OnSJoin(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { Channel *c = findchan(params[1]); time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo<time_t>(params[0]) : 0; @@ -367,7 +462,7 @@ class PlexusIRCdMessage : public IRCdMessage if (!modes.empty()) modes.erase(modes.begin()); /* Set the modes internally */ - c->SetModesInternal(NULL, modes); + c->SetModesInternal(source, modes); } spacesepstream sep(params[params.size() - 1]); @@ -409,7 +504,7 @@ class PlexusIRCdMessage : public IRCdMessage * This will enforce secureops etc on the user */ for (std::list<ChannelMode *>::iterator it = Status.begin(), it_end = Status.end(); it != it_end; ++it) - c->SetModeInternal(NULL, *it, buf); + c->SetModeInternal(source, *it, buf); /* Now set whatever modes this user is allowed to have on the channel */ chan_set_correct_modes(u, c, 1, true); @@ -436,155 +531,144 @@ class PlexusIRCdMessage : public IRCdMessage } }; -bool event_tburst(const Anope::string &source, const std::vector<Anope::string> ¶ms) +struct IRCDMessageTBurst : IRCDMessage { - // :rizon.server TBURST 1298674830 #lol 1298674833 Adam!Adam@i.has.a.spoof :lol - if (params.size() < 4) - return true; - - Channel *c = findchan(params[1]); + IRCDMessageTBurst() : IRCDMessage("TBURST", 5) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } - if (!c) + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - Log() << "TOPIC " << params[3] << " for nonexistent channel " << params[0]; - return true; - } - else if (c->creation_time < convertTo<time_t>(params[0])) - return true; - - Anope::string setter = myStrGetToken(params[3], '!', 0); - time_t topic_time = Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : Anope::CurTime; - c->ChangeTopicInternal(setter, params.size() > 4 ? params[4] : "", topic_time); + // 0 1 2 3 4 + // :rizon.server TBURST 1298674830 #lol 1298674833 Adam!Adam@i.has.a.spoof :lol + // chan ts topic ts - return true; -} + Channel *c = findchan(params[1]); -bool event_sid(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - /* :42X SID trystan.nomadirc.net 2 43X :ircd-plexus test server */ - Server *s = Server::Find(source); + try + { + if (!c || c->creation_time < convertTo<time_t>(params[0])) + return true; + } + catch (const ConvertException &) + { + return true; + } - do_server(s->GetName(), params[0], Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0, params[3], params[2]); - return true; -} + Anope::string setter = myStrGetToken(params[3], '!', 0); + time_t topic_time = Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : Anope::CurTime; + c->ChangeTopicInternal(setter, params.size() > 4 ? params[4] : "", topic_time); -bool event_mode(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() < 2) return true; + } +}; - if (params[0][0] == '#' || params[0][0] == '&') - do_cmode(source, params[0], params[2], params[1]); - else - do_umode(params[0], params[1]); - return true; -} - -bool event_tmode(const Anope::string &source, const std::vector<Anope::string> ¶ms) +struct IRCDMessageTMode : IRCDMessage { - if (params[1][0] == '#') + IRCDMessageTMode() : IRCDMessage("TMODE", 3) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { + time_t ts = Anope::CurTime; + try + { + ts = convertTo<time_t>(params[0]); + } + catch (const ConvertException &) { } + Channel *c = findchan(params[1]); Anope::string modes = params[2]; for (unsigned i = 3; i < params.size(); ++i) modes += " " + params[i]; - do_cmode(source, params[1], modes, params[0]); - } - return true; -} -bool event_pass(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - TS6UPLINK = params[3]; - return true; -} + if (c) + c->SetModesInternal(source, modes, ts); -bool event_bmask(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - /* :42X BMASK 1106409026 #ircops b :*!*@*.aol.com */ - /* 0 1 2 3 */ - Channel *c = findchan(params[1]); - - if (c) - { - ChannelMode *ban = ModeManager::FindChannelModeByName(CMODE_BAN), - *except = ModeManager::FindChannelModeByName(CMODE_EXCEPT), - *invex = ModeManager::FindChannelModeByName(CMODE_INVITEOVERRIDE); - Anope::string bans = params[3]; - int count = myNumToken(bans, ' '), i; - for (i = 0; i <= count - 1; ++i) - { - Anope::string b = myStrGetToken(bans, ' ', i); - if (ban && params[2].equals_cs("b")) - c->SetModeInternal(NULL, ban, b); - else if (except && params[2].equals_cs("e")) - c->SetModeInternal(NULL, except, b); - if (invex && params[2].equals_cs("I")) - c->SetModeInternal(NULL, invex, b); - } + return true; } - return true; -} +}; -bool event_encap(const Anope::string &source, const std::vector<Anope::string> ¶ms) +struct IRCDMessageTopic : IRCDMessage { - if (params.size() < 4) - return true; - /* - * Received: :dev.anope.de ENCAP * SU DukePyrolator DukePyrolator - * params[0] = * - * params[1] = SU - * params[2] = nickname - * params[3] = account - */ - else if (params[1].equals_cs("SU")) + IRCDMessageTopic() : IRCDMessage("TOPIC", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - User *u = finduser(params[2]); - const NickAlias *user_na = findnick(params[2]); - NickCore *nc = findcore(params[3]); - if (u && nc) - { - u->Login(nc); - if (!Config->NoNicknameOwnership && user_na && user_na->nc == nc && user_na->nc->HasFlag(NI_UNCONFIRMED) == false) - u->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); - } + Channel *c = findchan(params[0]); + if (!c) + return true; + + c->ChangeTopicInternal(params[1], params[3], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : Anope::CurTime); + return true; } +}; + +struct IRCDMessageUID : IRCDMessage +{ + IRCDMessageUID() : IRCDMessage("UID", 11) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } /* - * Received: :dev.anope.de ENCAP * CERTFP DukePyrolator :3F122A9CC7811DBAD3566BF2CEC3009007C0868F - * params[0] = * - * params[1] = CERTFP - * params[2] = nickname - * params[3] = fingerprint - */ - else if (params[1].equals_cs("CERTFP")) + params[0] = nick + params[1] = hop + params[2] = ts + params[3] = modes + params[4] = user + params[5] = host + params[6] = IP + params[7] = UID + params[8] = services stamp + params[9] = realhost + params[10] = info + */ + // :42X UID Adam 1 1348535644 +aow Adam 192.168.0.5 192.168.0.5 42XAAAAAB 0 192.168.0.5 :Adam + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - User *u = finduser(params[2]); - if (u) - { - u->fingerprint = params[3]; - FOREACH_MOD(I_OnFingerprint, OnFingerprint(u)); - } - } - return true; -} + /* An IP of 0 means the user is spoofed */ + Anope::string ip = params[6]; + if (ip == "0") + ip.clear(); -bool event_eob(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - Server *s = Server::Find(source); - if (s) - s->Sync(true); + User *user = new User(params[0], params[4], params[9], params[5], ip, source.GetServer(), params[10], params[2].is_pos_number_only() ? convertTo<time_t>(params[2]) : 0, params[3], params[7]); + if (user && user->server->IsSynced() && nickserv) + nickserv->Validate(user); - return true; -} + return true; + } +}; class ProtoPlexus : public Module { - Message message_tmode, message_bmask, message_pass, - message_tb, message_sid, message_encap, - message_eob; - PlexusProto ircd_proto; - PlexusIRCdMessage ircd_message; + + /* Core message handlers */ + CoreIRCDMessageAway core_message_away; + CoreIRCDMessageCapab core_message_capab; + CoreIRCDMessageError core_message_error; + CoreIRCDMessageKill core_message_kill; + CoreIRCDMessageMOTD core_message_motd; + CoreIRCDMessagePart core_message_part; + CoreIRCDMessagePing core_message_ping; + CoreIRCDMessagePrivmsg core_message_privmsg; + CoreIRCDMessageQuit core_message_quit; + CoreIRCDMessageSQuit core_message_squit; + CoreIRCDMessageStats core_message_stats; + CoreIRCDMessageTime core_message_time; + CoreIRCDMessageTopic core_message_topic; + CoreIRCDMessageVersion core_message_version; + CoreIRCDMessageWhois core_message_whois; + + /* Our message handlers */ + IRCDMessageBMask message_bmask; + IRCDMessageEncap message_encap; + IRCDMessageEOB message_eob; + IRCDMessageJoin message_join; + IRCDMessageMode message_mode; + IRCDMessageNick message_nick; + IRCDMessagePass message_pass; + IRCDMessageServer message_server; + IRCDMessageSID message_sid; + IRCDMessageSJoin message_sjoin; + IRCDMessageTBurst message_tburst; + IRCDMessageTMode message_tmode; + IRCDMessageTopic message_topic; + IRCDMessageUID message_uid; void AddModes() { @@ -605,6 +689,7 @@ class ProtoPlexus : public Module ModeManager::AddUserMode(new UserMode(UMODE_PRIV, 'p')); ModeManager::AddUserMode(new UserMode(UMODE_REGISTERED, 'r')); ModeManager::AddUserMode(new UserMode(UMODE_CLOAK, 'x')); + ModeManager::AddUserMode(new UserMode(UMODE_PROTECTED, 'U')); /* b/e/I */ ModeManager::AddChannelMode(new ChannelModeList(CMODE_BAN, 'b')); @@ -629,8 +714,8 @@ class ProtoPlexus : public Module ModeManager::AddChannelMode(new ChannelMode(CMODE_NONOTICE, 'N')); ModeManager::AddChannelMode(new ChannelModeOper('O')); ModeManager::AddChannelMode(new ChannelMode(CMODE_REGISTEREDONLY, 'R')); - ModeManager::AddChannelMode(new ChannelMode(CMODE_SSL, 'S')); + ModeManager::AddChannelMode(new ChannelMode(CMODE_BLOCKCOLOR, 'c')); ModeManager::AddChannelMode(new ChannelMode(CMODE_INVITE, 'i')); ModeManager::AddChannelMode(new ChannelMode(CMODE_MODERATED, 'm')); @@ -642,18 +727,10 @@ class ProtoPlexus : public Module } public: - ProtoPlexus(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL), - message_tmode("TMODE", event_tmode), message_bmask("BMASK", event_bmask), - message_pass("PASS", event_pass), message_tb("TBURST", event_tburst), - message_sid("SID", event_sid), message_encap("ENCAP", event_encap), - message_eob("EOB", event_eob) + ProtoPlexus(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL) { this->SetAuthor("Anope"); - pmodule_ircd_var(&myIrcd); - pmodule_ircd_proto(&this->ircd_proto); - pmodule_ircd_message(&this->ircd_message); - this->AddModes(); Implementation i[] = { I_OnServerSync }; @@ -670,13 +747,6 @@ class ProtoPlexus : public Module it->second->GenerateUID(); } - ~ProtoPlexus() - { - pmodule_ircd_var(NULL); - pmodule_ircd_proto(NULL); - pmodule_ircd_message(NULL); - } - void OnServerSync(Server *s) anope_override { if (nickserv) diff --git a/modules/protocol/ratbox.cpp b/modules/protocol/ratbox.cpp index 1054c0b8c..017af4e3f 100644 --- a/modules/protocol/ratbox.cpp +++ b/modules/protocol/ratbox.cpp @@ -11,35 +11,31 @@ #include "module.h" -static Anope::string TS6UPLINK; - -IRCDVar myIrcd = { - "Ratbox 2.0+", /* ircd name */ - "+oiS", /* Modes used by pseudoclients */ - 0, /* SVSNICK */ - 0, /* Vhost */ - 1, /* Supports SNlines */ - 1, /* Supports SQlines */ - 0, /* Supports SZlines */ - 1, /* Join 2 Message */ - 1, /* Chan SQlines */ - 0, /* Quit on Kill */ - 0, /* vidents */ - 0, /* svshold */ - 0, /* time stamp on mode */ - 0, /* UMODE */ - 0, /* O:LINE */ - 0, /* No Knock requires +i */ - 0, /* Can remove User Channel Modes with SVSMODE */ - 0, /* Sglines are not enforced until user reconnects */ - 1, /* ts6 */ - "$$", /* TLD Prefix for Global */ - 4, /* Max number of modes we can send per line */ - 0, /* IRCd sends a SSL users certificate fingerprint */ -}; +static Anope::string UplinkSID; class RatboxProto : public IRCDProto { + public: + RatboxProto() : IRCDProto("Ratbox 3.0+") + { + DefaultPseudoclientModes = "+oiS"; + CanSNLine = true; + CanSQLine = true; + CanSZLine = true; + RequiresID = true; + MaxModes = 4; + } + + void SendGlobalNotice(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override + { + UplinkSocket::Message(bi) << "NOTICE $$" << dest->GetName() << " :" << msg; + } + + void SendGlobalPrivmsg(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override + { + UplinkSocket::Message(bi) << "PRIVMSG $$" << dest->GetName() << " :" << msg; + } + void SendGlobopsInternal(const BotInfo *source, const Anope::string &buf) anope_override { UplinkSocket::Message(source) << "OPERWALL :" << buf; @@ -140,21 +136,13 @@ class RatboxProto : public IRCDProto QS - Can handle quit storm removal EX - Can do channel +e exemptions CHW - Can do channel wall @# - LL - Can do lazy links IE - Can do invite exceptions - EOB - Can do EOB message - KLN - Can do KLINE message GLN - Can do GLINE message - HUB - This server is a HUB - UID - Can do UIDs - ZIP - Can do ZIPlinks - ENC - Can do ENCrypted links - KNOCK - supports KNOCK - TBURST - supports TBURST - PARA - supports invite broadcasting for +p - ENCAP - ? + KNOCK - supports KNOCK + TB - supports topic burst + ENCAP - supports ENCAP */ - UplinkSocket::Message() << "CAPAB :QS EX CHW IE KLN GLN KNOCK TB UNKLN CLUSTER ENCAP TS6"; + UplinkSocket::Message() << "CAPAB :QS EX CHW IE GLN TB ENCAP"; /* Make myself known to myself in the serverlist */ SendServer(Me); /* @@ -224,93 +212,185 @@ class RatboxProto : public IRCDProto } }; -class RatboxIRCdMessage : public IRCdMessage +struct IRCDMessageBMask : IRCDMessage { - public: + IRCDMessageBMask() : IRCDMessage("BMASK", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + /* :42X BMASK 1106409026 #ircops b :*!*@*.aol.com */ + /* 0 1 2 3 */ + Channel *c = findchan(params[1]); + + if (c) + { + ChannelMode *ban = ModeManager::FindChannelModeByName(CMODE_BAN), + *except = ModeManager::FindChannelModeByName(CMODE_EXCEPT), + *invex = ModeManager::FindChannelModeByName(CMODE_INVITEOVERRIDE); + + Anope::string bans = params[3]; + int count = myNumToken(bans, ' '), i; + for (i = 0; i < count; ++i) + { + Anope::string b = myStrGetToken(bans, ' ', i); + if (ban && params[2].equals_cs("b")) + c->SetModeInternal(source, ban, b); + else if (except && params[2].equals_cs("e")) + c->SetModeInternal(source, except, b); + if (invex && params[2].equals_cs("I")) + c->SetModeInternal(source, invex, b); + } + } + + return true; + } +}; + +struct IRCDMessageEncap : IRCDMessage +{ + IRCDMessageEncap() : IRCDMessage("ENCAP", 3) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } + + // Debug: Received: :00BAAAAAB ENCAP * LOGIN Adam + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + if (params[1] == "LOGIN") + { + User *u = source.GetUser(); + + NickCore *nc = findcore(params[2]); + if (!nc) + return true; + u->Login(nc); + + const NickAlias *user_na = findnick(u->nick); + if (!Config->NoNicknameOwnership && user_na && user_na->nc == nc && user_na->nc->HasFlag(NI_UNCONFIRMED) == false) + u->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); + } + + return true; + } +}; + +struct IRCDMessageJoin : CoreIRCDMessageJoin +{ + IRCDMessageJoin() : CoreIRCDMessageJoin("JOIN") { } + /* * params[0] = ts * params[1] = channel + * params[2] = modes */ - bool OnJoin(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { if (params.size() < 2) - return IRCdMessage::OnJoin(source, params); - do_join(source, params[1], params[0]); - return true; + return true; + + std::vector<Anope::string> p = params; + p.erase(p.begin()); + + return CoreIRCDMessageJoin::Run(source, p); } +}; + +struct IRCDMessageMode : IRCDMessage +{ + IRCDMessageMode() : IRCDMessage("MODE", 3) { } - bool OnMode(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - if (params.size() < 2) - return true; + if (ircdproto->IsChannelValid(params[0])) + { + // 0 = channel, 1 = ts, 2 = modes + Channel *c = findchan(params[0]); + time_t ts = Anope::CurTime; + try + { + ts = convertTo<time_t>(params[1]); + } + catch (const ConvertException &) { } - if (params[0][0] == '#' || params[0][0] == '&') - do_cmode(source, params[0], params[2], params[1]); + if (c) + c->SetModesInternal(source, params[2], ts); + } else - do_umode(params[0], params[1]); + { + User *u = finduser(params[0]); + if (u) + u->SetModesInternal("%s", params[1].c_str()); + } return true; } +}; - bool OnUID(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override - { - /* Source is always the server */ - User *user = do_nick("", params[0], params[4], params[5], source, params[8], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : 0, params[6], "*", params[7], params[3]); - if (user && user->server->IsSynced() && nickserv) - nickserv->Validate(user); +struct IRCDMessageNick : IRCDMessage +{ + IRCDMessageNick() : IRCDMessage("NICK", 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + source.GetUser()->ChangeNick(params[0]); return true; } +}; - /* - params[0] = nick - params[1] = hop - params[2] = ts - params[3] = modes - params[4] = user - params[5] = host - params[6] = IP - params[7] = UID - params[8] = info - */ - bool OnNick(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override - { - do_nick(source, params[0], "", "", "", "", Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : 0, "", "", "", ""); +struct IRCDMessagePass : IRCDMessage +{ + IRCDMessagePass() : IRCDMessage("PASS", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + UplinkSID = params[3]; return true; } +}; + +struct IRCDMessagePong : IRCDMessage +{ + IRCDMessagePong() : IRCDMessage("PONG", 0) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } - bool OnServer(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - if (params[1].equals_cs("1")) - do_server(source, params[0], Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0, params[2], TS6UPLINK); - else - do_server(source, params[0], Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0, params[2], ""); - ircdproto->SendPing(Config->ServerName, params[0]); + source.GetServer()->Sync(false); return true; } +}; - bool OnTopic(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override +struct IRCDMessageServer : IRCDMessage +{ + IRCDMessageServer() : IRCDMessage("SERVER", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + + // SERVER hades.arpa 1 :ircd-ratbox test server + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - Channel *c = findchan(params[0]); - if (!c) - { - Log() << "TOPIC for nonexistant channel " << params[0]; + // Servers other then our immediate uplink are introduced via SID + if (params[1] != "1") return true; - } + new Server(source.GetServer() == NULL ? Me : source.GetServer(), params[0], 1, params[2], UplinkSID); + ircdproto->SendPing(Config->ServerName, params[0]); + return true; + } +}; - if (params.size() == 4) - { - c->ChangeTopicInternal(params[1], params[3], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : Anope::CurTime); - } - else - { - c->ChangeTopicInternal(source, (params.size() > 1 ? params[1] : "")); - } +struct IRCDMessageSID : IRCDMessage +{ + IRCDMessageSID() : IRCDMessage("SID", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + /* :42X SID trystan.nomadirc.net 2 43X :ircd-ratbox test server */ + unsigned int hops = params[1].is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0; + new Server(source.GetServer() == NULL ? Me : source.GetServer(), params[0], hops, params[3], params[2]); + ircdproto->SendPing(Config->ServerName, params[0]); return true; } +}; + +struct IRCDMessageSjoin : IRCDMessage +{ + IRCDMessageSjoin() : IRCDMessage("SJOIN", 2) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); } - bool OnSJoin(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { Channel *c = findchan(params[1]); time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo<time_t>(params[0]) : 0; @@ -340,7 +420,7 @@ class RatboxIRCdMessage : public IRCdMessage if (!modes.empty()) modes.erase(modes.begin()); /* Set the modes internally */ - c->SetModesInternal(NULL, modes); + c->SetModesInternal(source, modes); } spacesepstream sep(params[params.size() - 1]); @@ -382,7 +462,7 @@ class RatboxIRCdMessage : public IRCdMessage * This will enforce secureops etc on the user */ for (std::list<ChannelMode *>::iterator it = Status.begin(), it_end = Status.end(); it != it_end; ++it) - c->SetModeInternal(NULL, *it, buf); + c->SetModeInternal(source, *it, buf); /* Now set whatever modes this user is allowed to have on the channel */ chan_set_correct_modes(u, c, 1, true); @@ -409,120 +489,99 @@ class RatboxIRCdMessage : public IRCdMessage } }; -bool event_tburst(const Anope::string &source, const std::vector<Anope::string> ¶ms) +struct IRCDMessageTBurst : IRCDMessage { - if (params.size() != 4) - return true; - - Anope::string setter = myStrGetToken(params[2], '!', 0); - time_t topic_time = Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : Anope::CurTime; - Channel *c = findchan(params[0]); + IRCDMessageTBurst() : IRCDMessage("TBURST", 4) { } - if (!c) + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - Log() << "TOPIC " << params[3] << " for nonexistent channel " << params[0]; - return true; - } - - c->ChangeTopicInternal(setter, params.size() > 3 ? params[3] : "", topic_time); - - return true; -} - -bool event_kick(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() > 2) - do_kick(source, params[0], params[1], params[2]); - return true; -} + Anope::string setter = myStrGetToken(params[2], '!', 0); + time_t topic_time = Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : Anope::CurTime; + Channel *c = findchan(params[0]); -bool event_sid(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - /* :42X SID trystan.nomadirc.net 2 43X :ircd-ratbox test server */ - do_server(source, params[0], Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0, params[3], params[2]); - ircdproto->SendPing(Config->ServerName, params[0]); - return true; -} - -// Debug: Received: :00BAAAAAB ENCAP * LOGIN Adam -bool event_encap(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() > 2 && params[1] == "LOGIN") - { - User *u = finduser(source); - NickCore *nc = findcore(params[2]); - if (!u || !nc) + if (!c) return true; - u->Login(nc); - const NickAlias *user_na = findnick(u->nick); - if (!Config->NoNicknameOwnership && user_na && user_na->nc == nc && user_na->nc->HasFlag(NI_UNCONFIRMED) == false) - u->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); - } + c->ChangeTopicInternal(setter, params[3], topic_time); - return true; -} + return true; + } +}; -bool event_pong(const Anope::string &source, const std::vector<Anope::string> ¶ms) +struct IRCDMessageTMode : IRCDMessage { - Server *s = Server::Find(source); - if (s) - s->Sync(false); - return true; -} + IRCDMessageTMode() : IRCDMessage("TMODE", 3) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } -bool event_tmode(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params[1][0] == '#') + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { + time_t ts = Anope::CurTime; + try + { + ts = convertTo<time_t>(params[0]); + } + catch (const ConvertException &) { } + Channel *c = findchan(params[1]); Anope::string modes = params[2]; for (unsigned i = 3; i < params.size(); ++i) modes += " " + params[i]; - do_cmode(source, params[1], modes, params[0]); + + if (c) + c->SetModesInternal(source, modes, ts); + + return true; } - return true; -} +}; -bool event_pass(const Anope::string &source, const std::vector<Anope::string> ¶ms) +struct IRCDMessageUID : IRCDMessage { - TS6UPLINK = params[3]; - return true; -} + IRCDMessageUID() : IRCDMessage("UID", 9) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } -bool event_bmask(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - /* :42X BMASK 1106409026 #ircops b :*!*@*.aol.com */ - /* 0 1 2 3 */ - Channel *c = findchan(params[1]); - - if (c) - { - ChannelMode *ban = ModeManager::FindChannelModeByName(CMODE_BAN), - *except = ModeManager::FindChannelModeByName(CMODE_EXCEPT), - *invex = ModeManager::FindChannelModeByName(CMODE_INVITEOVERRIDE); - Anope::string bans = params[3]; - int count = myNumToken(bans, ' '), i; - for (i = 0; i <= count - 1; ++i) - { - Anope::string b = myStrGetToken(bans, ' ', i); - if (ban && params[2].equals_cs("b")) - c->SetModeInternal(NULL, ban, b); - else if (except && params[2].equals_cs("e")) - c->SetModeInternal(NULL, except, b); - if (invex && params[2].equals_cs("I")) - c->SetModeInternal(NULL, invex, b); - } + // :42X UID Adam 1 1348535644 +aow Adam 192.168.0.5 192.168.0.5 42XAAAAAB :Adam + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + /* Source is always the server */ + User *user = new User(params[0], params[4], params[5], "", params[6], source.GetServer(), params[8], params[2].is_pos_number_only() ? convertTo<time_t>(params[2]) : 0, params[3], params[7]); + if (user && user->server->IsSynced() && nickserv) + nickserv->Validate(user); + + return true; } - return true; -} +}; class ProtoRatbox : public Module { - Message message_kick, message_tmode, message_bmask, message_pass, message_tb, message_sid, message_encap, - message_pong; - RatboxProto ircd_proto; - RatboxIRCdMessage ircd_message; + + /* Core message handlers */ + CoreIRCDMessageAway core_message_away; + CoreIRCDMessageCapab core_message_capab; + CoreIRCDMessageError core_message_error; + CoreIRCDMessageKill core_message_kill; + CoreIRCDMessageMOTD core_message_motd; + CoreIRCDMessagePart core_message_part; + CoreIRCDMessagePing core_message_ping; + CoreIRCDMessagePrivmsg core_message_privmsg; + CoreIRCDMessageQuit core_message_quit; + CoreIRCDMessageSQuit core_message_squit; + CoreIRCDMessageStats core_message_stats; + CoreIRCDMessageTime core_message_time; + CoreIRCDMessageTopic core_message_topic; + CoreIRCDMessageVersion core_message_version; + + /* Our message handlers */ + IRCDMessageBMask message_bmask; + IRCDMessageEncap message_encap; + IRCDMessageJoin message_join; + IRCDMessageMode message_mode; + IRCDMessageNick message_nick; + IRCDMessagePass message_pass; + IRCDMessagePong message_pong; + IRCDMessageServer message_server; + IRCDMessageSID message_sid; + IRCDMessageSjoin message_sjoin; + IRCDMessageTBurst message_tburst; + IRCDMessageTMode message_tmode; + IRCDMessageUID message_uid; void AddModes() { @@ -554,18 +613,10 @@ class ProtoRatbox : public Module } public: - ProtoRatbox(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL), - message_kick("KICK", event_kick), message_tmode("TMODE", event_tmode), - message_bmask("BMASK", event_bmask), message_pass("PASS", event_pass), - message_tb("TB", event_tburst), message_sid("SID", event_sid), message_encap("ENCAP", event_encap), - message_pong("PONG", event_pong) + ProtoRatbox(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL) { this->SetAuthor("Anope"); - pmodule_ircd_var(&myIrcd); - pmodule_ircd_proto(&this->ircd_proto); - pmodule_ircd_message(&this->ircd_message); - this->AddModes(); Implementation i[] = { I_OnServerSync }; @@ -582,14 +633,6 @@ class ProtoRatbox : public Module it->second->GenerateUID(); } - ~ProtoRatbox() - { - pmodule_ircd_var(NULL); - pmodule_ircd_proto(NULL); - pmodule_ircd_message(NULL); - } - - void OnServerSync(Server *s) anope_override { if (nickserv) diff --git a/modules/protocol/unreal.cpp b/modules/protocol/unreal.cpp index 51e960fc0..59dd9ddd6 100644 --- a/modules/protocol/unreal.cpp +++ b/modules/protocol/unreal.cpp @@ -13,33 +13,24 @@ #include "module.h" -IRCDVar myIrcd = { - "UnrealIRCd 3.2.x", /* ircd name */ - "+Soiq", /* Modes used by pseudoclients */ - 1, /* SVSNICK */ - 1, /* Vhost */ - 1, /* Supports SNlines */ - 1, /* Supports SQlines */ - 1, /* Supports SZlines */ - 0, /* Join 2 Message */ - 0, /* Chan SQlines */ - 0, /* Quit on Kill */ - 1, /* vidents */ - 1, /* svshold */ - 1, /* time stamp on mode */ - 1, /* O:LINE */ - 1, /* UMODE */ - 1, /* No Knock requires +i */ - 1, /* Can remove User Channel Modes with SVSMODE */ - 0, /* Sglines are not enforced until user reconnects */ - 0, /* ts6 */ - "$", /* TLD Prefix for Global */ - 12, /* Max number of modes we can send per line */ - 0 /* IRCd sends a SSL users certificate fingerprint */ -}; - class UnrealIRCdProto : public IRCDProto { + public: + UnrealIRCdProto() : IRCDProto("UnrealIRCd 3.2.x") + { + DefaultPseudoclientModes = "+Soiq"; + CanSVSNick = true; + CanSetVHost = true; + CanSetVIdent = true; + CanSNLine = true; + CanSQLine = true; + CanSZLine = true; + CanSVSHold = true; + CanSVSO = true; + MaxModes = 12; + } + + private: /* SVSNOOP */ void SendSVSNOOP(const Server *server, bool set) anope_override { @@ -71,6 +62,16 @@ class UnrealIRCdProto : public IRCDProto UplinkSocket::Message(whosets) << ") " << c->name << " " << c->topic_setter << " " << c->topic_time + 1 << " :" << c->topic; } + void SendGlobalNotice(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override + { + UplinkSocket::Message(bi) << "NOTICE $" << dest->GetName() << " :" << msg; + } + + void SendGlobalPrivmsg(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override + { + UplinkSocket::Message(bi) << "PRIVMSG $" << dest->GetName() << " :" << msg; + } + void SendVhostDel(User *u) anope_override { const BotInfo *bi = findbot(Config->HostServ); @@ -248,9 +249,9 @@ class UnrealIRCdProto : public IRCDProto NS = Config->Numeric Server */ if (!Config->Numeric.empty()) - UplinkSocket::Message() << "PROTOCTL NICKv2 VHP UMODE2 NICKIP TOKEN SJOIN SJOIN2 SJ3 NOQUIT TKLEXT ESVID MLOCK VL"; + UplinkSocket::Message() << "PROTOCTL NICKv2 VHP UMODE2 NICKIP SJOIN SJOIN2 SJ3 NOQUIT TKLEXT ESVID MLOCK VL"; else - UplinkSocket::Message() << "PROTOCTL NICKv2 VHP UMODE2 NICKIP TOKEN SJOIN SJOIN2 SJ3 NOQUIT TKLEXT ESVID MLOCK"; + UplinkSocket::Message() << "PROTOCTL NICKv2 VHP UMODE2 NICKIP SJOIN SJOIN2 SJ3 NOQUIT TKLEXT ESVID MLOCK"; UplinkSocket::Message() << "PASS :" << Config->Uplinks[CurrentUplink]->password; SendServer(Me); } @@ -506,186 +507,11 @@ class ChannelModeUnrealSSL : public ChannelMode } }; -class Unreal32IRCdMessage : public IRCdMessage +struct IRCDMessageCapab : IRCDMessage { - public: - bool OnMode(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (params.size() < 2) - return true; - - bool server_source = Server::Find(source) != NULL; - Anope::string modes = params[1]; - for (unsigned i = 2; i < params.size() - (server_source ? 1 : 0); ++i) - modes += " " + params[i]; - - if (params[0][0] == '#' || params[0][0] == '&') - do_cmode(source, params[0], modes, server_source ? params[params.size() - 1] : ""); - else - do_umode(params[0], modes); - - return true; - } - - /* - ** NICK - new - ** source = NULL - ** parv[0] = nickname - ** parv[1] = hopcount - ** parv[2] = timestamp - ** parv[3] = username - ** parv[4] = hostname - ** parv[5] = servername - ** if NICK version 1: - ** parv[6] = servicestamp - ** parv[7] = info - ** if NICK version 2: - ** parv[6] = servicestamp - ** parv[7] = umodes - ** parv[8] = virthost, * if none - ** parv[9] = info - ** if NICKIP: - ** parv[9] = ip - ** parv[10] = info - ** - ** NICK - change - ** source = oldnick - ** parv[0] = new nickname - ** parv[1] = hopcount - */ - bool OnNick(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (params.size() == 7) - { - /* - <codemastr> that was a bug that is now fixed in 3.2.1 - <codemastr> in some instances it would use the non-nickv2 format - <codemastr> it's sent when a nick collision occurs - - so we have to leave it around for now -TSL - */ - do_nick(source, params[0], params[3], params[4], params[5], params[6], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : 0, "", "*", "", ""); - } - else if (params.size() == 11) - { - Anope::string decoded_ip; - Anope::B64Decode(params[9], decoded_ip); - - sockaddrs ip; - ip.ntop(params[9].length() == 8 ? AF_INET : AF_INET6, decoded_ip.c_str()); - - Anope::string vhost = params[8]; - if (vhost.equals_cs("*")) - vhost.clear(); - - User *user = do_nick(source, params[0], params[3], params[4], params[5], params[10], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : 0, ip.addr(), vhost, "", params[7]); - if (user) - { - const NickAlias *na = NULL; - - if (params[6] == "0") - ; - else if (params[6].is_pos_number_only()) - { - if (convertTo<time_t>(params[6]) == user->timestamp) - na = findnick(user->nick); - } - else - { - na = findnick(params[6]); - } - - if (na) - { - user->Login(na->nc); - if (!Config->NoNicknameOwnership && na->nc->HasFlag(NI_UNCONFIRMED) == false && nickserv) - user->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); - } - else if (nickserv) - nickserv->Validate(user); - } - } - else if (params.size() != 2) - { - Anope::string vhost = params[8]; - if (vhost.equals_cs("*")) - vhost.clear(); - - /* NON NICKIP */ - User *user = do_nick(source, params[0], params[3], params[4], params[5], params[9], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : 0, "", vhost, "", params[7]); - if (user) - { - const NickAlias *na = NULL; - - if (params[6] == "0") - ; - else if (params[6].is_pos_number_only()) - { - if (convertTo<time_t>(params[6]) == user->timestamp) - na = findnick(user->nick); - } - else - { - na = findnick(params[6]); - } - - if (na) - { - user->Login(na->nc); - if (!Config->NoNicknameOwnership && na->nc->HasFlag(NI_UNCONFIRMED) == false && nickserv) - user->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); - } - else if (nickserv) - nickserv->Validate(user); - } - } - else - do_nick(source, params[0], "", "", "", "", Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : 0, "", "", "", ""); - - return true; - } - - bool OnServer(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (params[1].equals_cs("1")) - { - Anope::string vl = myStrGetToken(params[2], ' ', 0); - Anope::string upnumeric = myStrGetToken(vl, '-', 2); - Anope::string desc = myStrGetTokenRemainder(params[2], ' ', 1); - do_server(source, params[0], Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0, desc, upnumeric); - } - else - do_server(source, params[0], Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0, params[2], ""); + IRCDMessageCapab() : IRCDMessage("PROTOCTL", 0) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } - ircdproto->SendPing(Config->ServerName, params[0]); - - return true; - } - - /* - ** source = sender prefix - ** parv[0] = channel name - ** parv[1] = topic nickname - ** parv[2] = topic time - ** parv[3] = topic text - */ - bool OnTopic(const Anope::string &, const std::vector<Anope::string> ¶ms) anope_override - { - if (params.size() != 4) - return true; - - Channel *c = findchan(params[0]); - if (!c) - { - Log() << "TOPIC for nonexistant channel " << params[0]; - return true; - } - - c->ChangeTopicInternal(params[1], params[3], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : Anope::CurTime); - - return true; - } - - bool OnCapab(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { for (unsigned i = 0; i < params.size(); ++i) { @@ -832,12 +658,283 @@ class Unreal32IRCdMessage : public IRCdMessage } } - IRCdMessage::OnCapab(source, params); + return true; + } +}; + +struct IRCDMessageChgHost : IRCDMessage +{ + IRCDMessageChgHost() : IRCDMessage("CHGHOST", 2) { } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + User *u = finduser(params[0]); + if (u) + u->SetDisplayedHost(params[1]); + return true; + } +}; + +struct IRCDMessageChgIdent : IRCDMessage +{ + IRCDMessageChgIdent() : IRCDMessage("CHGIDENT", 2) { } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + User *u = finduser(params[0]); + if (u) + u->SetVIdent(params[1]); + return true; + } +}; + +struct IRCDMessageChgName : IRCDMessage +{ + IRCDMessageChgName() : IRCDMessage("CHGNAME", 2) { } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + User *u = finduser(params[0]); + if (u) + u->SetRealname(params[1]); + return true; + } +}; + +struct IRCDMessageMode : IRCDMessage +{ + IRCDMessageMode(const Anope::string &mname) : IRCDMessage(mname, 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + bool server_source = source.GetServer() != NULL; + Anope::string modes = params[1]; + for (unsigned i = 2; i < params.size() - (server_source ? 1 : 0); ++i) + modes += " " + params[i]; + + if (ircdproto->IsChannelValid(params[0])) + { + Channel *c = findchan(params[0]); + time_t ts = Anope::CurTime; + try + { + if (server_source) + ts = convertTo<time_t>(params[params.size() - 1]); + } + catch (const ConvertException &) { } + + if (c) + c->SetModesInternal(source, modes, ts); + } + else + { + User *u = finduser(params[0]); + if (u) + u->SetModesInternal("%s", params[1].c_str()); + } + + return true; + } +}; + +/* netinfo + * argv[0] = max global count + * argv[1] = time of end sync + * argv[2] = unreal protocol using (numeric) + * argv[3] = cloak-crc (> u2302) + * argv[4] = free(**) + * argv[5] = free(**) + * argv[6] = free(**) + * argv[7] = ircnet + */ +struct IRCDMessageNetInfo : IRCDMessage +{ + IRCDMessageNetInfo() : IRCDMessage("NETINFO", 8) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + UplinkSocket::Message() << "AO " << maxusercnt << " " << Anope::CurTime << " " << convertTo<int>(params[2]) << " " << params[3] << " 0 0 0 :" << params[7]; + return true; + } +}; + +struct IRCDMessageNick : IRCDMessage +{ + IRCDMessageNick() : IRCDMessage("NICK", 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } + + /* + ** NICK - new + ** source = NULL + ** parv[0] = nickname + ** parv[1] = hopcount + ** parv[2] = timestamp + ** parv[3] = username + ** parv[4] = hostname + ** parv[5] = servername + ** parv[6] = servicestamp + ** parv[7] = umodes + ** parv[8] = virthost, * if none + ** parv[9] = ip + ** parv[10] = info + ** + ** NICK - change + ** source = oldnick + ** parv[0] = new nickname + ** parv[1] = hopcount + */ + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + if (params.size() == 11) + { + Anope::string decoded_ip; + Anope::B64Decode(params[9], decoded_ip); + + sockaddrs ip; + ip.ntop(params[9].length() == 8 ? AF_INET : AF_INET6, decoded_ip.c_str()); + + Anope::string vhost = params[8]; + if (vhost.equals_cs("*")) + vhost.clear(); + + time_t user_ts = params[2].is_pos_number_only() ? convertTo<time_t>(params[2]) : Anope::CurTime; + User *user = new User(params[0], params[3], params[4], vhost, ip.addr(), source.GetServer(), params[10], user_ts, params[7]); + + const NickAlias *na = NULL; + + if (params[6] == "0") + ; + else if (params[6].is_pos_number_only()) + { + if (convertTo<time_t>(params[6]) == user->timestamp) + na = findnick(user->nick); + } + else + { + na = findnick(params[6]); + } + + if (na) + { + user->Login(na->nc); + if (!Config->NoNicknameOwnership && na->nc->HasFlag(NI_UNCONFIRMED) == false && nickserv) + user->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); + } + else if (nickserv) + nickserv->Validate(user); + } + else + source.GetUser()->ChangeNick(params[0]); + return true; } +}; - bool OnSJoin(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override +/** This is here because: + * + * If we had three servers, A, B & C linked like so: A<->B<->C + * If Anope is linked to A and B splits from A and then reconnects + * B introduces itself, introduces C, sends EOS for C, introduces Bs clients + * introduces Cs clients, sends EOS for B. This causes all of Cs clients to be introduced + * with their server "not syncing". We now send a PING immediately when receiving a new server + * and then finish sync once we get a pong back from that server. + */ +struct IRCDMessagePong : IRCDMessage +{ + IRCDMessagePong() : IRCDMessage("PONG", 0) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + if (!source.GetServer()->IsSynced()) + source.GetServer()->Sync(false); + return true; + } +}; + +struct IRCDMessageSDesc : IRCDMessage +{ + IRCDMessageSDesc() : IRCDMessage("SDESC", 1) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + source.GetServer()->SetDescription(params[0]); + return true; + } +}; + +struct IRCDMessageSetHost : IRCDMessage +{ + IRCDMessageSetHost() : IRCDMessage("SETHOST", 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + User *u = source.GetUser(); + + /* When a user sets +x we recieve the new host and then the mode change */ + if (u->HasMode(UMODE_CLOAK)) + u->SetDisplayedHost(params[0]); + else + u->SetCloakedHost(params[0]); + + return true; + } +}; + +struct IRCDMessageSetIdent : IRCDMessage +{ + IRCDMessageSetIdent() : IRCDMessage("SETIDENT", 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + User *u = source.GetUser(); + u->SetVIdent(params[0]); + return true; + } +}; + +struct IRCDMessageSetName : IRCDMessage +{ + IRCDMessageSetName() : IRCDMessage("STENAME", 1) { } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + User *u = finduser(params[0]); + if (u) + u->SetRealname(params[1]); + return true; + } +}; + +struct IRCDMessageServer : IRCDMessage +{ + IRCDMessageServer() : IRCDMessage("SERVER", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + unsigned int hops = Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0; + + if (params[1].equals_cs("1")) + { + Anope::string vl = myStrGetToken(params[2], ' ', 0); + Anope::string upnumeric = myStrGetToken(vl, '-', 2); + Anope::string desc = myStrGetTokenRemainder(params[2], ' ', 1); + + new Server(source.GetServer() == NULL ? Me : source.GetServer(), params[0], hops, desc); + } + else + new Server(source.GetServer(), params[0], hops, params[2]); + + ircdproto->SendPing(Config->ServerName, params[0]); + + return true; + } +}; + +struct IRCDMessageSJoin : IRCDMessage +{ + IRCDMessageSJoin() : IRCDMessage("SJOIN", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { Channel *c = findchan(params[1]); time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo<time_t>(params[0]) : 0; @@ -867,7 +964,7 @@ class Unreal32IRCdMessage : public IRCdMessage if (!modes.empty()) modes.erase(modes.begin()); /* Set the modes internally */ - c->SetModesInternal(NULL, modes); + c->SetModesInternal(source, modes); } ChannelMode *ban = ModeManager::FindChannelModeByName(CMODE_BAN), @@ -878,22 +975,25 @@ class Unreal32IRCdMessage : public IRCdMessage while (sep.GetToken(buf)) { /* Ban */ - if (keep_their_modes && ban && buf[0] == '&') + if (buf[0] == '&') { buf.erase(buf.begin()); - c->SetModeInternal(NULL, ban, buf); + if (keep_their_modes && ban) + c->SetModeInternal(source, ban, buf); } /* Except */ - else if (keep_their_modes && except && buf[0] == '"') + else if (buf[0] == '"') { buf.erase(buf.begin()); - c->SetModeInternal(NULL, except, buf); + if (keep_their_modes && except) + c->SetModeInternal(source, except, buf); } /* Invex */ - else if (keep_their_modes && invex && buf[0] == '\'') + else if (buf[0] == '\'') { buf.erase(buf.begin()); - c->SetModeInternal(NULL, invex, buf); + if (keep_their_modes && invex) + c->SetModeInternal(source, invex, buf); } else { @@ -932,7 +1032,7 @@ class Unreal32IRCdMessage : public IRCdMessage * This will enforce secureops etc on the user */ for (std::list<ChannelMode *>::iterator it = Status.begin(), it_end = Status.end(); it != it_end; ++it) - c->SetModeInternal(NULL, *it, buf); + c->SetModeInternal(source, *it, buf); /* Now set whatever modes this user is allowed to have on the channel */ chan_set_correct_modes(u, c, 1, true); @@ -960,184 +1060,78 @@ class Unreal32IRCdMessage : public IRCdMessage } }; - -/** This is here because: - * - * If we had three servers, A, B & C linked like so: A<->B<->C - * If Anope is linked to A and B splits from A and then reconnects - * B introduces itself, introduces C, sends EOS for C, introduces Bs clients - * introduces Cs clients, sends EOS for B. This causes all of Cs clients to be introduced - * with their server "not syncing". We now send a PING immediately when receiving a new server - * and then finish sync once we get a pong back from that server. - */ -bool event_pong(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - Server *s = Server::Find(source); - if (s && !s->IsSynced()) - s->Sync(false); - return true; -} - -/* netinfo - * argv[0] = max global count - * argv[1] = time of end sync - * argv[2] = unreal protocol using (numeric) - * argv[3] = cloak-crc (> u2302) - * argv[4] = free(**) - * argv[5] = free(**) - * argv[6] = free(**) - * argv[7] = ircnet - */ -bool event_netinfo(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - UplinkSocket::Message() << "AO " << maxusercnt << " " << Anope::CurTime << " " << convertTo<int>(params[2]) << " " << params[3] << " 0 0 0 :" << params[7]; - return true; -} - -/* Unreal sends USER modes with this */ -/* - umode2 - parv[0] - sender - parv[1] - modes to change -*/ -bool event_umode2(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() < 1) - return true; - - do_umode(source, params[0]); - return true; -} - - -bool event_setname(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() != 1) - return true; - - User *u = finduser(source); - if (!u) - { - Log(LOG_DEBUG) << "SETNAME for nonexistent user " << source; - return true; - } - - u->SetRealname(params[0]); - return true; -} - -bool event_chgname(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() != 2) - return true; - - User *u = finduser(params[0]); - if (!u) - { - Log(LOG_DEBUG) << "CHGNAME for nonexistent user " << params[0]; - return true; - } - - u->SetRealname(params[1]); - return true; -} - -bool event_setident(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() != 1) - return true; - - User *u = finduser(source); - if (!u) - { - Log(LOG_DEBUG) << "SETIDENT for nonexistent user " << source; - return true; - } - - u->SetVIdent(params[0]); - return true; -} - -bool event_chgident(const Anope::string &source, const std::vector<Anope::string> ¶ms) +struct IRCDMessageTopic : IRCDMessage { - if (params.size() != 2) - return true; + IRCDMessageTopic() : IRCDMessage("TOPIC", 4) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } - User *u = finduser(params[0]); - if (!u) + /* + ** source = sender prefix + ** parv[0] = channel name + ** parv[1] = topic nickname + ** parv[2] = topic time + ** parv[3] = topic text + */ + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - Log(LOG_DEBUG) << "CHGIDENT for nonexistent user " << params[0]; - return true; - } - - u->SetVIdent(params[1]); - return true; -} - -bool event_sethost(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() != 1) - return true; + Channel *c = findchan(params[0]); + if (c) + c->ChangeTopicInternal(params[1], params[3], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : Anope::CurTime); - User *u = finduser(source); - if (!u) - { - Log(LOG_DEBUG) << "SETHOST for nonexistent user " << source; return true; } +}; - /* When a user sets +x we recieve the new host and then the mode change */ - if (u->HasMode(UMODE_CLOAK)) - u->SetDisplayedHost(params[0]); - else - u->SetCloakedHost(params[0]); - - return true; -} -bool event_chghost(const Anope::string &source, const std::vector<Anope::string> ¶ms) +struct IRCDMessageUmode2 : IRCDMessage { - if (params.size() != 2) - return true; + IRCDMessageUmode2() : IRCDMessage("UMODE2", 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } - User *u = finduser(params[0]); - if (!u) + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - Log(LOG_DEBUG) << "debug: CHGHOST for nonexistent user " << params[0]; + source.GetUser()->SetModesInternal("%s", params[0].c_str()); return true; } - - u->SetDisplayedHost(params[1]); - return true; -} - -bool event_sdesc(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - Server *s = Server::Find(source); - - if (s) - s->SetDescription(params[0]); - - return true; -} +}; class ProtoUnreal : public Module { - Message message_away, message_join, message_kick, - message_kill, message_mode, message_nick, message_part, - message_ping, message_pong, message_pong2, message_privmsg, - message_quit, message_server, message_squit, message_topic, - message_svsmode, message_svsmode2, message_svs2mode, message_svs2mode2, message_whois, - message_capab, message_capab2, message_chghost, message_chghost2, message_chgident, message_chgident2, - message_chgname, message_chgname2, message_netinfo, message_netinfo2, message_sethost, message_sethost2, - message_setident, message_setident2, message_setname, message_setname2, message_error, - message_umode2, message_umode22, message_sjoin, message_sdesc, message_sdesc2; - - /* Non-token of these in messages.cpp */ - Message message_stats, message_time, message_version; - UnrealIRCdProto ircd_proto; - Unreal32IRCdMessage ircd_message; + + /* Core message handlers */ + CoreIRCDMessageAway core_message_away; + CoreIRCDMessageCapab core_message_capab; + CoreIRCDMessageError core_message_error; + CoreIRCDMessageJoin core_message_join; + CoreIRCDMessageKill core_message_kill; + CoreIRCDMessageMOTD core_message_motd; + CoreIRCDMessagePart core_message_part; + CoreIRCDMessagePing core_message_ping; + CoreIRCDMessagePrivmsg core_message_privmsg; + CoreIRCDMessageQuit core_message_quit; + CoreIRCDMessageSQuit core_message_squit; + CoreIRCDMessageStats core_message_stats; + CoreIRCDMessageTime core_message_time; + CoreIRCDMessageTopic core_message_topic; + CoreIRCDMessageVersion core_message_version; + CoreIRCDMessageWhois core_message_whois; + + /* Our message handlers */ + IRCDMessageCapab message_capab; + IRCDMessageChgHost message_chghost; + IRCDMessageChgIdent message_chgident; + IRCDMessageChgName message_chgname; + IRCDMessageMode message_mode, message_svsmode, message_svs2mode; + IRCDMessageNetInfo message_netinfo; + IRCDMessageNick message_nick; + IRCDMessagePong message_pong; + IRCDMessageSDesc message_sdesc; + IRCDMessageSetHost message_sethost; + IRCDMessageSetIdent message_setident; + IRCDMessageSetName message_setname; + IRCDMessageServer message_server; + IRCDMessageSJoin message_sjoin; + IRCDMessageTopic message_topic; + IRCDMessageUmode2 message_umode2; void AddModes() { @@ -1179,37 +1173,10 @@ class ProtoUnreal : public Module public: ProtoUnreal(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL), - message_away("6", OnAway), - message_join("C", OnJoin), - message_kick("H", OnKick), message_kill(".", OnKill), - message_mode("G", OnMode), - message_nick("&", OnNick), message_part("D", OnPart), - message_ping("8", OnPing), message_pong("PONG", event_pong), - message_pong2("9", event_pong), message_privmsg("!", ::OnPrivmsg), - message_quit(",", OnQuit), - message_server("'", OnServer), message_squit("-", OnSQuit), - message_topic(")", OnTopic), message_svsmode("SVSMODE", OnMode), - message_svsmode2("n", OnMode), message_svs2mode("SVS2MODE", OnMode), message_svs2mode2("v", OnMode), - message_whois("#", OnWhois), message_capab("PROTOCTL", OnCapab), - message_capab2("_", OnCapab), message_chghost("CHGHOST", event_chghost), message_chghost2("AL", event_chghost), - message_chgident("CHGIDENT", event_chgident), message_chgident2("AZ", event_chgident), - message_chgname("CHGNAME", event_chgname), message_chgname2("BK", event_chgname), - message_netinfo("NETINFO", event_netinfo), message_netinfo2("AO", event_netinfo), - message_sethost("SETHOST", event_sethost), message_sethost2("AA", event_sethost), - message_setident("SETIDENT", event_setident), message_setident2("AD", event_setident), - message_setname("SETNAME", event_setname), message_setname2("AE", event_setname), - message_error("5", OnError), message_umode2("UMODE2", event_umode2), - message_umode22("|", event_umode2), message_sjoin("~", OnSJoin), - message_sdesc("SDESC", event_sdesc), message_sdesc2("AG", event_sdesc), - - message_stats("2", OnStats), message_time(">", OnTime), message_version("+", OnVersion) + message_mode("MODE"), message_svsmode("SVSMODE"), message_svs2mode("SVS2MODE") { this->SetAuthor("Anope"); - pmodule_ircd_var(&myIrcd); - pmodule_ircd_proto(&this->ircd_proto); - pmodule_ircd_message(&this->ircd_message); - this->AddModes(); Implementation i[] = { I_OnUserNickChange, I_OnChannelCreate, I_OnChanRegistered, I_OnDelChan, I_OnMLock, I_OnUnMLock }; @@ -1217,14 +1184,6 @@ class ProtoUnreal : public Module ModuleManager::SetPriority(this, PRIORITY_FIRST); } - ~ProtoUnreal() - { - pmodule_ircd_var(NULL); - pmodule_ircd_proto(NULL); - pmodule_ircd_message(NULL); - } - - void OnUserNickChange(User *u, const Anope::string &) anope_override { u->RemoveModeInternal(ModeManager::FindUserModeByName(UMODE_REGISTERED)); diff --git a/modules/pseudoclients/botserv.cpp b/modules/pseudoclients/botserv.cpp index beab46b23..d792f74da 100644 --- a/modules/pseudoclients/botserv.cpp +++ b/modules/pseudoclients/botserv.cpp @@ -199,7 +199,7 @@ class BotServCore : public Module "the following characters: %s"), Config->ChanServ.c_str(), Config->BSFantasyCharacter.c_str()); } - EventReturn OnChannelModeSet(Channel *c, User *setter, ChannelModeName Name, const Anope::string ¶m) anope_override + EventReturn OnChannelModeSet(Channel *c, MessageSource &, ChannelModeName Name, const Anope::string ¶m) anope_override { if (Config->BSSmartJoin && Name == CMODE_BAN && c->ci && c->ci->bi && c->FindUser(c->ci->bi)) { diff --git a/modules/pseudoclients/hostserv.cpp b/modules/pseudoclients/hostserv.cpp index c350903d0..33d183b9a 100644 --- a/modules/pseudoclients/hostserv.cpp +++ b/modules/pseudoclients/hostserv.cpp @@ -20,8 +20,8 @@ class HostServCore : public Module { this->SetAuthor("Anope"); - if (!ircd || !ircd->vhost) - throw ModuleException("Your IRCd does not suppor vhosts"); + if (!ircdproto || !ircdproto->CanSetVHost) + throw ModuleException("Your IRCd does not support vhosts"); const BotInfo *HostServ = findbot(Config->HostServ); if (HostServ == NULL) @@ -36,18 +36,17 @@ class HostServCore : public Module const NickAlias *na = findnick(u->nick); if (!na || !na->HasVhost()) na = findnick(u->Account()->display); - if (!na || !na->HasVhost()) + if (!ircdproto->CanSetVHost || !na || !na->HasVhost()) return; if (u->vhost.empty() || !u->vhost.equals_cs(na->GetVhostHost()) || (!na->GetVhostIdent().empty() && !u->GetVIdent().equals_cs(na->GetVhostIdent()))) { ircdproto->SendVhost(u, na->GetVhostIdent(), na->GetVhostHost()); - if (ircd->vhost) - { - u->vhost = na->GetVhostHost(); - u->UpdateHost(); - } - if (ircd->vident && !na->GetVhostIdent().empty()) + + u->vhost = na->GetVhostHost(); + u->UpdateHost(); + + if (ircdproto->CanSetVIdent && !na->GetVhostIdent().empty()) u->SetVIdent(na->GetVhostIdent()); const BotInfo *bi = findbot(Config->HostServ); diff --git a/modules/pseudoclients/operserv.cpp b/modules/pseudoclients/operserv.cpp index d9fa44597..b02120e91 100644 --- a/modules/pseudoclients/operserv.cpp +++ b/modules/pseudoclients/operserv.cpp @@ -37,7 +37,7 @@ class SGLineManager : public XLineManager { try { - if (!ircd->szline) + if (!ircdproto->CanSZLine) throw SocketException("SZLine is not supported"); else if (x->GetUser() != "*") throw SocketException("Can not ZLine a username"); @@ -236,7 +236,7 @@ class OperServCore : public Module void OnUserNickChange(User *u, const Anope::string &oldnick) anope_override { - if (ircd->sqline && !u->HasMode(UMODE_OPER)) + if (ircdproto->CanSQLine && !u->HasMode(UMODE_OPER)) this->sqlines.CheckAllXLines(u); } diff --git a/src/bots.cpp b/src/bots.cpp index 53f9b78c1..ffe814351 100644 --- a/src/bots.cpp +++ b/src/bots.cpp @@ -21,11 +21,8 @@ serialize_checker<botinfo_map> BotListByNick("BotInfo"); serialize_checker<botinfouid_map> BotListByUID("BotInfo"); -BotInfo::BotInfo(const Anope::string &nnick, const Anope::string &nuser, const Anope::string &nhost, const Anope::string &nreal, const Anope::string &bmodes) : User(nnick, nuser, nhost, ts6_uid_retrieve()), Flags<BotFlag, BI_END>(BotFlagString), botmodes(bmodes) +BotInfo::BotInfo(const Anope::string &nnick, const Anope::string &nuser, const Anope::string &nhost, const Anope::string &nreal, const Anope::string &bmodes) : User(nnick, nuser, nhost, "", "", Me, nreal, Anope::CurTime, "", ts6_uid_retrieve()), Flags<BotFlag, BI_END>(BotFlagString), botmodes(bmodes) { - this->realname = nreal; - this->server = Me; - this->lastmsg = this->created = Anope::CurTime; this->introduced = false; @@ -36,7 +33,7 @@ BotInfo::BotInfo(const Anope::string &nnick, const Anope::string &nuser, const A // If we're synchronised with the uplink already, send the bot. if (Me && Me->IsSynced()) { - Anope::string tmodes = !this->botmodes.empty() ? ("+" + this->botmodes) : (ircd ? ircd->pseudoclient_mode : ""); + Anope::string tmodes = !this->botmodes.empty() ? ("+" + this->botmodes) : (ircdproto ? ircdproto->DefaultPseudoclientModes : ""); if (!tmodes.empty()) this->SetModesInternal(tmodes.c_str()); diff --git a/src/botserv.cpp b/src/botserv.cpp index 5718be81a..27666f7ec 100644 --- a/src/botserv.cpp +++ b/src/botserv.cpp @@ -25,7 +25,7 @@ BotInfo* findbot(const Anope::string &nick) { BotInfo *bi = NULL; - if (isdigit(nick[0]) && ircd->ts6) + if (isdigit(nick[0]) && ircdproto->RequiresID) { botinfouid_map::iterator it = BotListByUID->find(nick); if (it != BotListByUID->end()) diff --git a/src/channels.cpp b/src/channels.cpp index e89b6010d..1790ddda1 100644 --- a/src/channels.cpp +++ b/src/channels.cpp @@ -337,7 +337,7 @@ std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> Channel::Get * @param param The param * @param EnforeMLock true if mlocks should be enforced, false to override mlock */ -void Channel::SetModeInternal(User *setter, ChannelMode *cm, const Anope::string ¶m, bool EnforceMLock) +void Channel::SetModeInternal(MessageSource &setter, ChannelMode *cm, const Anope::string ¶m, bool EnforceMLock) { if (!cm) return; @@ -412,7 +412,7 @@ void Channel::SetModeInternal(User *setter, ChannelMode *cm, const Anope::string * @param param The param * @param EnforceMLock true if mlocks should be enforced, false to override mlock */ -void Channel::RemoveModeInternal(User *setter, ChannelMode *cm, const Anope::string ¶m, bool EnforceMLock) +void Channel::RemoveModeInternal(MessageSource &setter, ChannelMode *cm, const Anope::string ¶m, bool EnforceMLock) { if (!cm) return; @@ -537,7 +537,8 @@ void Channel::SetMode(BotInfo *bi, ChannelMode *cm, const Anope::string ¶m, } ModeManager::StackerAdd(bi, this, cm, true, param); - SetModeInternal(bi, cm, param, EnforceMLock); + MessageSource ms(bi); + SetModeInternal(ms, cm, param, EnforceMLock); } /** @@ -589,7 +590,8 @@ void Channel::RemoveMode(BotInfo *bi, ChannelMode *cm, const Anope::string ¶ } ModeManager::StackerAdd(bi, this, cm, false, realparam); - RemoveModeInternal(bi, cm, realparam, EnforceMLock); + MessageSource ms(bi); + RemoveModeInternal(ms, cm, realparam, EnforceMLock); } /** @@ -680,13 +682,29 @@ void Channel::SetModes(BotInfo *bi, bool EnforceMLock, const char *cmodes, ...) } } -/** Set a string of modes internally on a channel - * @param setter The setter, if it is a user - * @param mode the modes - * @param EnforceMLock true to enforce mlock - */ -void Channel::SetModesInternal(User *setter, const Anope::string &mode, bool EnforceMLock) +void Channel::SetModesInternal(MessageSource &source, const Anope::string &mode, time_t ts, bool EnforceMLock) { + if (source.GetServer()) + { + if (Anope::CurTime != this->server_modetime) + { + this->server_modecount = 0; + this->server_modetime = Anope::CurTime; + } + + ++this->server_modecount; + } + + if (ts > 0 && ts < this->creation_time) + return; + else if (ts > this->creation_time) + { + Log(LOG_DEBUG) << "Changing TS of " << this->name << " from " << this->creation_time << " to " << ts; + this->creation_time = ts; + this->Reset(); + } + + User *setter = source.GetUser(); /* Removing channel modes *may* delete this channel */ dynamic_reference<Channel> this_reference(this); @@ -727,9 +745,9 @@ void Channel::SetModesInternal(User *setter, const Anope::string &mode, bool Enf if (cm->Type == MODE_REGULAR) { if (add) - this->SetModeInternal(setter, cm, "", EnforceMLock); + this->SetModeInternal(source, cm, "", EnforceMLock); else - this->RemoveModeInternal(setter, cm, "", EnforceMLock); + this->RemoveModeInternal(source, cm, "", EnforceMLock); continue; } else if (cm->Type == MODE_PARAM) @@ -738,7 +756,7 @@ void Channel::SetModesInternal(User *setter, const Anope::string &mode, bool Enf if (!add && cmp->MinusNoArg) { - this->RemoveModeInternal(setter, cm, "", EnforceMLock); + this->RemoveModeInternal(source, cm, "", EnforceMLock); continue; } } @@ -752,9 +770,9 @@ void Channel::SetModesInternal(User *setter, const Anope::string &mode, bool Enf paramstring += " " + token; if (add) - this->SetModeInternal(setter, cm, token, EnforceMLock); + this->SetModeInternal(source, cm, token, EnforceMLock); else - this->RemoveModeInternal(setter, cm, token, EnforceMLock); + this->RemoveModeInternal(source, cm, token, EnforceMLock); } else Log() << "warning: Channel::SetModesInternal() recieved more modes requiring params than params, modes: " << mode; @@ -766,7 +784,7 @@ void Channel::SetModesInternal(User *setter, const Anope::string &mode, bool Enf if (setter) Log(setter, this, "mode") << modestring << paramstring; else - Log(LOG_DEBUG) << "Setting " << this->name << " to " << modestring << paramstring; + Log(LOG_DEBUG) << source.GetName() << " is setting " << this->name << " to " << modestring << paramstring; } /** Kick a user from a channel internally @@ -774,23 +792,24 @@ void Channel::SetModesInternal(User *setter, const Anope::string &mode, bool Enf * @param nick The nick being kicked * @param reason The reason for the kick */ -void Channel::KickInternal(const Anope::string &source, const Anope::string &nick, const Anope::string &reason) +void Channel::KickInternal(MessageSource &source, const Anope::string &nick, const Anope::string &reason) { - User *sender = finduser(source); - BotInfo *bi = NULL; - if (this->ci && this->ci->bi) - bi = findbot(nick); - User *target = bi ? bi : finduser(nick); + User *sender = source.GetUser(); + User *target = finduser(nick); if (!target) { Log() << "Channel::KickInternal got a nonexistent user " << nick << " on " << this->name << ": " << reason; return; } + BotInfo *bi = NULL; + if (target->server == Me) + bi = findbot(nick); + if (sender) Log(sender, this, "kick") << "kicked " << target->nick << " (" << reason << ")"; else - Log(target, this, "kick") << "was kicked by " << source << " (" << reason << ")"; + Log(target, this, "kick") << "was kicked by " << source.GetSource() << " (" << reason << ")"; Anope::string chname = this->name; @@ -802,7 +821,7 @@ void Channel::KickInternal(const Anope::string &source, const Anope::string &nic this->DeleteUser(target); } else - Log() << "Channel::KickInternal got kick for user " << target->nick << " from " << (sender ? sender->nick : source) << " who isn't on channel " << this->name; + Log() << "Channel::KickInternal got kick for user " << target->nick << " from " << source.GetSource() << " who isn't on channel " << this->name; /* Bots get rejoined */ if (bi) @@ -833,13 +852,17 @@ bool Channel::Kick(BotInfo *bi, User *u, const char *reason, ...) /* Do not kick protected clients */ if (u->IsProtected()) return false; + + if (bi == NULL) + bi = this->ci->WhoSends(); EventReturn MOD_RESULT; FOREACH_RESULT(I_OnBotKick, OnBotKick(bi, this, u, buf)); if (MOD_RESULT == EVENT_STOP) return false; - ircdproto->SendKick(bi ? bi : this->ci->WhoSends(), this, u, "%s", buf); - this->KickInternal(bi ? bi->nick : this->ci->WhoSends()->nick, u->nick, buf); + ircdproto->SendKick(bi, this, u, "%s", buf); + MessageSource ms(bi); + this->KickInternal(ms, u->nick, buf); return true; } @@ -870,13 +893,14 @@ Anope::string Channel::GetModes(bool complete, bool plus) void Channel::ChangeTopicInternal(const Anope::string &user, const Anope::string &newtopic, time_t ts) { User *u = finduser(user); + this->topic = newtopic; this->topic_setter = u ? u->nick : user; this->topic_time = ts; - Log(LOG_DEBUG) << "Topic of " << this->name << " changed by " << user << " to " << newtopic; + Log(LOG_DEBUG) << "Topic of " << this->name << " changed by " << (u ? u->nick : user) << " to " << newtopic; - FOREACH_MOD(I_OnTopicUpdated, OnTopicUpdated(this, u, this->topic)); + FOREACH_MOD(I_OnTopicUpdated, OnTopicUpdated(this, user, this->topic)); if (this->ci) this->ci->CheckTopic(); @@ -885,13 +909,14 @@ void Channel::ChangeTopicInternal(const Anope::string &user, const Anope::string void Channel::ChangeTopic(const Anope::string &user, const Anope::string &newtopic, time_t ts) { User *u = finduser(user); + this->topic = newtopic; this->topic_setter = u ? u->nick : user; this->topic_time = ts; ircdproto->SendTopic(this->ci->WhoSends(), this); - FOREACH_MOD(I_OnTopicUpdated, OnTopicUpdated(this, u, this->topic)); + FOREACH_MOD(I_OnTopicUpdated, OnTopicUpdated(this, user, this->topic)); if (this->ci) this->ci->CheckTopic(); @@ -978,172 +1003,6 @@ User *nc_on_chan(Channel *c, const NickCore *nc) return NULL; } -/*************************************************************************/ -/*************************** Message Handling ****************************/ -/*************************************************************************/ - -/** Handle a JOIN command - * @param source user joining - * @param channels being joined - * @param ts TS for the join - */ -void do_join(const Anope::string &source, const Anope::string &channels, const Anope::string &ts) -{ - User *user = finduser(source); - if (!user) - { - Log() << "JOIN from nonexistent user " << source << ": " << channels; - return; - } - - commasepstream sep(channels); - Anope::string buf; - while (sep.GetToken(buf)) - { - if (buf[0] == '0') - { - for (UChannelList::iterator it = user->chans.begin(), it_end = user->chans.end(); it != it_end; ) - { - ChannelContainer *cc = *it++; - - Anope::string channame = cc->chan->name; - FOREACH_MOD(I_OnPrePartChannel, OnPrePartChannel(user, cc->chan)); - cc->chan->DeleteUser(user); - FOREACH_MOD(I_OnPartChannel, OnPartChannel(user, findchan(channame), channame, "")); - } - user->chans.clear(); - continue; - } - - Channel *chan = findchan(buf); - - /* Channel doesn't exist, create it */ - if (!chan) - chan = new Channel(buf, Anope::CurTime); - - /* Join came with a TS */ - if (!ts.empty()) - { - time_t t = Anope::string(ts).is_pos_number_only() ? convertTo<time_t>(ts) : 0; - - /* Their time is older, we lose */ - if (t && chan->creation_time > t) - { - Log(LOG_DEBUG) << "Recieved an older TS " << chan->name << " in JOIN, changing from " << chan->creation_time << " to " << ts; - chan->creation_time = t; - - chan->Reset(); - } - } - - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnPreJoinChannel, OnPreJoinChannel(user, chan)); - - /* Join the user to the channel */ - chan->JoinUser(user); - /* Set the propre modes on the user */ - chan_set_correct_modes(user, chan, 1, true); - - /* Modules may want to allow this user in the channel, check. - * If not, CheckKick will kick/ban them, don't call OnJoinChannel after this as the user will have - * been destroyed - */ - if (MOD_RESULT != EVENT_STOP && chan && chan->ci && chan->ci->CheckKick(user)) - continue; - - FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(user, chan)); - } -} - -/*************************************************************************/ - -/** Handle a KICK command. - * @param source The source of the kick - * @param users the user(s) being kicked - * @param reason The reason for the kick - */ -void do_kick(const Anope::string &source, const Anope::string &channel, const Anope::string &users, const Anope::string &reason) -{ - Channel *c = findchan(channel); - if (!c) - { - Log() << "Recieved kick for nonexistant channel " << channel; - return; - } - - Anope::string buf; - commasepstream sep(users); - while (sep.GetToken(buf)) - c->KickInternal(source, buf, reason); -} - -/*************************************************************************/ - -void do_part(const Anope::string &source, const Anope::string &channels, const Anope::string &reason) -{ - User *user = finduser(source); - if (!user) - { - Log() << "PART from nonexistent user " << source << ": " << reason; - return; - } - - commasepstream sep(channels); - Anope::string buf; - while (sep.GetToken(buf)) - { - Channel *c = findchan(buf); - - if (!c) - Log() << "Recieved PART from " << user->nick << " for nonexistant channel " << buf; - else if (user->FindChannel(c)) - { - Log(user, c, "part") << "Reason: " << (!reason.empty() ? reason : "No reason"); - FOREACH_MOD(I_OnPrePartChannel, OnPrePartChannel(user, c)); - Anope::string ChannelName = c->name; - c->DeleteUser(user); - FOREACH_MOD(I_OnPartChannel, OnPartChannel(user, findchan(ChannelName), ChannelName, !reason.empty() ? reason : "")); - } - else - Log() << "Recieved PART from " << user->nick << " for " << c->name << ", but " << user->nick << " isn't in " << c->name << "?"; - } -} - -/*************************************************************************/ - -/** Process a MODE command from the server, and set the modes on the user/channel - * it was sent for - * @param source The source of the command - * @param channel the channel to change modes on - * @param modes the mode changes - * @param ts the timestamp for the modes - */ -void do_cmode(const Anope::string &source, const Anope::string &channel, const Anope::string &modes, const Anope::string &ts) -{ - Channel *c = findchan(channel); - if (!c) - { - Log(LOG_DEBUG) << "MODE " << modes << " for nonexistant channel " << channel; - return; - } - - Log(LOG_DEBUG) << "MODE " << channel << " " << modes << " ts: " << ts; - - if (source.find('.') != Anope::string::npos) - { - if (Anope::CurTime != c->server_modetime) - { - c->server_modecount = 0; - c->server_modetime = Anope::CurTime; - } - ++c->server_modecount; - } - - c->SetModesInternal(finduser(source), modes); -} - -/*************************************************************************/ - /** * Set the correct modes, or remove the ones granted without permission, * for the specified user on ths specified channel. This doesn't give diff --git a/src/init.cpp b/src/init.cpp index b1001904c..ee36cb39a 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -481,8 +481,6 @@ void Init(int ac, char **av) /* Initialize the socket engine */ SocketEngine::Init(); - init_core_messages(); - /* Write our PID to the PID file. */ write_pidfile(); diff --git a/src/main.cpp b/src/main.cpp index cdddc3163..d43bda2bc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -213,10 +213,7 @@ UplinkSocket::Message::~Message() return; } - if (ircd->ts6) - message_source = this->server->GetSID(); - else - message_source = this->server->GetName(); + message_source = this->server->GetSID(); } else if (this->user != NULL) { @@ -233,10 +230,7 @@ UplinkSocket::Message::~Message() return; } - if (ircd->ts6) - message_source = this->user->GetUID(); - else - message_source = this->user->nick; + message_source = this->user->GetUID(); } if (!UplinkSock) diff --git a/src/messages.cpp b/src/messages.cpp index b34841094..2faa1cbb1 100644 --- a/src/messages.cpp +++ b/src/messages.cpp @@ -1,4 +1,4 @@ -/* Definitions of IRC message functions and list of messages. +/* Common message handlers * * (C) 2003-2012 Anope Team * Contact us at team@anope.org @@ -17,30 +17,288 @@ #include "extern.h" #include "uplink.h" #include "opertype.h" +#include "messages.h" +#include "servers.h" +#include "channels.h" -bool OnStats(const Anope::string &source, const std::vector<Anope::string> ¶ms) +bool CoreIRCDMessageAway::Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - if (params.size() < 1) + FOREACH_MOD(I_OnUserAway, OnUserAway(source.GetUser(), params.empty() ? "" : params[0])); + return true; +} + +bool CoreIRCDMessageCapab::Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override +{ + for (unsigned i = 0; i < params.size(); ++i) + Capab.insert(params[i]); + return true; +} + +bool CoreIRCDMessageError::Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override +{ + Log(LOG_TERMINAL) << "ERROR: " << params[0]; + quitmsg = "Received ERROR from uplink: " + params[0]; + + return true; +} + +bool CoreIRCDMessageJoin::Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override +{ + User *user = source.GetUser(); + const Anope::string &channels = params[0]; + + Anope::string channel; + commasepstream sep(channels); + + while (sep.GetToken(channel)) + { + /* Special case for /join 0 */ + if (channel == "0") + { + for (UChannelList::iterator it = user->chans.begin(), it_end = user->chans.end(); it != it_end; ) + { + ChannelContainer *cc = *it++; + + Anope::string channame = cc->chan->name; + FOREACH_MOD(I_OnPrePartChannel, OnPrePartChannel(user, cc->chan)); + cc->chan->DeleteUser(user); + FOREACH_MOD(I_OnPartChannel, OnPartChannel(user, findchan(channame), channame, "")); + } + user->chans.clear(); + continue; + } + + Channel *chan = findchan(channel); + /* Channel doesn't exist, create it */ + if (!chan) + chan = new Channel(channel, Anope::CurTime); + + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnPreJoinChannel, OnPreJoinChannel(user, chan)); + + /* Join the user to the channel */ + chan->JoinUser(user); + /* Set the proper modes on the user */ + chan_set_correct_modes(user, chan, 1, true); + + /* Modules may want to allow this user in the channel, check. + * If not, CheckKick will kick/ban them, don't call OnJoinChannel after this as the user will have + * been destroyed + */ + if (MOD_RESULT != EVENT_STOP && chan && chan->ci && chan->ci->CheckKick(user)) + continue; + + FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(user, chan)); + } + + return true; +} + +bool CoreIRCDMessageKill::Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override +{ + User *u = finduser(params[0]); + BotInfo *bi; + + if (!u) return true; - User *u = finduser(source); + /* Recover if someone kills us. */ + if (u->server == Me && (bi = dynamic_cast<BotInfo *>(u))) + { + bi->introduced = false; + introduce_user(bi->nick); + bi->RejoinAll(); + } + else + u->KillInternal(source.GetSource(), params[1]); + + return true; +} + +/* XXX We should cache the file somewhere not open/read/close it on every request */ +bool CoreIRCDMessageMOTD::Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override +{ + Server *s = Server::Find(params[0]); + if (s != Me) + return true; + + FILE *f = fopen(Config->MOTDFilename.c_str(), "r"); + if (f) + { + ircdproto->SendNumeric(375, source.GetSource(), ":- %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(372, source.GetSource(), ":- %s", buf); + } + fclose(f); + ircdproto->SendNumeric(376, source.GetSource(), ":End of /MOTD command."); + } + else + ircdproto->SendNumeric(422, source.GetSource(), ":- MOTD file not found! Please contact your IRC administrator."); + + return true; +} + +bool CoreIRCDMessagePart::Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override +{ + User *u = source.GetUser(); + const Anope::string &reason = params.size() > 1 ? params[1] : ""; + + Anope::string channel; + commasepstream sep(params[0]); + + while (sep.GetToken(channel)) + { + dynamic_reference<Channel> c = findchan(channel); + + if (!c || !u->FindChannel(c)) + continue; + + Log(u, c, "part") << "Reason: " << (!reason.empty() ? reason : "No reason"); + FOREACH_MOD(I_OnPrePartChannel, OnPrePartChannel(u, c)); + Anope::string ChannelName = c->name; + c->DeleteUser(u); + FOREACH_MOD(I_OnPartChannel, OnPartChannel(u, c, ChannelName, !reason.empty() ? reason : "")); + } + + return true; +} + +bool CoreIRCDMessagePing::Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override +{ + ircdproto->SendPong(params.size() > 1 ? params[1] : Me->GetSID(), params[0]); + return true; +} + +bool CoreIRCDMessagePrivmsg::Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override +{ + const Anope::string &receiver = params[0]; + Anope::string message = params[1]; + + User *u = source.GetUser(); + + if (ircdproto->IsChannelValid(receiver)) + { + Channel *c = findchan(receiver); + if (c) + { + FOREACH_MOD(I_OnPrivmsg, OnPrivmsg(u, c, message)); + } + } + else + { + /* 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 true; + } + else if (Config->UseStrictPrivMsg) + { + const BotInfo *bi = findbot(receiver); + if (!bi) + return true; + Log(LOG_DEBUG) << "Ignored PRIVMSG without @ from " << u->nick; + u->SendMessage(bi, _("\"/msg %s\" is no longer supported. Use \"/msg %s@%s\" or \"/%s\" instead."), receiver.c_str(), receiver.c_str(), Config->ServerName.c_str(), receiver.c_str()); + return true; + } + + BotInfo *bi = findbot(botname); + + if (bi) + { + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnBotPrivmsg, OnBotPrivmsg(u, bi, message)); + if (MOD_RESULT == EVENT_STOP) + return true; + + 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")) + { + Module *enc = ModuleManager::FindFirstOf(ENCRYPTION); + ircdproto->SendCTCP(bi, u->nick, "VERSION Anope-%s %s :%s - (%s) -- %s", Anope::Version().c_str(), Config->ServerName.c_str(), ircdproto->GetProtocolName().c_str(), enc ? enc->name.c_str() : "unknown", Anope::VersionBuildString().c_str()); + } + return true; + } + + bi->OnMessage(u, message); + } + } + + return true; +} + +bool CoreIRCDMessageQuit::Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override +{ + const Anope::string &reason = params[0]; + User *user = source.GetUser(); + + Log(user, "quit") << "quit (Reason: " << (!reason.empty() ? reason : "no reason") << ")"; + + NickAlias *na = findnick(user->nick); + if (na && !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 CoreIRCDMessageSQuit::Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override +{ + Server *s = Server::Find(params[0]); + + if (!s) + { + Log() << "SQUIT for nonexistent server " << params[0]; + return true; + } + + FOREACH_MOD(I_OnServerQuit, OnServerQuit(s)); + + s->Delete(s->GetName() + " " + s->GetUplink()->GetName()); + + return true; +} + +bool CoreIRCDMessageStats::Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override +{ + User *u = source.GetUser(); switch (params[0][0]) { case 'l': - if (u && u->HasMode(UMODE_OPER)) + if (u->HasMode(UMODE_OPER)) { - ircdproto->SendNumeric(211, source, "Server SendBuf SentBytes SentMsgs RecvBuf RecvBytes RecvMsgs ConnTime"); - ircdproto->SendNumeric(211, source, "%s %d %d %d %d %d %d %ld", Config->Uplinks[CurrentUplink]->host.c_str(), UplinkSock->WriteBufferLen(), TotalWritten, -1, UplinkSock->ReadBufferLen(), TotalRead, -1, static_cast<long>(Anope::CurTime - start_time)); + ircdproto->SendNumeric(211, source.GetSource(), "Server SendBuf SentBytes SentMsgs RecvBuf RecvBytes RecvMsgs ConnTime"); + ircdproto->SendNumeric(211, source.GetSource(), "%s %d %d %d %d %d %d %ld", Config->Uplinks[CurrentUplink]->host.c_str(), UplinkSock->WriteBufferLen(), TotalWritten, -1, UplinkSock->ReadBufferLen(), TotalRead, -1, static_cast<long>(Anope::CurTime - start_time)); } - ircdproto->SendNumeric(219, source, "%c :End of /STATS report.", params[0][0]); + ircdproto->SendNumeric(219, source.GetSource(), "%c :End of /STATS report.", params[0][0]); break; case 'o': case 'O': /* Check whether the user is an operator */ - if (u && !u->HasMode(UMODE_OPER) && Config->HideStatsO) - ircdproto->SendNumeric(219, source, "%c :End of /STATS report.", params[0][0]); + if (!u->HasMode(UMODE_OPER) && Config->HideStatsO) + ircdproto->SendNumeric(219, source.GetSource(), "%c :End of /STATS report.", params[0][0]); else { for (unsigned i = 0; i < Config->Opers.size(); ++i) @@ -49,127 +307,74 @@ bool OnStats(const Anope::string &source, const std::vector<Anope::string> ¶ const NickAlias *na = findnick(o->name); if (na) - ircdproto->SendNumeric(243, source, "O * * %s %s 0", o->name.c_str(), o->ot->GetName().c_str()); + ircdproto->SendNumeric(243, source.GetSource(), "O * * %s %s 0", o->name.c_str(), o->ot->GetName().c_str()); } - ircdproto->SendNumeric(219, source, "%c :End of /STATS report.", params[0][0]); + ircdproto->SendNumeric(219, source.GetSource(), "%c :End of /STATS report.", params[0][0]); } break; - case 'u': { time_t uptime = Anope::CurTime - start_time; - ircdproto->SendNumeric(242, source, ":Services up %d day%s, %02d:%02d:%02d", uptime / 86400, uptime / 86400 == 1 ? "" : "s", (uptime / 3600) % 24, (uptime / 60) % 60, uptime % 60); - ircdproto->SendNumeric(250, source, ":Current users: %d (%d ops); maximum %d", usercnt, opcnt, maxusercnt); - ircdproto->SendNumeric(219, source, "%c :End of /STATS report.", params[0][0]); + ircdproto->SendNumeric(242, source.GetSource(), ":Services up %d day%s, %02d:%02d:%02d", uptime / 86400, uptime / 86400 == 1 ? "" : "s", (uptime / 3600) % 24, (uptime / 60) % 60, uptime % 60); + ircdproto->SendNumeric(250, source.GetSource(), ":Current users: %d (%d ops); maximum %d", usercnt, opcnt, maxusercnt); + ircdproto->SendNumeric(219, source.GetSource(), "%c :End of /STATS report.", params[0][0]); break; } /* case 'u' */ default: - ircdproto->SendNumeric(219, source, "%c :End of /STATS report.", params[0][0]); + ircdproto->SendNumeric(219, source.GetSource(), "%c :End of /STATS report.", params[0][0]); } return true; } -bool OnTime(const Anope::string &source, const std::vector<Anope::string> &) +bool CoreIRCDMessageTime::Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - 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(391, source, "%s :%s", Config->ServerName.c_str(), buf); + ircdproto->SendNumeric(391, source.GetSource(), "%s :%s", Config->ServerName.c_str(), buf); + return true; +} + +bool CoreIRCDMessageTopic::Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override +{ + Channel *c = findchan(params[0]); + if (c) + c->ChangeTopicInternal(source.GetSource(), params[1], Anope::CurTime); + return true; } -bool OnVersion(const Anope::string &source, const std::vector<Anope::string> &) +bool CoreIRCDMessageVersion::Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { Module *enc = ModuleManager::FindFirstOf(ENCRYPTION); - ircdproto->SendNumeric(351, source, "Anope-%s %s :%s -(%s) -- %s", Anope::Version().c_str(), Config->ServerName.c_str(), ircd->name, enc ? enc->name.c_str() : "unknown", Anope::VersionBuildString().c_str()); + ircdproto->SendNumeric(351, source.GetSource(), "Anope-%s %s :%s -(%s) -- %s", Anope::Version().c_str(), Config->ServerName.c_str(), ircdproto->GetProtocolName().c_str(), enc ? enc->name.c_str() : "unknown", Anope::VersionBuildString().c_str()); return true; } -/* 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> &) +bool CoreIRCDMessageWhois::Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - if (source.empty()) - return true; + User *u = finduser(params[0]); - FILE *f = fopen(Config->MOTDFilename.c_str(), "r"); - if (f) + if (u && u->server == Me) { - ircdproto->SendNumeric(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(372, source, ":- %s", buf); - } - fclose(f); - ircdproto->SendNumeric(376, source, ":End of /MOTD command."); + const BotInfo *bi = findbot(u->nick); + ircdproto->SendNumeric(311, source.GetSource(), "%s %s %s * :%s", u->nick.c_str(), u->GetIdent().c_str(), u->host.c_str(), u->realname.c_str()); + if (bi) + ircdproto->SendNumeric(307, source.GetSource(), "%s :is a registered nick", bi->nick.c_str()); + ircdproto->SendNumeric(312, source.GetSource(), "%s %s :%s", u->nick.c_str(), Config->ServerName.c_str(), Config->ServerDesc.c_str()); + if (bi) + ircdproto->SendNumeric(317, source.GetSource(), "%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(318, source.GetSource(), "%s :End of /WHOIS list.", params[0].c_str()); } else - ircdproto->SendNumeric(422, source, ":- MOTD file not found! Please contact your IRC administrator."); + ircdproto->SendNumeric(401, source.GetSource(), "%s :No such user.", params[0].c_str()); 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", 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/modes.cpp b/src/modes.cpp index e466005f5..c14e09f70 100644 --- a/src/modes.cpp +++ b/src/modes.cpp @@ -384,7 +384,7 @@ std::list<Anope::string> ModeManager::BuildModeStrings(StackerInfo *info) for (it = info->AddModes.begin(), it_end = info->AddModes.end(); it != it_end; ++it) { - if (++NModes > ircd->maxmodes) + if (++NModes > ircdproto->MaxModes) { ret.push_back(buf + parambuf); buf = "+"; @@ -404,7 +404,7 @@ std::list<Anope::string> ModeManager::BuildModeStrings(StackerInfo *info) buf += "-"; for (it = info->DelModes.begin(), it_end = info->DelModes.end(); it != it_end; ++it) { - if (++NModes > ircd->maxmodes) + if (++NModes > ircdproto->MaxModes) { ret.push_back(buf + parambuf); buf = "-"; diff --git a/src/modules.cpp b/src/modules.cpp index e34c3597d..453a89a1a 100644 --- a/src/modules.cpp +++ b/src/modules.cpp @@ -13,7 +13,6 @@ #include "services.h" #include "modules.h" -message_map MessageMap; std::list<Module *> Modules; CallBack::CallBack(Module *mod, long time_from_now, time_t now, bool repeating) : Timer(time_from_now, now, repeating), m(mod) @@ -27,54 +26,3 @@ CallBack::~CallBack() m->CallBacks.erase(it); } -/** Message constructor, adds the message to Anope - * @param n The message name - * @param f A callback function - */ -Message::Message(const Anope::string &n, bool (*f)(const Anope::string &, const std::vector<Anope::string> &)) : name(n), func(f) -{ - MessageMap.insert(std::make_pair(this->name, this)); -} - -/** Message destructor - */ -Message::~Message() -{ - message_map::iterator it = MessageMap.find(this->name); - - if (it == MessageMap.end()) - return; - - message_map::iterator upper = MessageMap.upper_bound(this->name); - - for (; it != upper; ++it) - { - if (it->second == this) - { - MessageMap.erase(it); - break; - } - } -} - -/** Find a message in the message table - * @param name The name of the message were looking for - * @return NULL if we cant find it, or a pointer to the Message if we can - */ -std::vector<Message *> Anope::FindMessage(const Anope::string &name) -{ - std::vector<Message *> messages; - - message_map::iterator it = MessageMap.find(name); - - if (it == MessageMap.end()) - return messages; - - message_map::iterator upper = MessageMap.upper_bound(name); - - for (; it != upper; ++it) - messages.push_back(it->second); - - return messages; -} - diff --git a/src/nickalias.cpp b/src/nickalias.cpp index e9c8cce08..6db16c44c 100644 --- a/src/nickalias.cpp +++ b/src/nickalias.cpp @@ -92,7 +92,7 @@ void NickAlias::Release() { if (this->HasFlag(NS_HELD)) { - if (ircd->svshold) + if (ircdproto->CanSVSHold) ircdproto->SendSVSHoldDel(this->nick); else { @@ -147,11 +147,8 @@ class CoreExport NickServRelease : public User, public Timer * @param na The nick * @param delay The delay before the nick is released */ - NickServRelease(NickAlias *na, time_t delay) : User(na->nick, Config->NSEnforcerUser, Config->NSEnforcerHost, ts6_uid_retrieve()), Timer(delay), nick(na->nick) + NickServRelease(NickAlias *na, time_t delay) : User(na->nick, Config->NSEnforcerUser, Config->NSEnforcerHost, "", "", Me, "Services Enforcer", Anope::CurTime, "", ts6_uid_retrieve()), Timer(delay), nick(na->nick) { - this->realname = "Services Enforcer"; - this->server = Me; - /* Erase the current release timer and use the new one */ std::map<Anope::string, NickServRelease *>::iterator nit = NickServReleases.find(this->nick); if (nit != NickServReleases.end()) @@ -195,7 +192,7 @@ void NickAlias::OnCancel(User *) new NickServHeld(this, Config->NSReleaseTimeout); - if (ircd->svshold) + if (ircdproto->CanSVSHold) ircdproto->SendSVSHold(this->nick); else new NickServRelease(this, Config->NSReleaseTimeout); diff --git a/src/nickserv.cpp b/src/nickserv.cpp index a66738c03..65126b987 100644 --- a/src/nickserv.cpp +++ b/src/nickserv.cpp @@ -52,13 +52,10 @@ bool is_on_access(const User *u, const NickCore *nc) return false; Anope::string buf = u->GetIdent() + "@" + u->host, buf2, buf3; - if (ircd->vhost) - { - if (!u->vhost.empty()) - buf2 = u->GetIdent() + "@" + u->vhost; - if (!u->GetCloakedHost().empty()) - buf3 = u->GetIdent() + "@" + u->GetCloakedHost(); - } + if (!u->vhost.empty()) + buf2 = u->GetIdent() + "@" + u->vhost; + if (!u->GetCloakedHost().empty()) + buf3 = u->GetIdent() + "@" + u->GetCloakedHost(); for (unsigned i = 0, end = nc->access.size(); i < end; ++i) { diff --git a/src/process.cpp b/src/process.cpp index 6bfa3fec7..69017f63b 100644 --- a/src/process.cpp +++ b/src/process.cpp @@ -12,6 +12,9 @@ #include "services.h" #include "modules.h" #include "extern.h" +#include "protocol.h" +#include "servers.h" +#include "users.h" /** Main process routine * @param buffer A raw line from the uplink to do things with @@ -23,7 +26,8 @@ void process(const Anope::string &buffer) /* Strip all extra spaces */ Anope::string buf = buffer; - buf = buf.replace_all_cs(" ", " "); + while (buf.find(" ") != Anope::string::npos) + buf = buf.replace_all_cs(" ", " "); if (buf.empty()) return; @@ -74,18 +78,26 @@ void process(const Anope::string &buffer) Log() << "params " << i << ": " << params[i]; } - std::vector<Message *> messages = Anope::FindMessage(command); + const std::vector<IRCDMessage *> *messages = IRCDMessage::Find(command); - if (!messages.empty()) + if (messages && !messages->empty()) { - bool retVal = true; + MessageSource src(source); - for (std::vector<Message *>::iterator it = messages.begin(), it_end = messages.end(); retVal == true && it != it_end; ++it) + bool retVal = true; + /* Newer messages take priority */ + for (unsigned i = messages->size(); retVal && i > 0; --i) { - Message *m = *it; + IRCDMessage *m = messages->at(i - 1); - if (m->func) - retVal = m->func(source, params); + if (m->HasFlag(IRCDMESSAGE_SOFT_LIMIT) ? (params.size() < m->GetParamCount()) : (params.size() != m->GetParamCount())) + Log(LOG_DEBUG) << "invalid parameters for " << command << ": " << params.size() << " != " << m->GetParamCount(); + else if (m->HasFlag(IRCDMESSAGE_REQUIRE_USER) && !src.GetUser()) + Log(LOG_DEBUG) << "unexpected non-user source " << source << " for " << command; + else if (m->HasFlag(IRCDMESSAGE_REQUIRE_SERVER) && !source.empty() && !src.GetServer()) + Log(LOG_DEBUG) << "unexpected non-server soruce " << source << " for " << command; + else + retVal = m->Run(src, params); } } else diff --git a/src/protocol.cpp b/src/protocol.cpp index de55f4aec..e9ab88c77 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -21,27 +21,31 @@ #include "channels.h" IRCDProto *ircdproto; -IRCDVar *ircd; -IRCdMessage *ircdmessage; -void pmodule_ircd_proto(IRCDProto *proto) +IRCDProto::IRCDProto(const Anope::string &p) : proto_name(p) { - ircdproto = proto; + DefaultPseudoclientModes = "+io"; + CanSVSNick = CanSetVHost = CanSetVIdent = CanSNLine = CanSQLine = CanSQLineChannel = CanSZLine = CanSVSHold = + CanSVSO = CanCertFP = RequiresID = false; + MaxModes = 3; + + ircdproto = this; } -void pmodule_ircd_var(IRCDVar *ircdvar) +IRCDProto::~IRCDProto() { - ircd = ircdvar; + if (ircdproto == this) + ircdproto = NULL; } -void pmodule_ircd_message(IRCdMessage *message) +const Anope::string &IRCDProto::GetProtocolName() { - ircdmessage = message; + return this->proto_name; } -void IRCDProto::SendSVSKillInternal(const BotInfo *source, const User *user, const Anope::string &buf) +void IRCDProto::SendSVSKillInternal(const BotInfo *source, User *user, const Anope::string &buf) { - UplinkSocket::Message(source) << "KILL " << (ircd->ts6 ? user->GetUID() : user->nick) << " :" << buf; + UplinkSocket::Message(source) << "KILL " << user->GetUID() << " :" << buf; } void IRCDProto::SendModeInternal(const BotInfo *bi, const Channel *dest, const Anope::string &buf) @@ -52,9 +56,9 @@ void IRCDProto::SendModeInternal(const BotInfo *bi, const Channel *dest, const A void IRCDProto::SendKickInternal(const BotInfo *bi, const Channel *c, const User *u, const Anope::string &r) { if (!r.empty()) - UplinkSocket::Message(bi) << "KICK " << c->name << " " << (ircd->ts6 ? u->GetUID() : u->nick) << " :" << r; + UplinkSocket::Message(bi) << "KICK " << c->name << " " << u->GetUID() << " :" << r; else - UplinkSocket::Message(bi) << "KICK " << c->name << " " << (ircd->ts6 ? u->GetUID() : u->nick); + UplinkSocket::Message(bi) << "KICK " << c->name << " " << u->GetUID(); } void IRCDProto::SendMessageInternal(const BotInfo *bi, const Anope::string &dest, const Anope::string &buf) @@ -120,7 +124,7 @@ void IRCDProto::SendTopic(BotInfo *bi, Channel *c) UplinkSocket::Message(bi) << "TOPIC " << c->name << " :" << c->topic; } -void IRCDProto::SendSVSKill(const BotInfo *source, const User *user, const char *fmt, ...) +void IRCDProto::SendSVSKill(const BotInfo *source, User *user, const char *fmt, ...) { if (!user || !fmt) return; @@ -207,16 +211,6 @@ void IRCDProto::SendPrivmsg(const BotInfo *bi, const Anope::string &dest, const SendPrivmsgInternal(bi, dest, buf); } -void IRCDProto::SendGlobalNotice(const BotInfo *bi, const Server *dest, const Anope::string &msg) -{ - UplinkSocket::Message(bi) << "NOTICE " << ircd->globaltldprefix << dest->GetName() << " :" << msg; -} - -void IRCDProto::SendGlobalPrivmsg(const BotInfo *bi, const Server *dest, const Anope::string &msg) -{ - UplinkSocket::Message(bi) << "PRIVMSG " << ircd->globaltldprefix << dest->GetName() << " :" << msg; -} - void IRCDProto::SendQuit(const User *u, const char *fmt, ...) { va_list args; @@ -251,7 +245,7 @@ void IRCDProto::SendPong(const Anope::string &servname, const Anope::string &who void IRCDProto::SendInvite(const BotInfo *bi, const Channel *c, const User *u) { - UplinkSocket::Message(bi) << "INVITE " << (ircd->ts6 ? u->GetUID() : u->nick) << " " << c->name; + UplinkSocket::Message(bi) << "INVITE " << u->GetUID() << " " << c->name; } void IRCDProto::SendPart(const BotInfo *bi, const Channel *chan, const char *fmt, ...) @@ -322,258 +316,73 @@ bool IRCDProto::IsChannelValid(const Anope::string &chan) return true; } -bool IRCdMessage::On436(const Anope::string &, const std::vector<Anope::string> ¶ms) +MessageSource::MessageSource(const Anope::string &src) : source(src), u(NULL), s(NULL) { - if (!params.empty()) - introduce_user(params[0]); - return true; + if (src.empty()) + this->s = !Me->GetLinks().empty() ? Me->GetLinks().front() : NULL; + else if (ircdproto->RequiresID || src.find('.') != Anope::string::npos) + this->s = Server::Find(src); + if (this->s == NULL) + this->u = finduser(src); } -bool IRCdMessage::OnAway(const Anope::string &source, const std::vector<Anope::string> ¶ms) +MessageSource::MessageSource(User *_u) : source(_u->nick), u(_u), s(NULL) { - User *u = finduser(source); - if (u) - { - FOREACH_MOD(I_OnUserAway, OnUserAway(u, params.empty() ? "" : params[0])); - } - return true; } -bool IRCdMessage::OnJoin(const Anope::string &source, const std::vector<Anope::string> ¶ms) +MessageSource::MessageSource(Server *_s) : source(_s->GetName()), u(NULL), s(_s) { - 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) +const Anope::string MessageSource::GetName() { - 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 (u->server == Me && (bi = dynamic_cast<BotInfo *>(u))) - { - bi->introduced = false; - introduce_user(bi->nick); - bi->RejoinAll(); - } + if (this->s) + return this->s->GetName(); + else if (this->u) + return this->u->nick; else - do_kill(u, params[1]); - - - return true; + return this->source; } -bool IRCdMessage::OnUID(const Anope::string &source, const std::vector<Anope::string> ¶ms) +const Anope::string &MessageSource::GetSource() { - return true; + return this->source; } -bool IRCdMessage::OnPart(const Anope::string &source, const std::vector<Anope::string> ¶ms) +User *MessageSource::GetUser() { - if (!params.empty()) - do_part(source, params[0], params.size() > 1 ? params[1] : ""); - return true; + return this->u; } -bool IRCdMessage::OnPing(const Anope::string &, const std::vector<Anope::string> ¶ms) +Server *MessageSource::GetServer() { - if (!params.empty()) - ircdproto->SendPong(params.size() > 1 ? params[1] : Config->ServerName, params[0]); - return true; + return this->s; } -bool IRCdMessage::OnPrivmsg(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - const Anope::string &receiver = params.size() > 0 ? params[0] : ""; - 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); +std::map<Anope::string, std::vector<IRCDMessage *> > IRCDMessage::messages; - if (!u) - { - Log() << message << ": user record for " << source << " not found"; - - const BotInfo *bi = findbot(receiver); - if (bi) - ircdproto->SendMessage(bi, source, "%s", "Internal error - unable to process request."); - - return true; - } - - if (receiver[0] == '#') - { - Channel *c = findchan(receiver); - if (c) - { - FOREACH_MOD(I_OnPrivmsg, OnPrivmsg(u, c, message)); - } - } - else - { - /* 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 true; - } - else if (Config->UseStrictPrivMsg) - { - const BotInfo *bi = findbot(receiver); - if (!bi) - return true; - Log(LOG_DEBUG) << "Ignored PRIVMSG without @ from " << source; - u->SendMessage(bi, _("\"/msg %s\" is no longer supported. Use \"/msg %s@%s\" or \"/%s\" instead."), receiver.c_str(), receiver.c_str(), Config->ServerName.c_str(), receiver.c_str()); - return true; - } - - BotInfo *bi = findbot(botname); - - if (bi) - { - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnBotPrivmsg, OnBotPrivmsg(u, bi, message)); - if (MOD_RESULT == EVENT_STOP) - return true; - - 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")) - { - Module *enc = ModuleManager::FindFirstOf(ENCRYPTION); - ircdproto->SendCTCP(bi, u->nick, "VERSION Anope-%s %s :%s - (%s) -- %s", Anope::Version().c_str(), Config->ServerName.c_str(), ircd->name, enc ? enc->name.c_str() : "unknown", Anope::VersionBuildString().c_str()); - } - return true; - } - - bi->OnMessage(u, message); - } - } - - 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->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 std::vector<IRCDMessage *> *IRCDMessage::Find(const Anope::string &name) { - const Anope::string &server = params[0]; - - Server *s = Server::Find(server); - - if (!s) - { - Log() << "SQUIT for nonexistent server " << server; - return true; - } - - FOREACH_MOD(I_OnServerQuit, OnServerQuit(s)); - - Anope::string buf = s->GetName() + " " + s->GetUplink()->GetName(); - - if (s->GetUplink() == Me && Capab.count("UNCONNECT") > 0) - { - Log(LOG_DEBUG) << "Sending UNCONNECT SQUIT for " << s->GetName(); - /* need to fix */ - ircdproto->SendSquit(s, buf); - } - - s->Delete(buf); - - return true; + std::map<Anope::string, std::vector<IRCDMessage *> >::iterator it = messages.find(name); + if (it != messages.end()) + return &it->second; + return NULL; } -bool IRCdMessage::OnWhois(const Anope::string &source, const std::vector<Anope::string> ¶ms) +IRCDMessage::IRCDMessage(const Anope::string &n, unsigned p) : name(n), param_count(p) { - if (!source.empty() && !params.empty()) - { - User *u = finduser(params[0]); - if (u && u->server == Me) - { - const BotInfo *bi = findbot(u->nick); - ircdproto->SendNumeric(311, source, "%s %s %s * :%s", u->nick.c_str(), u->GetIdent().c_str(), u->host.c_str(), u->realname.c_str()); - if (bi) - ircdproto->SendNumeric(307, source, "%s :is a registered nick", bi->nick.c_str()); - ircdproto->SendNumeric(312, source, "%s %s :%s", u->nick.c_str(), Config->ServerName.c_str(), Config->ServerDesc.c_str()); - if (bi) - ircdproto->SendNumeric(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(318, source, "%s :End of /WHOIS list.", params[0].c_str()); - } - else - ircdproto->SendNumeric(401, source, "%s :No such user.", params[0].c_str()); - } - - return true; + messages[n].insert(messages[n].begin(), this); } -bool IRCdMessage::OnCapab(const Anope::string &, const std::vector<Anope::string> ¶ms) +IRCDMessage::~IRCDMessage() { - for (unsigned i = 0; i < params.size(); ++i) - Capab.insert(params[i]); - return true; + std::vector<IRCDMessage *>::iterator it = std::find(messages[this->name].begin(), messages[this->name].end(), this); + if (it != messages[this->name].end()) + messages[this->name].erase(it); } -bool IRCdMessage::OnError(const Anope::string &, const std::vector<Anope::string> ¶ms) +unsigned IRCDMessage::GetParamCount() const { - if (!params.empty()) - { - Log(LOG_TERMINAL) << "ERROR: " << params[0]; - quitmsg = "Received ERROR from uplink: " + params[0]; - } - - return true; + return this->param_count; } diff --git a/src/servers.cpp b/src/servers.cpp index 650625cdb..d89757996 100644 --- a/src/servers.cpp +++ b/src/servers.cpp @@ -52,7 +52,8 @@ Server::Server(Server *uplink, const Anope::string &name, unsigned hops, const A for (botinfo_map::iterator it = BotListByNick->begin(), it_end = BotListByNick->end(); it != it_end; ++it) { BotInfo *bi = it->second; - Anope::string modes = !bi->botmodes.empty() ? ("+" + bi->botmodes) : ircd->pseudoclient_mode; + Anope::string modes = !bi->botmodes.empty() ? ("+" + bi->botmodes) : ircdproto->DefaultPseudoclientModes; + bi->SetModesInternal(modes.c_str()); for (unsigned i = 0; i < bi->botchannels.size(); ++i) { @@ -70,7 +71,10 @@ Server::Server(Server *uplink, const Anope::string &name, unsigned hops, const A if (cm == NULL) cm = ModeManager::FindChannelModeByChar(ModeManager::GetStatusChar(want_modes[j])); if (cm && cm->Type == MODE_STATUS) - c->SetModeInternal(bi, cm, bi->nick); + { + MessageSource ms = bi; + c->SetModeInternal(ms, cm, bi->nick); + } } } } @@ -113,6 +117,8 @@ Server::Server(Server *uplink, const Anope::string &name, unsigned hops, const A } } } + + FOREACH_MOD(I_OnNewServer, OnNewServer(this)); } /** Destructor @@ -157,6 +163,7 @@ Server::~Server() void Server::Delete(const Anope::string &reason) { this->QReason = reason; + FOREACH_MOD(I_OnServerQuit, OnServerQuit(this)); delete this; } @@ -205,7 +212,10 @@ void Server::SetSID(const Anope::string &sid) */ const Anope::string &Server::GetSID() const { - return this->SID; + if (!this->SID.empty()) + return this->SID; + else + return this->Name; } /** Get the list of links this server has, or NULL if it has none @@ -395,42 +405,7 @@ Server *Server::Find(const Anope::string &name, Server *s) /*************************************************************************/ -/** - * Handle adding the server to the Server struct - * @param source Name of the uplink if any - * @param servername Name of the server being linked - * @param hops Number of hops to reach this server - * @param descript Description of the server - * @param numeric Server Numberic/SUID - * @return void - */ -void do_server(const Anope::string &source, const Anope::string &servername, unsigned int hops, const Anope::string &descript, const Anope::string &numeric) -{ - if (source.empty()) - Log(LOG_DEBUG) << "Server " << servername << " introduced"; - else - Log(LOG_DEBUG) << "Server introduced (" << servername << ")" << " from " << source; - - Server *s = NULL; - - if (!source.empty()) - { - s = Server::Find(source); - - if (!s) - throw CoreException("Recieved a server from a nonexistant uplink?"); - } - else - s = Me; - - /* Create a server structure. */ - Server *newserver = new Server(s, servername, hops, descript, numeric); - - /* Let modules know about the connection */ - FOREACH_MOD(I_OnNewServer, OnNewServer(newserver)); -} - -static inline char nextID(char &c) +static inline char& nextID(char &c) { if (c == 'Z') c = '0'; @@ -446,7 +421,7 @@ static inline char nextID(char &c) */ const Anope::string ts6_uid_retrieve() { - if (!ircd || !ircd->ts6) + if (!ircdproto || !ircdproto->RequiresID) return ""; static Anope::string current_uid = "AAAAAA"; @@ -465,7 +440,7 @@ const Anope::string ts6_uid_retrieve() */ const Anope::string ts6_sid_retrieve() { - if (!ircd || !ircd->ts6) + if (!ircdproto || !ircdproto->RequiresID) return ""; static Anope::string current_sid; diff --git a/src/users.cpp b/src/users.cpp index 338dc343f..a992d8d04 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -32,13 +32,11 @@ time_t maxusertime; /*************************************************************************/ /*************************************************************************/ -User::User(const Anope::string &snick, const Anope::string &sident, const Anope::string &shost, const Anope::string &suid) : modes(UserModeNameStrings) +User::User(const Anope::string &snick, const Anope::string &sident, const Anope::string &shost, const Anope::string &svhost, const Anope::string &sip, Server *sserver, const Anope::string &srealname, time_t ssignon, const Anope::string &smodes, const Anope::string &suid) { if (snick.empty() || sident.empty() || shost.empty()) throw CoreException("Bad args passed to User::User"); - // XXX: we should also duplicate-check here. - /* we used to do this by calloc, no more. */ server = NULL; invalid_pw_count = invalid_pw_time = lastmemosend = lastnickreg = lastmail = 0; @@ -48,41 +46,86 @@ User::User(const Anope::string &snick, const Anope::string &sident, const Anope: this->nick = snick; this->ident = sident; this->host = shost; + this->vhost = svhost; + if (!svhost.empty()) + this->SetCloakedHost(svhost); + this->ip = sip; + this->server = sserver; + this->realname = srealname; + this->timestamp = ssignon; + this->SetModesInternal("%s", smodes.c_str()); this->uid = suid; this->SuperAdmin = false; + size_t old = UserListByNick.size(); UserListByNick[snick] = this; if (!suid.empty()) UserListByUID[suid] = this; + if (old == UserListByNick.size()) + Log(LOG_DEBUG) << "Duplicate user " << snick << " in user table?"; this->nc = NULL; - ++usercnt; + if (sserver) // Our bots are introduced on startup with no server + Log(this, "connect") << (!svhost.empty() ? Anope::string("(") + svhost + ") " : "") << "(" << srealname << ") " << sip << " connected to the network (" << sserver->GetName() << ")"; + ++usercnt; if (usercnt > maxusercnt) { maxusercnt = usercnt; maxusertime = Anope::CurTime; Log(this, "maxusers") << "connected - new maximum user count: " << maxusercnt; } + + bool exempt = false; + if (server && server->IsULined()) + exempt = true; + dynamic_reference<User> user = this; + FOREACH_MOD(I_OnUserConnect, OnUserConnect(user, exempt)); } -void User::SetNewNick(const Anope::string &newnick) +void User::ChangeNick(const Anope::string &newnick) { /* Sanity check to make sure we don't segfault */ if (newnick.empty()) - throw CoreException("User::SetNewNick() got a bad argument"); - - UserListByNick.erase(this->nick); + throw CoreException("User::ChangeNick() got a bad argument"); + + this->SuperAdmin = false; + Log(this, "nick") << "(" << this->realname << ") changed nick to " << newnick; - this->nick = newnick; + Anope::string old = this->nick; - UserListByNick[this->nick] = this; + if (this->nick.equals_ci(newnick)) + this->nick = newnick; + else + { + /* Update this only if nicks aren't the same */ + this->my_signon = Anope::CurTime; + + NickAlias *old_na = findnick(this->nick); + if (old_na && (this->IsIdentified(true) || this->IsRecognized())) + old_na->last_seen = Anope::CurTime; + + UserListByNick.erase(this->nick); + this->nick = newnick; + UserListByNick[this->nick] = this; + + OnAccess = false; + NickAlias *na = findnick(this->nick); + if (na) + OnAccess = is_on_access(this, na->nc); + + if (old_na) + old_na->OnCancel(this); + + if (na && na->nc == this->Account()) + { + na->last_seen = Anope::CurTime; + this->UpdateHost(); + } + } - OnAccess = false; - const NickAlias *na = findnick(this->nick); - if (na) - OnAccess = is_on_access(this, na->nc); + FOREACH_MOD(I_OnUserNickChange, OnUserNickChange(this, old)); } void User::SetDisplayedHost(const Anope::string &shost) @@ -102,7 +145,7 @@ void User::SetDisplayedHost(const Anope::string &shost) */ const Anope::string &User::GetDisplayedHost() const { - if (ircd->vhost && !this->vhost.empty()) + if (!this->vhost.empty()) return this->vhost; else if (this->HasMode(UMODE_CLOAK) && !this->GetCloakedHost().empty()) return this->GetCloakedHost(); @@ -135,7 +178,10 @@ const Anope::string &User::GetCloakedHost() const const Anope::string &User::GetUID() const { - return this->uid; + if (!this->uid.empty()) + return this->uid; + else + return this->nick; } void User::SetVIdent(const Anope::string &sident) @@ -149,7 +195,7 @@ void User::SetVIdent(const Anope::string &sident) const Anope::string &User::GetVIdent() const { - if (this->HasMode(UMODE_CLOAK) || (ircd->vident && !this->vident.empty())) + if (!this->vident.empty()) return this->vident; else return this->ident; @@ -323,7 +369,7 @@ void User::Collide(NickAlias *na) if (na) na->SetFlag(NS_COLLIDED); - if (ircd->svsnick) + if (ircdproto->CanSVSNick) { Anope::string guestnick; @@ -386,7 +432,7 @@ void User::Identify(NickAlias *na) if (bi != NULL) this->SendMessage(bi, "Changing your usermodes to \002%s\002", this->nc->o->ot->modes.c_str()); } - if (ircd->vhost && !this->nc->o->vhost.empty()) + if (ircdproto->CanSetVHost && !this->nc->o->vhost.empty()) { if (bi != NULL) this->SendMessage(bi, "Changing your vhost to \002%s\002", this->nc->o->vhost.c_str()); @@ -687,6 +733,8 @@ void User::SetModesInternal(const char *umodes, ...) vsnprintf(buf, BUFSIZE - 1, umodes, args); va_end(args); + Log(this, "mode") << "changes modes to " << buf; + spacesepstream sep(buf); sep.GetToken(modebuf); for (unsigned i = 0, end = modebuf.length(); i < end; ++i) @@ -785,14 +833,25 @@ void User::Kill(const Anope::string &source, const Anope::string &reason) Anope::string real_reason = real_source + " (" + reason + ")"; ircdproto->SendSVSKill(findbot(source), this, "%s", real_reason.c_str()); +} + +void User::KillInternal(const Anope::string &source, const Anope::string &reason) +{ + Log(this, "killed") << "was killed by " << source << " (Reason: " << reason << ")"; + + NickAlias *na = findnick(this->nick); + if (na && !na->nc->HasFlag(NI_SUSPENDED) && (this->IsRecognized() || this->IsIdentified(true))) + { + na->last_seen = Anope::CurTime; + na->last_quit = reason; + } - if (!ircd->quitonkill) - do_kill(this, real_reason); + delete this; } User *finduser(const Anope::string &nick) { - if (isdigit(nick[0]) && ircd->ts6) + if (isdigit(nick[0]) && ircdproto->RequiresID) { Anope::map<User *>::iterator it = UserListByUID.find(nick); if (it != UserListByUID.end()) @@ -808,127 +867,6 @@ User *finduser(const Anope::string &nick) return NULL; } -/*************************************************************************/ - -/* Handle a server NICK command. */ - -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) -{ - if (source.empty()) - { - Server *serv = Server::Find(server); - if (serv == NULL) - { - Log() << "User " << nick << " introduced with nonexistant server " << server << "!"; - return NULL; - } - - /* Allocate User structure and fill it in. */ - dynamic_reference<User> user = new User(nick, username, host, uid); - user->ip = ip; - user->server = serv; - user->realname = realname; - user->timestamp = ts; - if (!vhost.empty()) - user->SetCloakedHost(vhost); - user->SetVIdent(username); - user->SetModesInternal(modes.c_str()); - - Log(user, "connect") << (!vhost.empty() ? Anope::string("(") + vhost + ") " : "") << "(" << user->realname << ") " << user->ip << " connected to the network (" << serv->GetName() << ")"; - - bool exempt = false; - if (user->server && user->server->IsULined()) - exempt = true; - FOREACH_MOD(I_OnUserConnect, OnUserConnect(user, exempt)); - - return user; - } - else - { - /* An old user changing nicks. */ - User *user = finduser(source); - - if (!user) - { - Log() << "user: NICK from nonexistent nick " << source; - return NULL; - } - user->SuperAdmin = false; - - Log(user, "nick") << "(" << user->realname << ") changed nick to " << nick; - - user->timestamp = ts; - - if (user->nick.equals_ci(nick)) - /* No need to redo things */ - user->SetNewNick(nick); - else - { - /* Update this only if nicks aren't the same */ - user->my_signon = Anope::CurTime; - - NickAlias *old_na = findnick(user->nick); - if (old_na && (old_na->nc == user->Account() || user->IsRecognized())) - old_na->last_seen = Anope::CurTime; - - Anope::string oldnick = user->nick; - user->SetNewNick(nick); - FOREACH_MOD(I_OnUserNickChange, OnUserNickChange(user, oldnick)); - - if (old_na) - old_na->OnCancel(user); - - NickAlias *na = findnick(user->nick); - if (na && na->nc == user->Account()) - { - na->last_seen = Anope::CurTime; - user->UpdateHost(); - } - } - - return user; - } -} - -/*************************************************************************/ - -void do_umode(const Anope::string &user, const Anope::string &modes) -{ - User *u = finduser(user); - if (!u) - { - Log() << "user: MODE "<< modes << " for nonexistent nick "<< user; - return; - } - - Log(u, "mode") << "changes modes to " << modes; - - u->SetModesInternal(modes.c_str()); -} - -/*************************************************************************/ - - -/* Handle a KILL command. - * @param user the user being killed - * @param msg why - */ -void do_kill(User *user, const Anope::string &msg) -{ - Log(user, "killed") << "was killed (Reason: " << msg << ")"; - - NickAlias *na = findnick(user->nick); - if (na && !na->nc->HasFlag(NI_SUSPENDED) && (user->IsRecognized() || user->IsIdentified(true))) - { - na->last_seen = Anope::CurTime; - na->last_quit = msg; - } - delete user; -} - -/*************************************************************************/ -/*************************************************************************/ - bool matches_list(Channel *c, User *user, ChannelModeName mode) { if (!c || !c->HasMode(mode)) |