diff options
-rw-r--r-- | docs/conf/inspircd.conf.example | 5 | ||||
-rw-r--r-- | docs/conf/modules.conf.example | 5 | ||||
-rw-r--r-- | include/configreader.h | 5 | ||||
-rw-r--r-- | include/users.h | 16 | ||||
-rw-r--r-- | src/configreader.cpp | 4 | ||||
-rw-r--r-- | src/modules/m_hostcycle.cpp | 114 | ||||
-rw-r--r-- | src/users.cpp | 77 |
7 files changed, 125 insertions, 101 deletions
diff --git a/docs/conf/inspircd.conf.example b/docs/conf/inspircd.conf.example index 7531117b9..2c75ddc7c 100644 --- a/docs/conf/inspircd.conf.example +++ b/docs/conf/inspircd.conf.example @@ -578,11 +578,6 @@ # the correct parameters are. syntaxhints="no" - # cyclehosts: If enabled, when a user gets a host set, it will cycle - # them in all their channels. If not, it will simply change their host - # without cycling them. - cyclehosts="no" - # cyclehostsfromuser: If enabled, the source of the mode change for # cyclehosts will be the user who cycled. This can look nicer, but # triggers anti-takeover mechanisms of some obsolete bots. diff --git a/docs/conf/modules.conf.example b/docs/conf/modules.conf.example index 10e1689b3..7e1a9f5ad 100644 --- a/docs/conf/modules.conf.example +++ b/docs/conf/modules.conf.example @@ -816,6 +816,11 @@ #<hostchange mask="a@b.com" action="set" value="blah.blah.blah"> #<hostchange mask="localhost" ports="7000,7001,7005-7007" action="set" value="blahblah.foo"> +# hostcycle: If loaded, when a user gets a host or ident set, it will +# cycle them in all their channels. If not loaded it will simply change +# their host/ident without cycling them. +#<module name="m_hostcycle.so"> + #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-# # httpd module: Provides http server support for InspIRCd #<module name="m_httpd.so"> diff --git a/include/configreader.h b/include/configreader.h index 51ced2ec7..33456d84b 100644 --- a/include/configreader.h +++ b/include/configreader.h @@ -450,11 +450,6 @@ class CoreExport ServerConfig */ bool SyntaxHints; - /** If set to true, users appear to quit then rejoin when their hosts change. - * This keeps clients synchronized properly. - */ - bool CycleHosts; - /** If set to true, the CycleHosts mode change will be sourced from the user, * rather than the server */ diff --git a/include/users.h b/include/users.h index 503357348..478476cdd 100644 --- a/include/users.h +++ b/include/users.h @@ -585,28 +585,20 @@ class CoreExport User : public Extensible */ bool SharesChannelWith(User *other); - /** Send fake quit/join messages for host or ident cycle. - * Run this after the item in question has changed. - * You should not need to use this function, call ChangeDisplayedHost instead - * - * @param quitline The entire QUIT line, including the source using the old value - */ - void DoHostCycle(const std::string &quitline); - /** Change the displayed host of a user. * ALWAYS use this function, rather than writing User::dhost directly, * as this triggers module events allowing the change to be syncronized to - * remote servers. This will also emulate a QUIT and rejoin (where configured) - * before setting their host field. + * remote servers. * @param host The new hostname to set * @return True if the change succeeded, false if it didn't + * (a module vetoed the change). */ bool ChangeDisplayedHost(const char* host); /** Change the ident (username) of a user. * ALWAYS use this function, rather than writing User::ident directly, - * as this correctly causes the user to seem to quit (where configured) - * before setting their ident field. + * as this triggers module events allowing the change to be syncronized to + * remote servers. * @param newident The new ident to set * @return True if the change succeeded, false if it didn't */ diff --git a/src/configreader.cpp b/src/configreader.cpp index d2291556c..047a2b5cd 100644 --- a/src/configreader.cpp +++ b/src/configreader.cpp @@ -32,7 +32,7 @@ ServerConfig::ServerConfig() { RawLog = HideBans = HideSplits = UndernetMsgPrefix = false; - WildcardIPv6 = CycleHosts = InvBypassModes = true; + WildcardIPv6 = InvBypassModes = true; dns_timeout = 5; MaxTargets = 20; NetBufferSize = 10240; @@ -349,6 +349,7 @@ static const DeprecatedConfig ChangedConfig[] = { { "link", "transport", "", "has been moved to <link:ssl> as of 2.0" }, { "module", "name", "m_chanprotect.so", "has been replaced with m_customprefix as of 2.2" }, { "module", "name", "m_halfop.so", "has been replaced with m_customprefix as of 2.2" }, + { "options", "cyclehosts", "", "has been replaced with m_hostcycle as of 2.2" }, { "performance", "nouserdns", "", "has been moved to <connect:nouserdns> as of 2.2" } }; @@ -405,7 +406,6 @@ void ServerConfig::Fill() RestrictBannedUsers = security->getBool("restrictbannedusers", true); GenericOper = security->getBool("genericoper"); SyntaxHints = options->getBool("syntaxhints"); - CycleHosts = options->getBool("cyclehosts"); CycleHostsFromUser = options->getBool("cyclehostsfromuser"); UndernetMsgPrefix = options->getBool("ircumsgprefix"); FullHostInTopic = options->getBool("hostintopic"); diff --git a/src/modules/m_hostcycle.cpp b/src/modules/m_hostcycle.cpp new file mode 100644 index 000000000..79b4169ec --- /dev/null +++ b/src/modules/m_hostcycle.cpp @@ -0,0 +1,114 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2013 Attila Molnar <attilamolnar@hush.com> + * Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org> + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "inspircd.h" + +class ModuleHostCycle : public Module +{ + /** Send fake quit/join/mode messages for host or ident cycle. + */ + static void DoHostCycle(User* user, const std::string& newident, const std::string& newhost, const char* quitmsg) + { + // GetFullHost() returns the original data at the time this function is called + const std::string quitline = ":" + user->GetFullHost() + " QUIT :" + quitmsg; + + already_sent_t silent_id = ++LocalUser::already_sent_id; + already_sent_t seen_id = ++LocalUser::already_sent_id; + + UserChanList include_chans(user->chans); + std::map<User*,bool> exceptions; + + FOREACH_MOD(OnBuildNeighborList, (user, include_chans, exceptions)); + + for (std::map<User*,bool>::iterator i = exceptions.begin(); i != exceptions.end(); ++i) + { + LocalUser* u = IS_LOCAL(i->first); + if (u && !u->quitting) + { + if (i->second) + { + u->already_sent = seen_id; + u->Write(quitline); + } + else + { + u->already_sent = silent_id; + } + } + } + + std::string newfullhost = user->nick + "!" + newident + "@" + newhost; + + for (UCListIter i = include_chans.begin(); i != include_chans.end(); ++i) + { + Channel* c = *i; + Membership* memb = c->GetUser(user); + const std::string joinline = ":" + newfullhost + " JOIN " + c->name; + std::string modeline; + + if (!memb->modes.empty()) + { + modeline = ":" + (ServerInstance->Config->CycleHostsFromUser ? newfullhost : ServerInstance->Config->ServerName) + + " MODE " + c->name + " +" + memb->modes; + + for (size_t j = 0; j < memb->modes.length(); j++) + modeline.append(" ").append(user->nick); + } + + const UserMembList* ulist = c->GetUsers(); + for (UserMembList::const_iterator j = ulist->begin(); j != ulist->end(); ++j) + { + LocalUser* u = IS_LOCAL(j->first); + if (u == NULL || u == user) + continue; + if (u->already_sent == silent_id) + continue; + + if (u->already_sent != seen_id) + { + u->Write(quitline); + u->already_sent = seen_id; + } + + u->Write(joinline); + if (!memb->modes.empty()) + u->Write(modeline); + } + } + } + + public: + void OnChangeIdent(User* user, const std::string& newident) CXX11_OVERRIDE + { + DoHostCycle(user, newident, user->dhost, "Changing ident"); + } + + void OnChangeHost(User* user, const std::string& newhost) CXX11_OVERRIDE + { + DoHostCycle(user, user->ident, newhost, "Changing host"); + } + + Version GetVersion() CXX11_OVERRIDE + { + return Version("Cycles users in all their channels when their host or ident changes", VF_VENDOR); + } +}; + +MODULE_INIT(ModuleHostCycle) diff --git a/src/users.cpp b/src/users.cpp index 371fa3bb6..bb7588fb2 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -1124,72 +1124,6 @@ bool User::ChangeName(const char* gecos) return true; } -void User::DoHostCycle(const std::string &quitline) -{ - if (!ServerInstance->Config->CycleHosts) - return; - - already_sent_t silent_id = ++LocalUser::already_sent_id; - already_sent_t seen_id = ++LocalUser::already_sent_id; - - UserChanList include_c(chans); - std::map<User*,bool> exceptions; - - FOREACH_MOD(OnBuildNeighborList, (this, include_c, exceptions)); - - for (std::map<User*,bool>::iterator i = exceptions.begin(); i != exceptions.end(); ++i) - { - LocalUser* u = IS_LOCAL(i->first); - if (u && !u->quitting) - { - if (i->second) - { - u->already_sent = seen_id; - u->Write(quitline); - } - else - { - u->already_sent = silent_id; - } - } - } - for (UCListIter v = include_c.begin(); v != include_c.end(); ++v) - { - Channel* c = *v; - Membership* memb = c->GetUser(this); - const std::string joinline = ":" + GetFullHost() + " JOIN " + c->name; - std::string modeline; - - if (!memb->modes.empty()) - { - modeline = ":" + (ServerInstance->Config->CycleHostsFromUser ? GetFullHost() : ServerInstance->Config->ServerName) - + " MODE " + c->name + " +" + memb->modes; - - for (size_t i = 0; i < memb->modes.length(); i++) - modeline.append(" ").append(nick); - } - - const UserMembList *ulist = c->GetUsers(); - for (UserMembList::const_iterator i = ulist->begin(); i != ulist->end(); i++) - { - LocalUser* u = IS_LOCAL(i->first); - if (u == NULL || u == this) - continue; - if (u->already_sent == silent_id) - continue; - - if (u->already_sent != seen_id) - { - u->Write(quitline); - u->already_sent = seen_id; - } - u->Write(joinline); - if (!memb->modes.empty()) - u->Write(modeline); - } - } -} - bool User::ChangeDisplayedHost(const char* shost) { if (dhost == shost) @@ -1205,15 +1139,9 @@ bool User::ChangeDisplayedHost(const char* shost) FOREACH_MOD(OnChangeHost, (this,shost)); - std::string quitstr = ":" + GetFullHost() + " QUIT :Changing host"; - - /* Fix by Om: User::dhost is 65 long, this was truncating some long hosts */ this->dhost.assign(shost, 0, 64); - this->InvalidateCache(); - this->DoHostCycle(quitstr); - if (IS_LOCAL(this)) this->WriteNumeric(RPL_YOURDISPLAYEDHOST, "%s %s :is now your displayed host",this->nick.c_str(),this->dhost.c_str()); @@ -1227,14 +1155,9 @@ bool User::ChangeIdent(const char* newident) FOREACH_MOD(OnChangeIdent, (this,newident)); - std::string quitstr = ":" + GetFullHost() + " QUIT :Changing ident"; - this->ident.assign(newident, 0, ServerInstance->Config->Limits.IdentMax); - this->InvalidateCache(); - this->DoHostCycle(quitstr); - return true; } |