Move host cycle logic into m_hostcycle

This commit is contained in:
attilamolnar 2013-08-09 18:10:48 +02:00
parent 9962840222
commit e4b76e6502
7 changed files with 125 additions and 101 deletions

View File

@ -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.

View File

@ -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">

View File

@ -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
*/

View File

@ -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
*/

View File

@ -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");

114
src/modules/m_hostcycle.cpp Normal file
View File

@ -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)

View File

@ -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;
}