From 0b8bdfd2ab30166967313e34bb3ebc5ea1eebe13 Mon Sep 17 00:00:00 2001 From: Daniel Edrisian Date: Thu, 21 Aug 2025 17:40:52 -0700 Subject: [PATCH] aaa --- codex-rs/tui/src/bottom_pane/string_utils.rs | 22 ++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/codex-rs/tui/src/bottom_pane/string_utils.rs b/codex-rs/tui/src/bottom_pane/string_utils.rs index 63fb1541a4..14d5917ca1 100644 --- a/codex-rs/tui/src/bottom_pane/string_utils.rs +++ b/codex-rs/tui/src/bottom_pane/string_utils.rs @@ -1,6 +1,7 @@ use std::path::PathBuf; pub fn normalize_pasted_path(pasted: &str) -> Option { + let pasted = pasted.trim(); // file:// URL → filesystem path if let Ok(url) = url::Url::parse(pasted) { if url.scheme() == "file" { @@ -8,6 +9,20 @@ pub fn normalize_pasted_path(pasted: &str) -> Option { } } + // Windows paths (unquoted) → bypass POSIX shlex to preserve backslashes + // - Drive letter paths like C:\Users\Alice\img.png + // - UNC paths like \\server\share\img.png + let looks_like_windows_drive_path = pasted.len() >= 3 + && pasted.as_bytes()[1] == b':' + && (pasted.as_bytes()[2] == b'/' || pasted.as_bytes()[2] == b'\\') + && pasted.as_bytes()[0].is_ascii_alphabetic(); + let looks_like_unc = pasted.starts_with("\\\\"); + let is_quoted = (pasted.starts_with('"') && pasted.ends_with('"')) + || (pasted.starts_with('\'') && pasted.ends_with('\'')); + if (looks_like_windows_drive_path || looks_like_unc) && !is_quoted { + return Some(PathBuf::from(pasted)); + } + // shell-escaped single path → unescaped let parts: Vec = shlex::Shlex::new(pasted).collect(); if parts.len() == 1 { @@ -96,4 +111,11 @@ mod tests { ); assert_eq!(get_img_format_label(PathBuf::from(r"C:\a\b\noext")), "IMG"); } + + #[test] + fn normalize_unquoted_windows_path() { + let input = r"C:\Users\Alice\img.png"; + let result = normalize_pasted_path(input).expect("should accept unquoted windows path"); + assert_eq!(result, PathBuf::from(r"C:\Users\Alice\img.png")); + } }