summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/conf/inspircd.conf.example5
-rw-r--r--docs/conf/modules.conf.example5
-rw-r--r--include/configreader.h5
-rw-r--r--include/users.h16
-rw-r--r--src/configreader.cpp4
-rw-r--r--src/modules/m_hostcycle.cpp114
-rw-r--r--src/users.cpp77
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;
}