userrec* who = NULL; /* User we are currently checking */
std::string channel = params[0]; /* Channel name, as a string */
time_t TS = atoi(params[1].c_str()); /* Timestamp given to us for remote side */
+ std::string nicklist = params[2];
bool created = false;
/* Try and find the channel */
ourTS = chan->age;
else
created = true; /* don't perform deops, and set TS to correct time after processing. */
+
+ /* do this first, so our mode reversals are correctly received by other servers
+ * if there is a TS collision.
+ */
+ params[2] = ":" + params[2];
+ Utils->DoOneToAllButSender(source,"FJOIN",params,source);
+
/* In 1.1, if they have the newer channel, we immediately clear
* all status modes from our users. We then accept their modes.
* If WE have the newer channel its the other side's job to do this.
}
}
/* Put the final parameter of the FJOIN into a tokenstream ready to split it */
- irc::tokenstream users(params[2]);
+ irc::tokenstream users(nicklist);
std::string item = "*";
- /* do this first, so our mode reversals are correctly received by other servers
- * if there is a TS collision.
- */
- params[2] = ":" + params[2];
- Utils->DoOneToAllButSender(source,"FJOIN",params,source);
+
/* Now, process every 'prefixes,nick' pair */
while (item != "")
{
/* Finally, we can actually place the user into the channel.
* We're sure its right. Final answer, phone a friend.
*/
- chanrec::JoinUser(this->Instance, who, channel.c_str(), true, "");
+ if (created)
+ chanrec::JoinUser(this->Instance, who, channel.c_str(), true, "", TS);
+ else
+ chanrec::JoinUser(this->Instance, who, channel.c_str(), true, "");
/* Have we already queued up MAXMODES modes with parameters
* (+qaohv) ready to be sent to the server?
*/
for (unsigned int f = 2; f < modectr; f++)
free(mode_users[f]);
}
- /* if we newly created the channel, set it's TS properly. */
- if (created)
- {
- /* find created channel .. */
- chan = this->Instance->FindChan(channel);
- if (chan)
- /* w00t said this shouldnt be needed but it is.
- * This isnt strictly true, as chan can be NULL
- * if a nick collision has occured and therefore
- * the channel was never created.
- */
- chan->age = TS;
- }
/* All done. That wasnt so bad was it, you can wipe
* the sweat from your forehead now. :-)
*/
/** NICK command */
bool TreeSocket::IntroduceClient(const std::string &source, std::deque<std::string> ¶ms)
{
- if (params.size() < 8)
- return true;
- if (params.size() > 8)
+ /** Do we have enough parameters:
+ * NICK age nick host dhost ident +modes ip :gecos
+ */
+ if (params.size() != 8)
{
this->WriteLine(std::string(":")+this->Instance->Config->ServerName+" KILL "+params[1]+" :Invalid client introduction ("+params[1]+"?)");
return true;
}
- // NICK age nick host dhost ident +modes ip :gecos
- // 0 1 2 3 4 5 6 7
- time_t age = atoi(params[0].c_str());
+ time_t age = atoi(params[0].c_str());
const char* tempnick = params[1].c_str();
- Instance->Log(DEBUG,"New remote client %s",tempnick);
+ /** Check parameters for validity before introducing the client, discovered by dmb.
+ * XXX: Can we make this neater?
+ */
+ if (!age)
+ {
+ this->WriteLine(std::string(":")+this->Instance->Config->ServerName+" KILL "+params[1]+" :Invalid client introduction (Invalid TS?)");
+ return true;
+ }
+ else if (params[1].length() > NICKMAX)
+ {
+ this->WriteLine(std::string(":")+this->Instance->Config->ServerName+" KILL "+params[1]+" :Invalid client introduction ("+params[1]+" > NICKMAX?)");
+ return true;
+ }
+ else if (params[2].length() > 64)
+ {
+ this->WriteLine(std::string(":")+this->Instance->Config->ServerName+" KILL "+params[1]+" :Invalid client introduction ("+params[2]+" > 64?)");
+ return true;
+ }
+ else if (params[3].length() > 64)
+ {
+ this->WriteLine(std::string(":")+this->Instance->Config->ServerName+" KILL "+params[1]+" :Invalid client introduction ("+params[3]+" > 64?)");
+ return true;
+ }
+ else if (params[4].length() > IDENTMAX)
+ {
+ this->WriteLine(std::string(":")+this->Instance->Config->ServerName+" KILL "+params[1]+" :Invalid client introduction ("+params[4]+" > IDENTMAX?)");
+ return true;
+ }
+ else if (params[7].length() > MAXGECOS)
+ {
+ this->WriteLine(std::string(":")+this->Instance->Config->ServerName+" KILL "+params[1]+" :Invalid client introduction ("+params[7]+" > MAXGECOS?)");
+ return true;
+ }
+
+ /** Our client looks ok, lets introduce it now
+ */
+ Instance->Log(DEBUG,"New remote client %s",tempnick);
user_hash::iterator iter = this->Instance->clientlist->find(tempnick);
if (iter != this->Instance->clientlist->end())
{
- // nick collision
+ /* nick collision */
this->WriteLine(std::string(":")+this->Instance->Config->ServerName+" KILL "+tempnick+" :Nickname collision");
userrec::QuitUser(this->Instance, iter->second, "Nickname collision");
return true;
_new->registered = REG_ALL;
_new->signon = age;
- /*
- * we need to remove the + from the modestring, so we can do our stuff
- */
+ /* we need to remove the + from the modestring, so we can do our stuff */
std::string::size_type pos_after_plus = params[5].find_first_not_of('+');
if (pos_after_plus != std::string::npos)
params[5] = params[5].substr(pos_after_plus);