From 6537ce1dbef0b2db80af4aa0c9d552dc4aa335c0 Mon Sep 17 00:00:00 2001 From: Sadie Powell Date: Tue, 6 Apr 2021 12:14:33 +0100 Subject: [PATCH] Rewrite the COMMANDS handler - C++17ify - Fix the weird visibility logic. - Only show commands to opers that they can execute - Add a priv to show all commands regardless of access. - Use parameters instead of jamming everything into a . - Use SplitCommand as the command is local-only. --- src/coremods/core_info/cmd_commands.cpp | 61 ++++++++++++++++--------- src/coremods/core_info/core_info.h | 15 ++---- 2 files changed, 43 insertions(+), 33 deletions(-) diff --git a/src/coremods/core_info/cmd_commands.cpp b/src/coremods/core_info/cmd_commands.cpp index bec8a16ae..b0b5b6742 100644 --- a/src/coremods/core_info/cmd_commands.cpp +++ b/src/coremods/core_info/cmd_commands.cpp @@ -34,43 +34,62 @@ enum }; CommandCommands::CommandCommands(Module* parent) - : Command(parent, "COMMANDS", 0, 0) + : SplitCommand(parent, "COMMANDS") { Penalty = 3; } /** Handle /COMMANDS */ -CmdResult CommandCommands::Handle(User* user, const Params& parameters) +CmdResult CommandCommands::HandleLocal(LocalUser* user, const Params& parameters) { - const CommandParser::CommandMap& commands = ServerInstance->Parser.GetCommands(); - std::vector list; - list.reserve(commands.size()); - for (CommandParser::CommandMap::const_iterator i = commands.begin(); i != commands.end(); ++i) + std::vector numerics; + numerics.reserve(ServerInstance->Parser.GetCommands().size()); + + for (const auto& [_, command] : ServerInstance->Parser.GetCommands()) { // Don't show privileged commands to users without the privilege. - switch (i->second->access_needed) + bool usable = true; + switch (command->access_needed) { - case CmdAccess::NORMAL: // Everyone can see user commands. + case CmdAccess::NORMAL: // Everyone can use user commands. break; - case CmdAccess::OPERATOR: // Only opers can see oper commands. - if (user->IsOper()) - break; - - continue; - case CmdAccess::SERVER: // Nobody can see server commands. - continue; + case CmdAccess::OPERATOR: // Only opers can use oper commands. + usable = user->HasCommandPermission(command->name); + break; + case CmdAccess::SERVER: // Nobody can use server commands. + usable = false; + break; } - Module* src = i->second->creator; - list.push_back(InspIRCd::Format("%s %s %d %d", i->second->name.c_str(), src->ModuleSourceFile.c_str(), - i->second->min_params, i->second->Penalty)); + // Only send this command to the user if: + // 1. It is usable by the caller. + // 2. The caller has the servers/auspex priv. + if (!usable || user->HasPrivPermission("servers/auspex")) + continue; + + Numeric::Numeric numeric(RPL_COMMANDS); + numeric.push(command->name); + numeric.push(command->creator->ModuleSourceFile); + numeric.push(command->min_params); + if (command->max_params < command->min_params) + numeric.push("*"); + else + numeric.push(command->max_params); + numeric.push(command->Penalty); + numerics.push_back(numeric); } - std::sort(list.begin(), list.end()); - for(unsigned int i=0; i < list.size(); i++) - user->WriteNumeric(RPL_COMMANDS, list[i]); + + // Sort alphabetically by command name. + std::sort(numerics.begin(), numerics.end(), [](const auto& lhs, const auto& rhs) { + return lhs.GetParams()[0] > rhs.GetParams()[0]; + }); + + for (const auto& numeric : numerics) + user->WriteNumeric(numeric); + user->WriteNumeric(RPL_COMMANDSEND, "End of COMMANDS list"); return CmdResult::SUCCESS; } diff --git a/src/coremods/core_info/core_info.h b/src/coremods/core_info/core_info.h index cf0ae8309..15936998c 100644 --- a/src/coremods/core_info/core_info.h +++ b/src/coremods/core_info/core_info.h @@ -108,21 +108,12 @@ class CommandAdmin : public ServerTargetCommand CmdResult Handle(User* user, const Params& parameters) override; }; -/** Handle /COMMANDS. - */ -class CommandCommands : public Command +class CommandCommands final + : public SplitCommand { public: - /** Constructor for commands. - */ CommandCommands(Module* parent); - - /** 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(User* user, const Params& parameters) override; + CmdResult HandleLocal(LocalUser* user, const Params& parameters) override; }; /** Handle /INFO.