X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fcoremods%2Fcore_channel%2Fcmd_kick.cpp;h=b9fdbef252e23aa15102c37559e665b59b1b5cb6;hb=d71c37e05911d87830987a09128a178c3e402bb4;hp=01f2039fa78e2fa00d4c82c653dd67159b1e5c6e;hpb=c67d3103e9f7397f0ab9631bf07a5e5547deb2c3;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/coremods/core_channel/cmd_kick.cpp b/src/coremods/core_channel/cmd_kick.cpp index 01f2039fa..b9fdbef25 100644 --- a/src/coremods/core_channel/cmd_kick.cpp +++ b/src/coremods/core_channel/cmd_kick.cpp @@ -1,8 +1,16 @@ /* * InspIRCd -- Internet Relay Chat Daemon * - * Copyright (C) 2009 Daniel De Graaf + * Copyright (C) 2017-2018 Sadie Powell + * Copyright (C) 2017 B00mX0r + * Copyright (C) 2013-2014, 2016 Attila Molnar + * Copyright (C) 2012, 2019 Robby + * Copyright (C) 2009-2010 Daniel De Graaf + * Copyright (C) 2009 Uli Schlachter + * Copyright (C) 2008 Thomas Stagner + * Copyright (C) 2007-2008 Dennis Friis * Copyright (C) 2007 Robin Burchell + * Copyright (C) 2006 Craig Edwards * * This file is part of InspIRCd. InspIRCd is free software: you can * redistribute it and/or modify it under the terms of the GNU General Public @@ -19,32 +27,18 @@ #include "inspircd.h" +#include "core_channel.h" -/** Handle /KICK. - */ -class CommandKick : public Command +CommandKick::CommandKick(Module* parent) + : Command(parent, "KICK", 2, 3) { - public: - /** Constructor for kick. - */ - CommandKick ( Module* parent) : Command(parent,"KICK",2,3) { syntax = " {,} []"; } - /** Handle command. - * @param parameters The parameters to the command - * @param user The user issuing the command - * @return A value from CmdResult to indicate command success or failure. - */ - CmdResult Handle(const std::vector& parameters, User *user); - RouteDescriptor GetRouting(User* user, const std::vector& parameters) - { - return (IS_LOCAL(user) ? ROUTE_LOCALONLY : ROUTE_BROADCAST); - } -}; + syntax = " [,]+ [:]"; +} /** Handle /KICK */ -CmdResult CommandKick::Handle (const std::vector& parameters, User *user) +CmdResult CommandKick::Handle(User* user, const Params& parameters) { - std::string reason; Channel* c = ServerInstance->FindChan(parameters[0]); User* u; @@ -56,9 +50,14 @@ CmdResult CommandKick::Handle (const std::vector& parameters, User else u = ServerInstance->FindNick(parameters[1]); - if (!u || !c) + if (!c) + { + user->WriteNumeric(Numerics::NoSuchChannel(parameters[0])); + return CMD_FAILURE; + } + if ((!u) || (u->registered != REG_ALL)) { - user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", u ? parameters[0].c_str() : parameters[1].c_str()); + user->WriteNumeric(Numerics::NoSuchNick(parameters[1])); return CMD_FAILURE; } @@ -68,29 +67,75 @@ CmdResult CommandKick::Handle (const std::vector& parameters, User srcmemb = c->GetUser(user); if (!srcmemb) { - user->WriteNumeric(ERR_NOTONCHANNEL, "%s :You're not on that channel!", parameters[0].c_str()); + user->WriteNumeric(ERR_NOTONCHANNEL, parameters[0], "You're not on that channel!"); return CMD_FAILURE; } if (u->server->IsULine()) { - user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s :You may not kick a u-lined client", c->name.c_str()); + user->WriteNumeric(ERR_CHANOPRIVSNEEDED, c->name, "You may not kick a U-lined client"); return CMD_FAILURE; } } - if (parameters.size() > 2) + const Channel::MemberMap::iterator victimiter = c->userlist.find(u); + if (victimiter == c->userlist.end()) { - reason.assign(parameters[2], 0, ServerInstance->Config->Limits.MaxKick); + user->WriteNumeric(ERR_USERNOTINCHANNEL, u->nick, c->name, "They are not on that channel"); + return CMD_FAILURE; } - else + Membership* const memb = victimiter->second; + + // KICKs coming from servers can carry a membership id + if ((!IS_LOCAL(user)) && (parameters.size() > 3)) + { + // 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) { - reason.assign(user->nick, 0, ServerInstance->Config->Limits.MaxKick); + // Modules are allowed to explicitly allow or deny kicks done by local users + ModResult res; + FIRST_MOD_RESULT(OnUserPreKick, res, (user, memb, reason)); + if (res == MOD_RES_DENY) + return CMD_FAILURE; + + if (res == MOD_RES_PASSTHRU) + { + unsigned int them = srcmemb->getRank(); + unsigned int req = HALFOP_VALUE; + for (std::string::size_type i = 0; i < memb->modes.length(); i++) + { + ModeHandler* mh = ServerInstance->Modes->FindMode(memb->modes[i], MODETYPE_CHANNEL); + if (mh && mh->GetLevelRequired(true) > req) + req = mh->GetLevelRequired(true); + } + + if (them < req) + { + user->WriteNumeric(ERR_CHANOPRIVSNEEDED, c->name, InspIRCd::Format("You must be a channel %soperator", + req > HALFOP_VALUE ? "" : "half-")); + return CMD_FAILURE; + } + } } - c->KickUser(user, u, reason, srcmemb); + c->KickUser(user, victimiter, reason); return CMD_SUCCESS; } -COMMAND_INIT(CommandKick) +RouteDescriptor CommandKick::GetRouting(User* user, const Params& parameters) +{ + return (IS_LOCAL(user) ? ROUTE_LOCALONLY : ROUTE_BROADCAST); +}