*/
CmdResult CommandKick::Handle (const std::vector<std::string>& parameters, User *user)
{
- std::string reason;
Channel* c = ServerInstance->FindChan(parameters[0]);
User* u;
}
}
- const UserMembIter victimiter = c->userlist.find(u);
+ const Channel::MemberMap::iterator victimiter = c->userlist.find(u);
if (victimiter == c->userlist.end())
{
user->WriteNumeric(ERR_USERNOTINCHANNEL, "%s %s :They are not on that channel", u->nick.c_str(), c->name.c_str());
}
Membership* const memb = victimiter->second;
- if (parameters.size() > 2)
+ // KICKs coming from servers can carry a membership id
+ if ((!IS_LOCAL(user)) && (parameters.size() > 3))
{
- reason.assign(parameters[2], 0, ServerInstance->Config->Limits.MaxKick);
- }
- else
- {
- reason.assign(user->nick, 0, ServerInstance->Config->Limits.MaxKick);
+ // If the current membership id is not equal to the one in the message then the user rejoined
+ if (memb->id != Membership::IdFromString(parameters[2]))
+ {
+ ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Dropped KICK due to membership id mismatch: " + ConvToStr(memb->id) + " != " + parameters[2]);
+ return CMD_FAILURE;
+ }
}
+ const bool has_reason = (parameters.size() > 2);
+ const std::string reason((has_reason ? parameters.back() : user->nick), 0, ServerInstance->Config->Limits.MaxKick);
+
// Do the following checks only if the KICK is done by a local user;
// each server enforces its own rules.
if (srcmemb)