diff options
| author | 2024-07-17 00:06:50 +0100 | |
|---|---|---|
| committer | 2024-07-17 00:06:50 +0100 | |
| commit | 889d521e05f2e922683d48c74eb00290e7a2f548 (patch) | |
| tree | b4c56bd4cdf0881601c7e4d6ff571e491af10bf4 /src/modules/m_clearchan.cpp | |
| parent | Use std::endian from C++20 in the sha1 module. (diff) | |
Shuffle the modules about a bit.
Diffstat (limited to 'src/modules/m_clearchan.cpp')
| -rw-r--r-- | src/modules/m_clearchan.cpp | 216 |
1 files changed, 0 insertions, 216 deletions
diff --git a/src/modules/m_clearchan.cpp b/src/modules/m_clearchan.cpp deleted file mode 100644 index eac317206..000000000 --- a/src/modules/m_clearchan.cpp +++ /dev/null @@ -1,216 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2018-2023 Sadie Powell <sadie@witchery.services> - * Copyright (C) 2014 Attila Molnar <attilamolnar@hush.com> - * - * 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 - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - - -#include "inspircd.h" -#include "xline.h" - -class CommandClearChan final - : public Command -{ -public: - Channel* activechan; - - CommandClearChan(Module* Creator) - : Command(Creator, "CLEARCHAN", 1, 3) - { - syntax = { "<channel> [KILL|KICK|G|Z] [:<reason>]" }; - access_needed = CmdAccess::OPERATOR; - - // Stop the linking mod from forwarding ENCAP'd CLEARCHAN commands, see below why - force_manual_route = true; - } - - CmdResult Handle(User* user, const Params& parameters) override - { - Channel* chan = activechan = ServerInstance->Channels.Find(parameters[0]); - if (!chan) - { - user->WriteNotice("The channel " + parameters[0] + " does not exist."); - return CmdResult::FAILURE; - } - - // See what method the oper wants to use, default to KILL - std::string method("KILL"); - if (parameters.size() > 1) - { - method = parameters[1]; - std::transform(method.begin(), method.end(), method.begin(), ::toupper); - } - - XLineFactory* xlf = nullptr; - bool kick = (method == "KICK"); - if ((!kick) && (method != "KILL")) - { - if ((method != "Z") && (method != "G")) - { - user->WriteNotice("Invalid method for clearing " + chan->name); - return CmdResult::FAILURE; - } - - xlf = ServerInstance->XLines->GetFactory(method); - if (!xlf) - return CmdResult::FAILURE; - } - - const std::string reason = parameters.size() > 2 ? parameters.back() : "Clearing " + chan->name; - - if (!user->server->IsSilentService()) - ServerInstance->SNO.WriteToSnoMask((IS_LOCAL(user) ? 'a' : 'A'), user->nick + " has cleared \002" + chan->name + "\002 (" + method + "): " + reason); - - user->WriteNotice("Clearing \002" + chan->name + "\002 (" + method + "): " + reason); - - { - // Route this command manually so it is sent before the QUITs we are about to generate. - // The idea is that by the time our QUITs reach the next hop, it has already removed all their - // clients from the channel, meaning victims on other servers won't see the victims on this - // server quitting. - CommandBase::Params eparams; - eparams.push_back(chan->name); - eparams.push_back(method); - eparams.push_back(":"); - eparams.back().append(reason); - ServerInstance->PI->BroadcastEncap(this->name, eparams, user, user); - } - - // Attach to the appropriate hook so we're able to hide the QUIT/KICK messages - Implementation hook = (kick ? I_OnUserKick : I_OnBuildNeighborList); - ServerInstance->Modules.Attach(hook, creator); - - std::string mask; - // Now remove all local non-opers from the channel - Channel::MemberMap& users = chan->userlist; - for (Channel::MemberMap::iterator i = users.begin(); i != users.end(); ) - { - User* curr = i->first; - const Channel::MemberMap::iterator currit = i; - ++i; - - if (!IS_LOCAL(curr) || curr->IsOper()) - continue; - - // If kicking users, remove them and skip the QuitUser() - if (kick) - { - chan->KickUser(ServerInstance->FakeClient, currit, reason); - continue; - } - - // If we are banning users then create the XLine and add it - if (xlf) - { - XLine* xline; - try - { - mask = (method[0] == 'Z') ? curr->GetAddress() : (curr->GetBanUser(true) + "@" + curr->GetRealHost()); - xline = xlf->Generate(ServerInstance->Time(), 60*60, user->nick, reason, mask); - } - catch (const ModuleException&) - { - // Nothing, move on to the next user - continue; - } - - if (!ServerInstance->XLines->AddLine(xline, user)) - delete xline; - } - - ServerInstance->Users.QuitUser(curr, reason); - } - - ServerInstance->Modules.Detach(hook, creator); - if (xlf) - ServerInstance->XLines->ApplyLines(); - - return CmdResult::SUCCESS; - } -}; - -class ModuleClearChan final - : public Module -{ -private: - CommandClearChan cmd; - -public: - ModuleClearChan() - : Module(VF_VENDOR | VF_OPTCOMMON, "Adds the /CLEARCHAN command which allows server operators to mass-punish the members of a channel.") - , cmd(this) - { - } - - void init() override - { - // Only attached while we are working; don't react to events otherwise - Implementation events[] = { I_OnBuildNeighborList, I_OnUserKick }; - ServerInstance->Modules.Detach(events, this, sizeof(events)/sizeof(Implementation)); - } - - void OnBuildNeighborList(User* source, User::NeighborList& include, User::NeighborExceptions& exception) override - { - bool found = false; - for (User::NeighborList::iterator i = include.begin(); i != include.end(); ++i) - { - if ((*i)->chan == cmd.activechan) - { - // Don't show the QUIT to anyone in the channel by default - include.erase(i); - found = true; - break; - } - } - - for (const auto& [member, _] : cmd.activechan->GetUsers()) - { - LocalUser* curr = IS_LOCAL(member); - if (!curr) - continue; - - if (curr->IsOper()) - { - // If another module has removed the channel we're working on from the list of channels - // to consider for sending the QUIT to then don't add exceptions for opers, because the - // module before us doesn't want them to see it or added the exceptions already. - // If there is a value for this oper in excepts already, this won't overwrite it. - if (found) - exception.emplace(curr, true); - continue; - } - else if (!include.empty() && curr->chans.size() > 1) - { - // This is a victim and potentially has another common channel with the user quitting, - // add a negative exception overwriting the previous value, if any. - exception[curr] = false; - } - } - } - - void OnUserKick(User* source, Membership* memb, const std::string& reason, CUList& excepts) override - { - // Hide the KICK from all non-opers - User* leaving = memb->user; - for (const auto& [curr, _] : memb->chan->GetUsers()) - { - if ((IS_LOCAL(curr)) && (!curr->IsOper()) && (curr != leaving)) - excepts.insert(curr); - } - } -}; - -MODULE_INIT(ModuleClearChan) |
