use crate::api::xml;
use crate::api::{Client, Error, READ_ONLY_COMMANDS, Transport, canonical_command};
const RESERVED_PARAMS: &[&str] = &["apiuser", "apikey", "username", "command", "clientip"];
pub fn parse_params(raw: &[String]) -> Result<Vec<(String, String)>, Error> {
raw.iter()
.map(|p| {
let (k, v) = p
.split_once('=')
.ok_or_else(|| Error::Usage(format!("--param {p:?} is not KEY=VALUE")))?;
if RESERVED_PARAMS.contains(&k.to_ascii_lowercase().as_str()) {
return Err(Error::Usage(format!(
"--param {k} is reserved: authentication parameters are set from the profile"
)));
}
Ok((k.to_owned(), v.to_owned()))
})
.collect()
}
pub fn call<T: Transport>(
client: &Client<T>,
command: &str,
params: &[(String, String)],
) -> Result<String, Error> {
let canonical = canonical_command(command);
if !READ_ONLY_COMMANDS.contains(&canonical.as_str()) {
return Err(Error::Usage(format!(
"{command:?} is not on the read-only allowlist; allowed: {}",
READ_ONLY_COMMANDS.join(", ")
)));
}
let params: Vec<(&str, &str)> = params
.iter()
.map(|(k, v)| (k.as_str(), v.as_str()))
.collect();
let body = client.call(&canonical, ¶ms)?;
let _: serde::de::IgnoredAny = xml::parse(&body)?;
Ok(body)
}