From a1886a13967b0471b55428f7aed55087ad357491 Mon Sep 17 00:00:00 2001 From: Curious Date: Tue, 6 May 2025 02:08:44 +0800 Subject: [PATCH] Enhance admin commands parsing --- Cargo.lock | 7 +++++++ Cargo.toml | 1 + src/service/admin/mod.rs | 17 ++++++++++------- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 76150f30..ed4c7638 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -507,6 +507,7 @@ dependencies = [ "serde_yaml", "sha-1", "sha2", + "shell-words", "thiserror 2.0.12", "thread_local", "threadpool", @@ -3009,6 +3010,12 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shell-words" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" + [[package]] name = "shlex" version = "1.3.0" diff --git a/Cargo.toml b/Cargo.toml index 38ccd381..ebdabcd9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -138,6 +138,7 @@ clap = { version = "4", default-features = false, features = [ "usage", ] } humantime = "2" +shell-words = "1.1.0" futures-util = { version = "0.3", default-features = false } # Used for reading the configuration from conduit.toml & environment variables diff --git a/src/service/admin/mod.rs b/src/service/admin/mod.rs index c88dc044..e7f169fb 100644 --- a/src/service/admin/mod.rs +++ b/src/service/admin/mod.rs @@ -539,23 +539,26 @@ impl Service { // Parse chat messages from the admin room into an AdminCommand object fn parse_admin_command(&self, command_line: &str) -> std::result::Result { // Note: argv[0] is `@conduit:servername:`, which is treated as the main command - let mut argv: Vec<_> = command_line.split_whitespace().collect(); + let mut argv = match shell_words::split(command_line) { + Ok(args) => args, + Err(e) => return Err(format!("Failed to parse admin command: {e}")), + }; // Replace `help command` with `command --help` // Clap has a help subcommand, but it omits the long help description. if argv.len() > 1 && argv[1] == "help" { argv.remove(1); - argv.push("--help"); + argv.push("--help".to_owned()); } // Backwards compatibility with `register_appservice`-style commands - let command_with_dashes; - if argv.len() > 1 && argv[1].contains('_') { - command_with_dashes = argv[1].replace('_', "-"); - argv[1] = &command_with_dashes; + if let Some(command) = argv.get_mut(1) { + if command.contains('_') { + *command = command.replace('_', "-"); + } } - AdminCommand::try_parse_from(argv).map_err(|error| error.to_string()) + AdminCommand::try_parse_from(&argv).map_err(|error| error.to_string()) } async fn process_admin_command(