From 11aa6fe84265c334b2acd2a7e87f11adc817dd05 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Mon, 10 May 2021 19:32:12 +0100 Subject: [PATCH] bundles: Scan the zipfile Signed-off-by: Ian Jackson --- Cargo.lock | 1 + Cargo.toml | 1 + src/bundles.rs | 35 +++++++++++++++++++++++++++++++++-- src/prelude.rs | 1 + src/shapelib.rs | 2 +- 5 files changed, 37 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6f887316..b047e9bc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2260,6 +2260,7 @@ dependencies = [ "toml 0.5.8", "typetag", "uds", + "unicase 2.6.0", "url 2.2.1", "usvg", "vecdeque-stableix", diff --git a/Cargo.toml b/Cargo.toml index 03ca80d7..24debfe0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -74,6 +74,7 @@ tera="0.11" toml="0.5" typetag="0.1.6" uds="0.2" +unicase="2" url="2" vecdeque-stableix="1" zip="0.5" diff --git a/src/bundles.rs b/src/bundles.rs index a69b2d05..e6ff1e0b 100644 --- a/src/bundles.rs +++ b/src/bundles.rs @@ -265,6 +265,38 @@ impl From for LoadError { } } +pub struct IndexedZip where R: Read + io::Seek { + za: ZipArchive>, + members: BTreeMap, usize>, +} +deref_to_field_mut!{{ R: Read + io::Seek } + IndexedZip, ZipArchive>, za } + +impl IndexedZip where R: Read + io::Seek { + #[throws(LoadError)] + fn new(file: R) -> Self { + let file = BufReader::new(file); + let mut za = ZipArchive::new(file)?; + let mut members = BTreeMap::new(); + for i in 0..za.len() { + let entry = za.by_index_raw(i)?; + let sname = entry.name().to_owned(); + let uname = UniCase::new(sname.to_owned()); + if let Some(previously) = members.insert(uname, i) { + let sname = sname.to_owned(); + drop(entry); + let previously = za.by_index_raw(previously)?; + let previously = previously.name(); + throw!(LE::BadBundle(format!( + "duplicate files, differing only in case, {:?} vs {:?}", + &previously, sname, + ))); + } + } + IndexedZip { za, members } + } +} + #[ext(pub)] impl ZipArchive where R: Read + io::Seek { #[throws(LoadError)] @@ -366,10 +398,9 @@ fn parse_bundle(id: Id, file: &mut F, bpath: &str) -> Parsed where EH: BundleParseError, F: Read + io::Seek { - let file = BufReader::new(file); match id.kind { Kind::Zip => () } let mut za = EH::required(bpath, ||{ - ZipArchive::new(file) + IndexedZip::new(file) })?; let meta = EH::besteffort(bpath, ||{ diff --git a/src/prelude.rs b/src/prelude.rs index 00989747..221062a3 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -98,6 +98,7 @@ pub use strum::{IntoEnumIterator, IntoStaticStr}; pub use subtle::ConstantTimeEq; pub use tempfile::NamedTempFile; pub use thiserror::Error; +pub use unicase::UniCase; pub use url::Url; pub use vecdeque_stableix::Deque as StableIndexVecDeque; pub use void::{unreachable, Void, ResultVoidExt, ResultVoidErrExt}; diff --git a/src/shapelib.rs b/src/shapelib.rs index 8bedfca6..b55d63d4 100644 --- a/src/shapelib.rs +++ b/src/shapelib.rs @@ -557,7 +557,7 @@ fn resolve_inherit<'r>(depth: u8, groups: &toml::value::Table, Cow::Owned(build) } -trait LibrarySource { +pub trait LibrarySource { fn read_catalogue(&self) -> Result; fn svg_dir(&self) -> String; } -- 2.30.2