use crate::error::ConfigError;
use path_absolutize::Absolutize;
use std::path::{Path, PathBuf};
pub struct PathUtils;
impl PathUtils {
pub fn normalize(path: &str) -> Result<PathBuf, ConfigError> {
let expanded = shellexpand::full(path).map_err(|e| {
ConfigError::FormatDetectionFailed(format!("Path expansion failed: {}", e))
})?;
let path_buf = PathBuf::from(expanded.as_ref());
let absolute = path_buf
.absolutize()
.map_err(|_| ConfigError::UnsafePath(path_buf.clone()))?;
Self::validate_security(&absolute)?;
Ok(absolute.to_path_buf())
}
pub fn validate_security(path: &Path) -> Result<(), ConfigError> {
let path_str = path.to_string_lossy();
let forbidden = [
"/etc/shadow",
"/etc/passwd",
"/proc",
"/sys",
"C:\\Windows\\System32",
];
for &p in &forbidden {
if path_str.starts_with(p) {
return Err(ConfigError::UnsafePath(path.to_path_buf()));
}
}
Ok(())
}
pub fn to_unix_string(path: &Path) -> String {
path.to_string_lossy().replace('\\', "/")
}
}