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 /src | |
parent | b937d6310d9a7c0e2434200306b63d513cb2ae61 (diff) |
Cleanup of all of the protocol modules, rewrote message handling system to be a bit more C++ ish
Diffstat (limited to 'src')
-rw-r--r-- | src/bots.cpp | 7 | ||||
-rw-r--r-- | src/botserv.cpp | 2 | ||||
-rw-r--r-- | src/channels.cpp | 249 | ||||
-rw-r--r-- | src/init.cpp | 2 | ||||
-rw-r--r-- | src/main.cpp | 10 | ||||
-rw-r--r-- | src/messages.cpp | 393 | ||||
-rw-r--r-- | src/modes.cpp | 4 | ||||
-rw-r--r-- | src/modules.cpp | 52 | ||||
-rw-r--r-- | src/nickalias.cpp | 9 | ||||
-rw-r--r-- | src/nickserv.cpp | 11 | ||||
-rw-r--r-- | src/process.cpp | 28 | ||||
-rw-r--r-- | src/protocol.cpp | 297 | ||||
-rw-r--r-- | src/servers.cpp | 57 | ||||
-rw-r--r-- | src/users.cpp | 224 |
14 files changed, 537 insertions, 808 deletions
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)) |