From 6a24586412cef47f48edb0a03ac191bc1eebfefd Mon Sep 17 00:00:00 2001 From: NetterSilver <133535268+Silvertree2010@users.noreply.github.com> Date: Sun, 25 Oct 2026 06:29:31 +0000 Subject: [PATCH] Resolve OPC relationship targets that use backslash separators Found while testing crates/pptx/src/opc.rs:295-309 (resolve, used by rels_of) Co-Authored-By: Claude Haiku 5.5 Co-Authored-By: Claude Sonnet 5.5 --- crates/pptx/src/opc.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/crates/pptx/src/opc.rs b/crates/pptx/src/opc.rs index 8e9e8357..c027bb87 100644 --- a/crates/pptx/src/opc.rs +++ b/crates/pptx/src/opc.rs @@ -293,7 +293,7 @@ fn percent_decode(s: &str) -> String { /// Resolve a relative target against a base directory into a part name. pub fn resolve(base: &str, target: &str) -> String { - let target = percent_decode(target.split('#').next().unwrap_or("")); + let target = percent_decode(target.split('#').next().unwrap_or("")).replace('\\', "/"); let target = target.as_str(); let mut segs: Vec<&str> = if target.starts_with('/') { vec![] } else { base.split('/').filter(|s| !s.is_empty()).collect() }; for s in target.split('/') { @@ -497,6 +497,12 @@ mod tests { assert!(p.xml_bytes("missing.xml").is_none()); } + #[test] + fn resolve_backslash_target() { + assert_eq!(resolve("ppt/slides", "..\\media\\image1.png"), "ppt/media/image1.png"); + assert_eq!(resolve("ppt/slides", "\\ppt\\media\\a.png"), "ppt/media/a.png"); + } + #[test] fn path_resolution() { assert_eq!(resolve("ppt/slides", "../media/image1.png"), "ppt/media/image1.png");