2 * InspIRCd -- Internet Relay Chat Daemon
4 * Copyright (C) 2017 B00mX0r <b00mx0r@aureus.pw>
5 * Copyright (C) 2013, 2018, 2020 Sadie Powell <sadie@witchery.services>
6 * Copyright (C) 2012-2014, 2016 Attila Molnar <attilamolnar@hush.com>
7 * Copyright (C) 2012, 2019 Robby <robby@chatbelgie.be>
8 * Copyright (C) 2012 Justin Crawford <Justasic@Gmail.com>
9 * Copyright (C) 2009 Uli Schlachter <psychon@inspircd.org>
10 * Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
11 * Copyright (C) 2008 Thomas Stagner <aquanight@inspircd.org>
12 * Copyright (C) 2007 Robin Burchell <robin+git@viroteck.net>
13 * Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
14 * Copyright (C) 2006 Oliver Lupton <om@inspircd.org>
15 * Copyright (C) 2005-2006, 2010 Craig Edwards <brain@inspircd.org>
17 * This file is part of InspIRCd. InspIRCd is free software: you can
18 * redistribute it and/or modify it under the terms of the GNU General Public
19 * License as published by the Free Software Foundation, version 2.
21 * This program is distributed in the hope that it will be useful, but WITHOUT
22 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
23 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
26 * You should have received a copy of the GNU General Public License
27 * along with this program. If not, see <http://www.gnu.org/licenses/>.
34 * This module supports the use of the +q and +a usermodes, but should work without them too.
35 * Usage of the command is restricted to +hoaq, and you cannot remove a user with a "higher" level than yourself.
36 * eg: +h can remove +hv and users with no modes. +a can remove +aohv and users with no modes.
39 /** Base class for /FPART and /REMOVE
41 class RemoveBase : public Command
44 ChanModeReference& nokicksmode;
47 unsigned int protectedrank;
49 RemoveBase(Module* Creator, bool& snk, ChanModeReference& nkm, const char* cmdn)
50 : Command(Creator, cmdn, 2, 3)
56 CmdResult HandleRMB(User* user, const CommandBase::Params& parameters, bool fpart)
62 // If the command is a /REMOVE then detect the parameter order
63 bool neworder = ((fpart) || (parameters[0][0] == '#'));
65 /* Set these to the parameters needed, the new version of this module switches it's parameters around
66 * supplying a new command with the new order while keeping the old /remove with the older order.
67 * /remove <nick> <channel> [reason ...]
68 * /fpart <channel> <nick> [reason ...]
70 const std::string& channame = parameters[neworder ? 0 : 1];
71 const std::string& username = parameters[neworder ? 1 : 0];
73 /* Look up the user we're meant to be removing from the channel */
75 target = ServerInstance->FindNickOnly(username);
77 target = ServerInstance->FindNick(username);
79 /* And the channel we're meant to be removing them from */
80 channel = ServerInstance->FindChan(channame);
82 /* Fix by brain - someone needs to learn to validate their input! */
85 user->WriteNumeric(Numerics::NoSuchChannel(channame));
88 if ((!target) || (target->registered != REG_ALL))
90 user->WriteNumeric(Numerics::NoSuchNick(username));
94 if (!channel->HasUser(target))
96 user->WriteNotice(InspIRCd::Format("*** User %s is not on channel %s", target->nick.c_str(), channel->name.c_str()));
100 if (target->server->IsULine())
102 user->WriteNumeric(ERR_CHANOPRIVSNEEDED, channame, "Only a U-line may remove a U-line from a channel.");
106 /* We support the +Q channel mode via. the m_nokicks module, if the module is loaded and the mode is set then disallow the /remove */
107 if ((!IS_LOCAL(user)) || (!supportnokicks) || (!channel->IsModeSet(nokicksmode)))
109 /* We'll let everyone remove their level and below, eg:
110 * ops can remove ops, halfops, voices, and those with no mode (no moders actually are set to 1)
111 a ulined target will get a higher level than it's possible for a /remover to get..so they're safe.
112 * Nobody may remove people with >= protectedrank rank.
114 unsigned int ulevel = channel->GetPrefixValue(user);
115 unsigned int tlevel = channel->GetPrefixValue(target);
116 if ((!IS_LOCAL(user)) || ((ulevel > VOICE_VALUE) && (ulevel >= tlevel) && ((protectedrank == 0) || (tlevel < protectedrank))))
118 // REMOVE will be sent to the target's server and it will reply with a PART (or do nothing if it doesn't understand the command)
119 if (!IS_LOCAL(target))
121 // Send an ENCAP REMOVE with parameters being in the old <user> <chan> order which is
122 // compatible with both 2.0 and 3.0. This also turns FPART into REMOVE.
123 CommandBase::Params p;
124 p.push_back(target->uuid);
125 p.push_back(channel->name);
126 if (parameters.size() > 2)
127 p.push_back(":" + parameters[2]);
128 ServerInstance->PI->SendEncapsulatedData(target->server->GetName(), "REMOVE", p, user);
133 std::string reasonparam;
135 /* If a reason is given, use it */
136 if(parameters.size() > 2)
137 reasonparam = parameters[2];
139 reasonparam = "No reason given";
141 /* Build up the part reason string. */
142 reason = "Removed by " + user->nick + ": " + reasonparam;
144 channel->WriteRemoteNotice(InspIRCd::Format("%s removed %s from the channel", user->nick.c_str(), target->nick.c_str()));
145 target->WriteNotice("*** " + user->nick + " removed you from " + channel->name + " with the message: " + reasonparam);
147 channel->PartUser(target, reason);
151 user->WriteNotice(InspIRCd::Format("*** You do not have access to /REMOVE %s from %s", target->nick.c_str(), channel->name.c_str()));
157 /* m_nokicks.so was loaded and +Q was set, block! */
158 user->WriteNumeric(ERR_RESTRICTED, channel->name, InspIRCd::Format("Can't remove user %s from channel (+Q is set)", target->nick.c_str()));
168 class CommandRemove : public RemoveBase
171 CommandRemove(Module* Creator, bool& snk, ChanModeReference& nkm)
172 : RemoveBase(Creator, snk, nkm, "REMOVE")
174 syntax = "<channel> <nick> [:<reason>]";
175 TRANSLATE3(TR_NICK, TR_TEXT, TR_TEXT);
178 CmdResult Handle(User* user, const Params& parameters) CXX11_OVERRIDE
180 return HandleRMB(user, parameters, false);
186 class CommandFpart : public RemoveBase
189 CommandFpart(Module* Creator, bool& snk, ChanModeReference& nkm)
190 : RemoveBase(Creator, snk, nkm, "FPART")
192 syntax = "<channel> <nick> [:<reason>]";
193 TRANSLATE3(TR_TEXT, TR_NICK, TR_TEXT);
196 CmdResult Handle(User* user, const Params& parameters) CXX11_OVERRIDE
198 return HandleRMB(user, parameters, true);
202 class ModuleRemove : public Module
204 ChanModeReference nokicksmode;
211 : nokicksmode(this, "nokick")
212 , cmd1(this, supportnokicks, nokicksmode)
213 , cmd2(this, supportnokicks, nokicksmode)
217 void On005Numeric(std::map<std::string, std::string>& tokens) CXX11_OVERRIDE
222 void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
224 ConfigTag* tag = ServerInstance->Config->ConfValue("remove");
225 supportnokicks = tag->getBool("supportnokicks");
226 cmd1.protectedrank = cmd2.protectedrank = tag->getUInt("protectedrank", 50000);
229 Version GetVersion() CXX11_OVERRIDE
231 return Version("Adds the /FPART and /REMOVE commands which allows channel operators to force part users from a channel.", VF_OPTCOMMON | VF_VENDOR);
235 MODULE_INIT(ModuleRemove)