]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/coremods/core_channel/cmd_kick.cpp
Add support for blocking tag messages with the deaf mode.
[user/henk/code/inspircd.git] / src / coremods / core_channel / cmd_kick.cpp
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2017-2018 Sadie Powell <sadie@witchery.services>
5  *   Copyright (C) 2017 B00mX0r <b00mx0r@aureus.pw>
6  *   Copyright (C) 2013-2014, 2016 Attila Molnar <attilamolnar@hush.com>
7  *   Copyright (C) 2012, 2019 Robby <robby@chatbelgie.be>
8  *   Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org>
9  *   Copyright (C) 2009 Uli Schlachter <psychon@inspircd.org>
10  *   Copyright (C) 2008 Thomas Stagner <aquanight@inspircd.org>
11  *   Copyright (C) 2007-2008 Dennis Friis <peavey@inspircd.org>
12  *   Copyright (C) 2007 Robin Burchell <robin+git@viroteck.net>
13  *   Copyright (C) 2006 Craig Edwards <brain@inspircd.org>
14  *
15  * This file is part of InspIRCd.  InspIRCd is free software: you can
16  * redistribute it and/or modify it under the terms of the GNU General Public
17  * License as published by the Free Software Foundation, version 2.
18  *
19  * This program is distributed in the hope that it will be useful, but WITHOUT
20  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
21  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
22  * details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
26  */
27
28
29 #include "inspircd.h"
30 #include "core_channel.h"
31
32 CommandKick::CommandKick(Module* parent)
33         : Command(parent, "KICK", 2, 3)
34 {
35         syntax = "<channel> <nick>[,<nick>]+ [:<reason>]";
36 }
37
38 /** Handle /KICK
39  */
40 CmdResult CommandKick::Handle(User* user, const Params& parameters)
41 {
42         Channel* c = ServerInstance->FindChan(parameters[0]);
43         User* u;
44
45         if (CommandParser::LoopCall(user, this, parameters, 1))
46                 return CMD_SUCCESS;
47
48         if (IS_LOCAL(user))
49                 u = ServerInstance->FindNickOnly(parameters[1]);
50         else
51                 u = ServerInstance->FindNick(parameters[1]);
52
53         if (!c)
54         {
55                 user->WriteNumeric(Numerics::NoSuchChannel(parameters[0]));
56                 return CMD_FAILURE;
57         }
58         if ((!u) || (u->registered != REG_ALL))
59         {
60                 user->WriteNumeric(Numerics::NoSuchNick(parameters[1]));
61                 return CMD_FAILURE;
62         }
63
64         Membership* srcmemb = NULL;
65         if (IS_LOCAL(user))
66         {
67                 srcmemb = c->GetUser(user);
68                 if (!srcmemb)
69                 {
70                         user->WriteNumeric(ERR_NOTONCHANNEL, parameters[0], "You're not on that channel!");
71                         return CMD_FAILURE;
72                 }
73
74                 if (u->server->IsULine())
75                 {
76                         user->WriteNumeric(ERR_CHANOPRIVSNEEDED, c->name, "You may not kick a U-lined client");
77                         return CMD_FAILURE;
78                 }
79         }
80
81         const Channel::MemberMap::iterator victimiter = c->userlist.find(u);
82         if (victimiter == c->userlist.end())
83         {
84                 user->WriteNumeric(ERR_USERNOTINCHANNEL, u->nick, c->name, "They are not on that channel");
85                 return CMD_FAILURE;
86         }
87         Membership* const memb = victimiter->second;
88
89         // KICKs coming from servers can carry a membership id
90         if ((!IS_LOCAL(user)) && (parameters.size() > 3))
91         {
92                 // If the current membership id is not equal to the one in the message then the user rejoined
93                 if (memb->id != Membership::IdFromString(parameters[2]))
94                 {
95                         ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Dropped KICK due to membership id mismatch: " + ConvToStr(memb->id) + " != " + parameters[2]);
96                         return CMD_FAILURE;
97                 }
98         }
99
100         const bool has_reason = (parameters.size() > 2);
101         const std::string reason((has_reason ? parameters.back() : user->nick), 0, ServerInstance->Config->Limits.MaxKick);
102
103         // Do the following checks only if the KICK is done by a local user;
104         // each server enforces its own rules.
105         if (srcmemb)
106         {
107                 // Modules are allowed to explicitly allow or deny kicks done by local users
108                 ModResult res;
109                 FIRST_MOD_RESULT(OnUserPreKick, res, (user, memb, reason));
110                 if (res == MOD_RES_DENY)
111                         return CMD_FAILURE;
112
113                 if (res == MOD_RES_PASSTHRU)
114                 {
115                         unsigned int them = srcmemb->getRank();
116                         unsigned int req = HALFOP_VALUE;
117                         for (std::string::size_type i = 0; i < memb->modes.length(); i++)
118                         {
119                                 ModeHandler* mh = ServerInstance->Modes->FindMode(memb->modes[i], MODETYPE_CHANNEL);
120                                 if (mh && mh->GetLevelRequired(true) > req)
121                                         req = mh->GetLevelRequired(true);
122                         }
123
124                         if (them < req)
125                         {
126                                 user->WriteNumeric(ERR_CHANOPRIVSNEEDED, c->name, InspIRCd::Format("You must be a channel %soperator",
127                                         req > HALFOP_VALUE ? "" : "half-"));
128                                 return CMD_FAILURE;
129                         }
130                 }
131         }
132
133         c->KickUser(user, victimiter, reason);
134
135         return CMD_SUCCESS;
136 }
137
138 RouteDescriptor CommandKick::GetRouting(User* user, const Params& parameters)
139 {
140         return (IS_LOCAL(user) ? ROUTE_LOCALONLY : ROUTE_BROADCAST);
141 }