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