diff --git a/Cargo.toml b/Cargo.toml index 0ef678f..b89279f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "docxtools" -version = "0.9.1-SNAPSHOT" +version = "0.10.0-SNAPSHOT" edition = "2021" authors = ["David Bosschaert "] license = "Apache-2.0" diff --git a/src/file_util.rs b/src/file_util.rs index bb42435..08adee4 100644 --- a/src/file_util.rs +++ b/src/file_util.rs @@ -1,24 +1,37 @@ -use std::path::Path; +use std::path::{MAIN_SEPARATOR, MAIN_SEPARATOR_STR, Path}; pub struct FileUtil { } impl FileUtil { + pub fn normalize_path(s: &str) -> String { + let src_char = if MAIN_SEPARATOR == '/' { + "\\" + } else { + "/" + }; + + s.replace(src_char, MAIN_SEPARATOR_STR) + } + pub fn get_sub_path(path: &Path, base_dir: &str) -> String { + let nbase_dir = FileUtil::normalize_path(base_dir); + let base; - if base_dir.ends_with("/") { - base = base_dir.to_owned(); + if nbase_dir.ends_with(MAIN_SEPARATOR_STR) { + base = nbase_dir; } else { - base = base_dir.to_owned() + "/"; + base = nbase_dir + MAIN_SEPARATOR_STR; } let sub_path; let full_path = path.to_string_lossy(); - if full_path.starts_with(&base) { - sub_path = &full_path[base.len()..]; + let nfull_path = FileUtil::normalize_path(&full_path); + if nfull_path.starts_with(&base) { + sub_path = &nfull_path[base.len()..]; } else { - sub_path = &full_path; + sub_path = &nfull_path; } sub_path.to_owned() @@ -34,20 +47,20 @@ mod tests { fn test_get_sub_path() { let p = Path::new("/some/where/on/the/rainbow.docx"); let b = "/some/where/on/"; - assert_eq!("the/rainbow.docx", FileUtil::get_sub_path(p, b)); + assert_eq!(FileUtil::normalize_path("the/rainbow.docx"), FileUtil::get_sub_path(p, b)); } #[test] fn test_get_sub_path1() { let p = Path::new("/some/where/on/the/rainbow.docx"); let b = "/some/where/on"; - assert_eq!("the/rainbow.docx", FileUtil::get_sub_path(p, b)); + assert_eq!(FileUtil::normalize_path("the/rainbow.docx"), FileUtil::get_sub_path(p, b)); } #[test] fn test_get_sub_path2() { let b = "/some/where/on/"; let p = Path::new("/elsewhere/cloud.docx"); - assert_eq!("/elsewhere/cloud.docx", FileUtil::get_sub_path(p, b)); + assert_eq!(FileUtil::normalize_path("/elsewhere/cloud.docx"), FileUtil::get_sub_path(p, b)); } } \ No newline at end of file diff --git a/src/xml_util.rs b/src/xml_util.rs index 1620a75..fc705ed 100644 --- a/src/xml_util.rs +++ b/src/xml_util.rs @@ -7,7 +7,7 @@ use regex::Regex; use std::collections::{BTreeMap, HashMap}; use std::fs::{File, self}; use std::io::{BufReader, BufWriter}; -use std::path::{Path, PathBuf}; +use std::path::{Path, PathBuf, MAIN_SEPARATOR, MAIN_SEPARATOR_STR}; use std::str; use uuid::Uuid; use unicase::UniCase; @@ -154,7 +154,7 @@ impl XMLUtil { let mut rels_files = vec!(); for f in files { - let last_slash = f.rfind('/').expect(&f); + let last_slash = f.rfind(MAIN_SEPARATOR).expect(&f); let mut new_fn = String::new(); new_fn.push_str(&f[..last_slash]); new_fn.push_str("/_"); @@ -162,7 +162,7 @@ impl XMLUtil { new_fn.push_str(&f[last_slash..]); new_fn.push('.'); new_fn.push_str(rels_extension); - rels_files.push(new_fn); + rels_files.push(FileUtil::normalize_path(&new_fn)); } rels_files @@ -175,9 +175,9 @@ impl XMLUtil { /// `pattern` and `replacement` are used to search/replace operations. /// `output_file` optionally specifies a different output file for replacement operations. fn snr_xml(mode: Mode, dir: &str, src_file: &str, files: Option>, output_file: Option<&str>) { - let mut base_dir = dir.to_owned(); - if !dir.ends_with("/") { - base_dir.push('/'); + let mut base_dir = FileUtil::normalize_path(dir); + if !base_dir.ends_with(MAIN_SEPARATOR_STR) { + base_dir.push(MAIN_SEPARATOR); } for entry in WalkDir::new(dir).into_iter() @@ -838,7 +838,7 @@ impl XMLUtil { } else { rel_pn = pn; } - mappings.insert(rel_pn.to_string(), + mappings.insert(FileUtil::normalize_path(rel_pn), str::from_utf8(cv.value.as_ref()).unwrap().to_string()); } } diff --git a/src/zip_util.rs b/src/zip_util.rs index 39e079a..bf285e4 100644 --- a/src/zip_util.rs +++ b/src/zip_util.rs @@ -151,7 +151,7 @@ impl ZipUtil { mod tests { use crate::file_util::FileUtil; use super::ZipUtil; - use std::{path::Path, fs, io}; + use std::{path::MAIN_SEPARATOR_STR, path::Path, fs, io}; use walkdir::WalkDir; use testdir::testdir; @@ -165,13 +165,13 @@ mod tests { let wd = WalkDir::new(&outdir); let extracts: Vec = wd.into_iter() .map(|e| FileUtil::get_sub_path(&e.unwrap().path(), &outdir.to_string_lossy())) - .filter(|e| !e.starts_with("/")) + .filter(|e| !e.starts_with(MAIN_SEPARATOR_STR)) .filter(|e| e.contains('.')) .collect(); assert!(extracts.contains(&"foo.test.txt".into())); assert!(extracts.contains(&"empty.file".into())); - assert!(extracts.contains(&"sub/sub/[Content_Types].xml".into())); + assert!(extracts.contains(&FileUtil::normalize_path("sub/sub/[Content_Types].xml"))); assert_eq!(3, extracts.len(), "Should be only 3 files"); let empty_file = Path::new(&outdir).join("empty.file"); @@ -209,14 +209,14 @@ mod tests { let extracts: Vec = WalkDir::new(&expldir).into_iter() .map(|e| FileUtil::get_sub_path(&e.unwrap().path(), &expldir.to_string_lossy())) - .filter(|e| !e.starts_with("/")) + .filter(|e| !e.starts_with(MAIN_SEPARATOR_STR)) .filter(|e| e.contains('.')) .collect(); assert_eq!(3, extracts.len()); assert!(extracts.contains(&"foo.test.txt".into())); assert!(extracts.contains(&"empty.file".into())); - assert!(extracts.contains(&"sub/sub/[Content_Types].xml".into())); + assert!(extracts.contains(&FileUtil::normalize_path("sub/sub/[Content_Types].xml"))); let empty_file = Path::new(&expldir).join("empty.file"); assert!(empty_file.is_file());