summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/modules/m_spanningtree.cpp85
1 files changed, 81 insertions, 4 deletions
diff --git a/src/modules/m_spanningtree.cpp b/src/modules/m_spanningtree.cpp
index 9484c282b..069ad53db 100644
--- a/src/modules/m_spanningtree.cpp
+++ b/src/modules/m_spanningtree.cpp
@@ -306,6 +306,7 @@ class TreeSocket : public InspSocket
std::string InboundDescription;
int num_lost_users;
int num_lost_servers;
+ nspace::hash_map<std::string,std::string> replacements;
public:
@@ -517,6 +518,29 @@ class TreeSocket : public InspSocket
log(DEBUG,"FJOIN detected, our TS=%lu, their TS=%lu",ourTS,TS);
+ // corect all nicknames that have been force changed due to collision
+ for (unsigned int usernum = 2; usernum < params.size(); usernum++)
+ {
+ log(DEBUG,"Collision translation: In=%s",params[usernum].c_str());
+ char* usr = (char*)params[usernum].c_str();
+ char permissions = *usr;
+ switch (permissions)
+ {
+ case '@':
+ case '%':
+ case '+':
+ usr++;
+ break;
+ }
+ std::string nickname = this->GetFJoinReplacement(usr);
+ if ((permissions == '@') || (permissions == '%') || (permissions == '+'))
+ {
+ nickname = permissions + nickname;
+ }
+ params[usernum] = nickname;
+ log(DEBUG,"Collision translation: Out=%s",params[usernum].c_str());
+ }
+
// do this first, so our mode reversals are correctly received by other servers
// if there is a TS collision.
DoOneToAllButSender(source,"FJOIN",params,source);
@@ -525,6 +549,7 @@ class TreeSocket : public InspSocket
{
// process one channel at a time, applying modes.
char* usr = (char*)params[usernum].c_str();
+ std::string nickname;
char permissions = *usr;
switch (permissions)
{
@@ -600,6 +625,33 @@ class TreeSocket : public InspSocket
return true;
}
+ bool ClearFJoinReplacement()
+ {
+ replacements.clear();
+ return true;
+ }
+
+ void AddFJoinReplacement(std::string oldnick, std::string newnick)
+ {
+ nspace::hash_map<std::string,std::string>::iterator iter = replacements.find(oldnick);
+ if (iter != replacements.end())
+ return;
+ replacements[oldnick] = newnick;
+ }
+
+ std::string GetFJoinReplacement(std::string nickname)
+ {
+ nspace::hash_map<std::string,std::string>::iterator iter = replacements.find(nickname);
+ if (iter != replacements.end())
+ {
+ return iter->second;
+ }
+ else
+ {
+ return nickname;
+ }
+ }
+
bool IntroduceClient(std::string source, std::deque<std::string> params)
{
if (params.size() < 8)
@@ -629,11 +681,13 @@ class TreeSocket : public InspSocket
{
// nick collision
log(DEBUG,"Nick collision on %s!%s@%s: %lu %lu",tempnick,ident.c_str(),host.c_str(),(unsigned long)age,(unsigned long)iter->second->age);
- if (iter->second->age > age)
+ if (iter->second->age >= age)
{
- // ours is older than theirs, ours stays. Ignore their NICK, send KILL.
- this->WriteLine(":"+Srv->GetServerName()+" KILL "+tempnick+" :Nickname collision");
- return true;
+ // ours is older than theirs, ours stays. Set a new nick here, send SVSNICK
+ params[1] = nick = "Guest0";
+ this->WriteLine(":"+Srv->GetServerName()+" FNICK "+tempnick+" "+nick);
+ // temporarily (until end of burst) we auto-replace occurances of the old nick with the new nick
+ AddFJoinReplacement(tempnick,nick);
}
}
@@ -806,6 +860,21 @@ class TreeSocket : public InspSocket
return true;
}
+ bool ForceNick(std::string prefix, std::deque<std::string> params)
+ {
+ if (params.size() != 2)
+ return true;
+ std::string oldnick = params[0];
+ std::string newnick = params[1];
+ userrec* u = Srv->FindNick(oldnick);
+ if (u)
+ {
+ Srv->ChangeUserNick(u,newnick);
+ DoOneToAllButSender(prefix,"FNICK",params,prefix);
+ }
+ return true;
+ }
+
bool RemoteRehash(std::string prefix, std::deque<std::string> params)
{
if (params.size() < 1)
@@ -1120,6 +1189,14 @@ class TreeSocket : public InspSocket
{
return this->RemoteRehash(prefix,params);
}
+ else if (command == "FNICK")
+ {
+ return this->ForceNick(prefix,params);
+ }
+ else if (command == "ENDBURST")
+ {
+ return this->ClearFJoinReplacement();
+ }
else if (command == "SQUIT")
{
if (params.size() == 2)