use crate::error::PathError;
use crate::platform::is_reserved_windows_name;
use std::path::{Component, Path};
pub(crate) const MAX_EXPANSION_DEPTH: u32 = 8;
#[cfg(feature = "search")]
pub(crate) const MAX_PATTERN_LENGTH: usize = 4096;
pub(crate) fn reject_nul(input: &str) -> Result<(), PathError> {
if input.contains('\0') {
return Err(PathError::EmbeddedNul);
}
Ok(())
}
pub(crate) fn reject_nul_path(path: &Path) -> Result<(), PathError> {
#[cfg(unix)]
{
use std::os::unix::ffi::OsStrExt;
if path.as_os_str().as_bytes().contains(&0) {
return Err(PathError::EmbeddedNul);
}
}
#[cfg(not(unix))]
{
if path.to_string_lossy().contains('\0') {
return Err(PathError::EmbeddedNul);
}
}
Ok(())
}
pub(crate) fn validate_app_name(app_name: &str) -> Result<(), PathError> {
if app_name.is_empty() {
return Err(PathError::InvalidAppName {
message: "application name must not be empty".into(),
});
}
reject_nul(app_name).map_err(|_| PathError::InvalidAppName {
message: "application name must not contain NUL".into(),
})?;
if app_name.contains('/') || app_name.contains('\\') {
return Err(PathError::InvalidAppName {
message: "application name must not contain path separators".into(),
});
}
if app_name == "." || app_name == ".." {
return Err(PathError::InvalidAppName {
message: "application name must not be '.' or '..'".into(),
});
}
if app_name.contains("..") {
return Err(PathError::InvalidAppName {
message: "application name must not contain '..'".into(),
});
}
let as_path = Path::new(app_name);
let mut components = as_path.components();
match (components.next(), components.next()) {
(Some(Component::Normal(name)), None) => {
if is_reserved_windows_name(name) {
return Err(PathError::InvalidAppName {
message: format!(
"application name collides with a Windows reserved name: {}",
name.to_string_lossy()
),
});
}
}
_ => {
return Err(PathError::InvalidAppName {
message: "application name must be a single path component".into(),
});
}
}
Ok(())
}
#[cfg(feature = "listing")]
pub(crate) fn is_hidden_name(name: &std::ffi::OsStr) -> bool {
name.to_string_lossy().starts_with('.')
}