fix(paths): accept literal tilde-digit filenames
Catalog generation and peer install/download validation rejected any path component containing a tilde followed by digits, even when the component was a valid long filename such as Bosons TD Gold~1.w3m. Remove the heuristic from all three validators and retain the existing device-name and portable-alias checks. Add a regression test for the literal filename so catalog publication and later path validation agree. Test Plan: - just clippy (passed) - just test (passed) - git diff --check (passed)
This commit is contained in:
@@ -184,9 +184,6 @@ fn validate_component(component: &str) -> eyre::Result<()> {
|
||||
if is_windows_device_name(device_stem) {
|
||||
eyre::bail!("catalog path uses a Windows device name: {component}");
|
||||
}
|
||||
if looks_like_dos_short_name(component) {
|
||||
eyre::bail!("catalog path resembles a Windows short-name alias: {component}");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -206,16 +203,6 @@ fn is_windows_device_name(stem: &str) -> bool {
|
||||
})
|
||||
}
|
||||
|
||||
fn looks_like_dos_short_name(component: &str) -> bool {
|
||||
let stem = component.split('.').next().unwrap_or_default();
|
||||
stem.rsplit_once('~').is_some_and(|(prefix, suffix)| {
|
||||
!prefix.is_empty()
|
||||
&& !suffix.is_empty()
|
||||
&& suffix.len() <= 6
|
||||
&& suffix.bytes().all(|byte| byte.is_ascii_digit())
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -242,7 +229,6 @@ mod tests {
|
||||
"NUL.txt",
|
||||
"com1",
|
||||
"LPT¹.log",
|
||||
"LOCAL~1/file",
|
||||
"Donne\u{301}es/file",
|
||||
] {
|
||||
assert!(
|
||||
@@ -252,6 +238,11 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn accepts_literal_tilde_digit_names() {
|
||||
assert!(CanonicalCatalogPath::new("Bosons TD Gold~1.w3m").is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn aliases_are_conservative_across_platforms() {
|
||||
let left = CanonicalCatalogPath::new("Straße/FILE").expect("path should validate");
|
||||
|
||||
@@ -370,9 +370,6 @@ fn validate_component(component: &str) -> eyre::Result<()> {
|
||||
if is_windows_device_name(device_stem) {
|
||||
eyre::bail!("download path uses a Windows device name: {component}");
|
||||
}
|
||||
if looks_like_dos_short_name(component) {
|
||||
eyre::bail!("download path resembles a Windows short-name alias: {component}");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -393,16 +390,6 @@ fn is_windows_device_name(stem: &str) -> bool {
|
||||
})
|
||||
}
|
||||
|
||||
fn looks_like_dos_short_name(component: &str) -> bool {
|
||||
let stem = component.split('.').next().unwrap_or_default();
|
||||
stem.rsplit_once('~').is_some_and(|(prefix, suffix)| {
|
||||
!prefix.is_empty()
|
||||
&& !suffix.is_empty()
|
||||
&& suffix.len() <= 6
|
||||
&& suffix.bytes().all(|byte| byte.is_ascii_digit())
|
||||
})
|
||||
}
|
||||
|
||||
fn validate_existing_destination(
|
||||
game_root: &Path,
|
||||
components: &[&str],
|
||||
|
||||
@@ -374,9 +374,6 @@ pub(super) fn validate_game_id(game_id: &str) -> eyre::Result<()> {
|
||||
if is_windows_device_name(device_stem) {
|
||||
eyre::bail!("game ID uses a Windows device name: {game_id}");
|
||||
}
|
||||
if looks_like_dos_short_name(game_id) {
|
||||
eyre::bail!("game ID resembles a Windows short-name alias: {game_id}");
|
||||
}
|
||||
if is_download_protected_root_name(game_id) {
|
||||
eyre::bail!("game ID is reserved for application state: {game_id}");
|
||||
}
|
||||
@@ -395,16 +392,6 @@ fn is_windows_device_name(stem: &str) -> bool {
|
||||
})
|
||||
}
|
||||
|
||||
fn looks_like_dos_short_name(component: &str) -> bool {
|
||||
let stem = component.split('.').next().unwrap_or_default();
|
||||
stem.rsplit_once('~').is_some_and(|(prefix, suffix)| {
|
||||
!prefix.is_empty()
|
||||
&& !suffix.is_empty()
|
||||
&& suffix.len() <= 6
|
||||
&& suffix.bytes().all(|byte| byte.is_ascii_digit())
|
||||
})
|
||||
}
|
||||
|
||||
fn open_ambient_directory_nofollow(path: &Path) -> eyre::Result<File> {
|
||||
let directory = fs::open_ambient(path, &directory_options(), ambient_authority())?;
|
||||
validate_directory_handle(&directory, &path.display().to_string())?;
|
||||
|
||||
Reference in New Issue
Block a user