use std::path::Path;
use super::PublishConfig;
pub(super) fn is_safe_key_id(key_id: &str) -> bool {
!key_id.is_empty()
&& !key_id.contains('/')
&& !key_id.contains('\\')
&& key_id != ".."
&& key_id != "."
}
pub(super) fn resolve_signing_key(
cfg: &PublishConfig,
) -> anyhow::Result<(ed25519_dalek::SigningKey, String)> {
if let Some(path) = &cfg.key_path {
let key = crate::signing::load_signing_key(Some(path), &cfg.key_env)?;
let label = cfg.key_id.clone().unwrap_or_else(|| key_id_from_path(path));
return Ok((key, label));
}
if let Some(key_id) = &cfg.key_id {
if !is_safe_key_id(key_id) {
anyhow::bail!("invalid --key-id {key_id:?}: must not contain path separators or '..'");
}
let key_path = cfg.home.join("keys").join(format!("{key_id}.key"));
let key = crate::signing::load_signing_key(Some(&key_path), &cfg.key_env)?;
return Ok((key, key_id.clone()));
}
let key = crate::signing::load_signing_key(None, &cfg.key_env)?;
Ok((key, "env".to_string()))
}
fn key_id_from_path(path: &Path) -> String {
path.file_stem()
.and_then(|s| s.to_str())
.filter(|s| !s.is_empty())
.unwrap_or("default")
.to_string()
}