summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/inspircd.conf.example8
-rw-r--r--include/configreader.h8
-rw-r--r--include/mode.h10
-rw-r--r--src/configreader.cpp3
-rw-r--r--src/mode.cpp25
-rw-r--r--src/modes/cmode_h.cpp2
-rw-r--r--src/modes/cmode_o.cpp2
-rw-r--r--src/modes/cmode_v.cpp3
-rw-r--r--src/users.cpp16
9 files changed, 70 insertions, 7 deletions
diff --git a/docs/inspircd.conf.example b/docs/inspircd.conf.example
index 3cd1536e5..b7dcec7ad 100644
--- a/docs/inspircd.conf.example
+++ b/docs/inspircd.conf.example
@@ -522,6 +522,13 @@
# used in unreal. This is only useful on networks #
# running the m_chanprotect module #
# #
+# cyclehosts - If this is set to true, yes or 1, then when a #
+# user's hostname changes, they will appear to quit #
+# and then rejoin with their new host. This prevents #
+# clients from being confused by host changes, #
+# especially in the case of bots, and it is #
+# recommended that this option is enabled. #
+# #
# netbuffersize - size of the buffer used to receive data from #
# clients. The ircd may only read() this amount #
# of text in one go at any time. (OPTIONAL) #
@@ -638,6 +645,7 @@
hideulines="no"
nouserdns="no"
syntaxhints="no"
+ cyclehosts="yes"
allowhalfop="yes">
diff --git a/include/configreader.h b/include/configreader.h
index 467b5bde3..5c8a66307 100644
--- a/include/configreader.h
+++ b/include/configreader.h
@@ -361,10 +361,14 @@ class ServerConfig : public Extensible
*/
bool SyntaxHints;
+ /** If set to true, users appear to quit then rejoin when their hosts change.
+ * This keeps clients synchronized properly.
+ */
+ bool CycleHosts;
+
ServerConfig(InspIRCd* Instance);
- /** Clears the include stack in preperation for
- * a Read() call.
+ /** Clears the include stack in preperation for a Read() call.
*/
void ClearStack();
diff --git a/include/mode.h b/include/mode.h
index b26c0d9c3..4cdab2884 100644
--- a/include/mode.h
+++ b/include/mode.h
@@ -445,6 +445,16 @@ class ModeParser : public classbase
/** This returns the PREFIX=(ohv)@%+ section of the 005 numeric.
*/
std::string BuildPrefixes();
+
+ /** This returns the privilages of a user upon a channel, in the format of a mode change.
+ * For example, if a user has privilages +avh, this will return the string "avh nick nick nick".
+ * This is used by the core when cycling a user to refresh their hostname. You may use it for
+ * similar purposes.
+ * @param user The username to look up
+ * @param channel The channel name to look up the privilages of the user for
+ * @return The mode string.
+ */
+ std::string ModeString(userrec* user, chanrec* channel);
};
/** Command handler class for the MODE command.
diff --git a/src/configreader.cpp b/src/configreader.cpp
index a9e34a716..d8651766d 100644
--- a/src/configreader.cpp
+++ b/src/configreader.cpp
@@ -37,7 +37,7 @@ ServerConfig::ServerConfig(InspIRCd* Instance) : ServerInstance(Instance)
*OperOnlyStats = *ModPath = *MyExecutable = *DisabledCommands = *PID = '\0';
log_file = NULL;
NoUserDns = forcedebug = OperSpyWhois = nofork = HideBans = HideSplits = false;
- writelog = AllowHalfop = true;
+ CycleHosts = writelog = AllowHalfop = true;
dns_timeout = DieDelay = 5;
MaxTargets = 20;
NetBufferSize = 10240;
@@ -560,6 +560,7 @@ void ServerConfig::Read(bool bail, userrec* user)
{"options", "tempdir", &this->TempDir, DT_CHARPTR, ValidateTempDir},
{"options", "nouserdns", &this->NoUserDns, DT_BOOLEAN, NoValidation},
{"options", "syntaxhints", &this->SyntaxHints, DT_BOOLEAN, NoValidation},
+ {"options", "cyclehosts", &this->CycleHosts, DT_BOOLEAN, NoValidation},
{"pid", "file", &this->PID, DT_CHARPTR, NoValidation},
{NULL}
};
diff --git a/src/mode.cpp b/src/mode.cpp
index 8351ab2e0..5ae457b68 100644
--- a/src/mode.cpp
+++ b/src/mode.cpp
@@ -666,6 +666,31 @@ ModeHandler* ModeParser::FindPrefix(unsigned const char pfxletter)
return NULL;
}
+std::string ModeParser::ModeString(userrec* user, chanrec* channel)
+{
+ std::string types;
+ std::string pars;
+
+ for (unsigned char mode = 'A'; mode <= 'z'; mode++)
+ {
+ unsigned char pos = (mode-65) | MASK_CHANNEL;
+ ModeHandler* mh = modehandlers[pos];
+ if ((mh) && (mh->GetNumParams(true)) && (mh->GetNumParams(false)))
+ {
+ ModePair ret;
+ ret = mh->ModeSet(NULL, user, channel, user->nick);
+ if (ret.first)
+ {
+ pars.append(" ");
+ pars.append(user->nick);
+ types.push_back(mh->GetModeChar());
+ }
+ }
+ }
+
+ return types+pars;
+}
+
std::string ModeParser::ChanModes()
{
std::string type1; /* Listmodes EXCEPT those with a prefix */
diff --git a/src/modes/cmode_h.cpp b/src/modes/cmode_h.cpp
index 1b0370439..d58fb94c9 100644
--- a/src/modes/cmode_h.cpp
+++ b/src/modes/cmode_h.cpp
@@ -28,7 +28,7 @@ ModePair ModeChannelHalfOp::ModeSet(userrec* source, userrec* dest, chanrec* cha
userrec* x = ServerInstance->FindNick(parameter);
if (x)
{
- if (channel->GetStatus(x) == STATUS_HOP)
+ if (channel->GetStatusFlags(x) & UCMODE_HOP)
{
return std::make_pair(true, x->nick);
}
diff --git a/src/modes/cmode_o.cpp b/src/modes/cmode_o.cpp
index c631ec779..bed7da615 100644
--- a/src/modes/cmode_o.cpp
+++ b/src/modes/cmode_o.cpp
@@ -28,7 +28,7 @@ ModePair ModeChannelOp::ModeSet(userrec* source, userrec* dest, chanrec* channel
userrec* x = ServerInstance->FindNick(parameter);
if (x)
{
- if (channel->GetStatus(x) == STATUS_OP)
+ if (channel->GetStatusFlags(x) & UCMODE_OP)
{
return std::make_pair(true, x->nick);
}
diff --git a/src/modes/cmode_v.cpp b/src/modes/cmode_v.cpp
index 7b14d84d4..f12d9f9cf 100644
--- a/src/modes/cmode_v.cpp
+++ b/src/modes/cmode_v.cpp
@@ -7,7 +7,6 @@
#include "mode.h"
#include "channels.h"
#include "users.h"
-
#include "commands.h"
#include "modules.h"
#include "inspstring.h"
@@ -28,7 +27,7 @@ ModePair ModeChannelVoice::ModeSet(userrec* source, userrec* dest, chanrec* chan
userrec* x = ServerInstance->FindNick(parameter);
if (x)
{
- if (channel->GetStatus(x) == STATUS_VOICE)
+ if (channel->GetStatusFlags(x) & UCMODE_VOICE)
{
return std::make_pair(true, x->nick);
}
diff --git a/src/users.cpp b/src/users.cpp
index 085440367..031333dfc 100644
--- a/src/users.cpp
+++ b/src/users.cpp
@@ -1632,8 +1632,24 @@ bool userrec::ChangeDisplayedHost(const char* host)
return false;
FOREACH_MOD(I_OnChangeHost,OnChangeHost(this,host));
}
+ if (this->ServerInstance->Config->CycleHosts)
+ this->WriteCommonExcept("QUIT :Changing hosts");
+
strlcpy(this->dhost,host,63);
+ if (this->ServerInstance->Config->CycleHosts)
+ {
+ for (std::vector<ucrec*>::const_iterator i = this->chans.begin(); i != this->chans.end(); i++)
+ {
+ if ((*i)->channel)
+ {
+ (*i)->channel->WriteAllExceptSender(this, 0, "JOIN %s", (*i)->channel->name);
+ (*i)->channel->WriteChannelWithServ(this->ServerInstance->Config->ServerName, "MODE %s +%s",
+ (*i)->channel->name, this->ServerInstance->Modes->ModeString(this, (*i)->channel).c_str());
+ }
+ }
+ }
+
if (IS_LOCAL(this))
this->WriteServ("396 %s %s :is now your hidden host",this->nick,this->dhost);