- /** Do we have enough parameters:
- * UID uuid age nick host dhost ident +modestr ip.string :gecos
- */
- if (params.size() != 9)
- {
- this->WriteLine(std::string(":")+this->Instance->Config->ServerName+" KILL "+params[0]+" :Invalid client introduction ("+params[0]+"?)");
- return true;
- }
-
- time_t age = ConvToInt(params[1]);
- const char* tempnick = params[2].c_str();
- std::string empty;
-
- /* XXX probably validate UID length too -- w00t */
- cmd_validation valid[] = { {"Nickname", 2, NICKMAX}, {"Hostname", 3, 64}, {"Displayed hostname", 4, 64}, {"Ident", 5, IDENTMAX}, {"GECOS", 7, MAXGECOS}, {"", 0, 0} };
-
- TreeServer* remoteserver = Utils->FindServer(source);
-
- if (!remoteserver)
- {
- this->WriteLine(std::string(":")+this->Instance->Config->ServerName+" KILL "+params[0]+" :Invalid client introduction (Unknown server "+source+")");
- return true;
- }
-
- userrec *u = this->Instance->FindUUID(params[0]);
-
- if (u)
- {
- /* barf! */
- userrec::QuitUser(this->Instance, u, "UID collision (?!)");
- this->WriteLine(std::string(":")+this->Instance->Config->ServerName+" KILL "+params[0]+" :Invalid client introduction (UID collision (?!))");
- return true;
- }
-
- /* Check parameters for validity before introducing the client, discovered by dmb */
- if (!age)
- {
- this->WriteLine(std::string(":")+this->Instance->Config->ServerName+" KILL "+params[0]+" :Invalid client introduction (Invalid TS?)");
- return true;
- }
-
- for (size_t x = 0; valid[x].length; ++x)
- {
- if (params[valid[x].param].length() > valid[x].length)
- {
- this->WriteLine(std::string(":")+this->Instance->Config->ServerName+" KILL "+params[0]+" :Invalid client introduction (" + valid[x].item + " > " + ConvToStr(valid[x].length) + ")");
- return true;
- }
- }
-
-
- /* check for collision */
- user_hash::iterator iter = this->Instance->clientlist->find(tempnick);
-
- if (iter != this->Instance->clientlist->end())
- {
- /*
- * Nick collision.
- * Under old protocol rules, we would have had to kill both clients.
- * Really, this sucks.
- * These days, we have UID. And, so what we do is, force nick change client(s)
- * involved according to timestamp rules.
- *
- * RULES:
- * user@ip equal:
- * Force nick change on OLDER timestamped client
- * user@ip differ:
- * Force nick change on NEWER timestamped client
- * TS EQUAL:
- * FNC both.
- *
- * This stops abusive use of collisions, simplifies problems with loops, and so on.
- * -- w00t
- */
- Instance->Log(DEBUG,"*** Collision on %s", tempnick);
-
- bool bChangeLocal = true;
- bool bChangeRemote = true;
-
- /* mmk. let's do this again. */
- if (age == iter->second->age)
- {
- /* equal. fuck them both! do nada, let the handler at the bottom figure this out. */
- }
- else
- {
- /* fuck. now it gets complex. */
-
- /* first, let's see if ident@host matches. */
- bool SamePerson = strcmp(iter->second->ident, params[5].c_str())
- && !strcmp(iter->second->GetIPString(), params[7].c_str());
-
- /*
- * if ident@ip is equal, and theirs is newer, or
- * ident@ip differ, and ours is newer
- */
- if((SamePerson && age < iter->second->age) ||
- (!SamePerson && age > iter->second->age))
- {
- /* remote needs to change */
- bChangeLocal = false;
- }
- else
- {
- /* ours needs to change */
- bChangeRemote = false;
- }
- }
-
-
- if (bChangeLocal)
- {
- iter->second->ForceNickChange(iter->second->uuid);
- }
- if (bChangeRemote)
- {
- /*
- * Cheat a little here. Instead of a dedicated command to change UID,
- * use SVSNICK and accept their client with it's UID (as we know the SVSNICK will
- * not fail under any circumstances -- UIDs are netwide exclusive).
- *
- * This means that each side of a collide will generate one extra NICK back to where
- * they have just linked (and where it got the SVSNICK from), however, it will
- * be dropped harmlessly as it will come in as :928AAAB NICK 928AAAB, and we already
- * have 928AAAB's nick set to that.
- * -- w00t
- */
- this->WriteLine(std::string(":")+this->Instance->Config->ServerName+" SVSNICK "+params[0]+" " + params[0]);
- /* also, don't trample on the hash - use their UID as nick */
- tempnick = params[0].c_str();
- }
- }
-
- /* IMPORTANT NOTE: For remote users, we pass the UUID in the constructor. This automatically
- * sets it up in the UUID hash for us.
- */
- userrec* _new = NULL;
- try
- {
- _new = new userrec(this->Instance, params[0]);
- }
- catch (CoreException &e)
- {
- /** TODO: SQUIT the server here, the remote server is fucking with us
- * and has sent us the same UID twice!
- */
- }
- (*(this->Instance->clientlist))[tempnick] = _new;
- _new->SetFd(FD_MAGIC_NUMBER);
- strlcpy(_new->nick, tempnick, NICKMAX - 1);
- strlcpy(_new->host, params[3].c_str(),64);
- strlcpy(_new->dhost, params[4].c_str(),64);
- _new->server = this->Instance->FindServerNamePtr(source.c_str());
- strlcpy(_new->ident, params[5].c_str(),IDENTMAX);
- strlcpy(_new->fullname, params[8].c_str(),MAXGECOS);
- _new->registered = REG_ALL;
- _new->signon = age;
-
- /* we need to remove the + from the modestring, so we can do our stuff */
- std::string::size_type pos_after_plus = params[6].find_first_not_of('+');
- if (pos_after_plus != std::string::npos)
- params[6] = params[6].substr(pos_after_plus);
-
- for (std::string::iterator v = params[6].begin(); v != params[6].end(); v++)
- {
- /* For each mode thats set, increase counter */
- ModeHandler* mh = Instance->Modes->FindMode(*v, MODETYPE_USER);
-
- if (mh)
- {
- mh->OnModeChange(_new, _new, NULL, empty, true);
- _new->SetMode(*v, true);
- mh->ChangeCount(1);
- }
- }
-
- /* now we've done with modes processing, put the + back for remote servers */
- params[6] = "+" + params[6];
-
-#ifdef SUPPORT_IP6LINKS
- if (params[7].find_first_of(":") != std::string::npos)
- _new->SetSockAddr(AF_INET6, params[7].c_str(), 0);
- else
-#endif
- _new->SetSockAddr(AF_INET, params[7].c_str(), 0);
-
- Instance->AddGlobalClone(_new);
-
- bool dosend = !(((this->Utils->quiet_bursts) && (this->bursting || Utils->FindRemoteBurstServer(remoteserver))) || (this->Instance->SilentULine(_new->server)));
-
- if (dosend)
- this->Instance->SNO->WriteToSnoMask('C',"Client connecting at %s: %s!%s@%s [%s] [%s]",_new->server,_new->nick,_new->ident,_new->host, _new->GetIPString(), _new->fullname);
-
- params[8] = ":" + params[8];
- Utils->DoOneToAllButSender(source, "UID", params, source);
-
- // Increment the Source Servers User Count..
- TreeServer* SourceServer = Utils->FindServer(source);
- if (SourceServer)
- {
- SourceServer->AddUserCount();
- }
-
- FOREACH_MOD_I(Instance,I_OnPostConnect,OnPostConnect(_new));
-
- return true;