From 97469c58ae5058ee87c16d78cadf83fa9b499727 Mon Sep 17 00:00:00 2001 From: spuds <71292624+bananaturtlesandwich@users.noreply.github.com> Date: Sat, 14 Jan 2023 14:20:00 +0000 Subject: [PATCH] ok read is broken but now iter impl is there --- examples/list.rs | 4 ++-- examples/unpack.rs | 14 ++++++++++++++ examples/version.rs | 8 ++++++-- src/entry.rs | 14 ++++++++------ src/error.rs | 8 +++++--- src/pak.rs | 29 ++++++++++++++++++----------- 6 files changed, 53 insertions(+), 24 deletions(-) create mode 100644 examples/unpack.rs diff --git a/examples/list.rs b/examples/list.rs index 8d9dc45..360e5fd 100644 --- a/examples/list.rs +++ b/examples/list.rs @@ -4,8 +4,8 @@ fn main() -> Result<(), un_pak::Error> { un_pak::Version::CompressionEncryption, None, )?; - for file in pak.entries.keys() { - println!("{file}") + for file in pak.files() { + println!("{file}"); } Ok(()) } diff --git a/examples/unpack.rs b/examples/unpack.rs new file mode 100644 index 0000000..42c2d87 --- /dev/null +++ b/examples/unpack.rs @@ -0,0 +1,14 @@ +fn main() -> Result<(), un_pak::Error> { + let mut pak = un_pak::Pak::new( + std::io::BufReader::new(std::io::Cursor::new(include_bytes!("rando_p.pak"))), + un_pak::Version::CompressionEncryption, + None, + )?; + for file in pak.files() { + match pak.get(&file).expect("file should be in pak") { + Ok(data) => std::fs::write(&file, data)?, + Err(e) => eprintln!("{e}"), + } + } + Ok(()) +} diff --git a/examples/version.rs b/examples/version.rs index 10635fc..985dfb8 100644 --- a/examples/version.rs +++ b/examples/version.rs @@ -7,8 +7,12 @@ fn main() -> Result<(), un_pak::Error> { ver, None, ) { - Ok(un_pak::Pak { version, .. }) | Err(un_pak::Error::Version { version, .. }) => { - println!("{}", version); + Ok(pak) => { + println!("{}", pak.version()); + break; + } + Err(un_pak::Error::Version { version, .. }) => { + println!("{version}"); break; } _ => continue, diff --git a/src/entry.rs b/src/entry.rs index 2cea50b..f53cbaa 100644 --- a/src/entry.rs +++ b/src/entry.rs @@ -72,19 +72,21 @@ impl Entry { ) -> Result, super::Error> { let mut buf = io::BufWriter::new(Vec::with_capacity(self.uncompressed as usize)); reader.seek(io::SeekFrom::Start(self.offset))?; + Entry::new(reader, version)?; let mut data = reader.read_len(match self.encrypted { // add alignment (aes block size: 16) then zero out alignment bits true => (self.compressed + 15) & !17, false => self.compressed, } as usize)?; if self.encrypted { - if let Some(key) = key { - use aes::cipher::BlockDecrypt; - for block in data.chunks_mut(16) { - key.decrypt_block(aes::Block::from_mut_slice(block)) - } - data.truncate(self.compressed as usize); + let Some(key) = key else { + return Err(super::Error::Encrypted); + }; + use aes::cipher::BlockDecrypt; + for block in data.chunks_mut(16) { + key.decrypt_block(aes::Block::from_mut_slice(block)) } + data.truncate(self.compressed as usize); } use io::Write; match self.compression { diff --git a/src/error.rs b/src/error.rs index db198a6..3821300 100644 --- a/src/error.rs +++ b/src/error.rs @@ -14,16 +14,18 @@ pub enum Error { Utf16(#[from] std::string::FromUtf16Error), #[error("bufwriter dereference: {0}")] IntoInner(#[from] std::io::IntoInnerError>>), - #[error("found magic of {0:#x} instead of {:#x}", super::MAGIC)] // crate errors + #[error("got {0}, which is not a boolean")] + Bool(u8), + #[error("found magic of {0:#x} instead of {:#x}", super::MAGIC)] Magic(u32), #[error("used version {used} but pak is version {version}")] Version { used: super::Version, version: super::Version, }, - #[error("got {0}, which is not a boolean")] - Bool(u8), + #[error("pak is encrypted but no key was provided")] + Encrypted, #[error("{0}")] Other(String), } diff --git a/src/pak.rs b/src/pak.rs index d879e51..699f278 100644 --- a/src/pak.rs +++ b/src/pak.rs @@ -27,18 +27,17 @@ impl Pak { let mut key = None; // decrypt index if needed if footer.encrypted { - if let Some(hash) = key_hash { - use aes::cipher::{BlockDecrypt, KeyInit}; - match aes::Aes256Dec::new_from_slice(hash) { - Ok(decrypter) => { - for chunk in index.chunks_mut(16) { - decrypter.decrypt_block(aes::Block::from_mut_slice(chunk)) - } - key = Some(decrypter); - } - Err(_) => return Err(super::Error::Aes), - } + let Some(hash) = key_hash else { + return Err(super::Error::Encrypted); + }; + use aes::cipher::{BlockDecrypt, KeyInit}; + let Ok(decrypter)= aes::Aes256Dec::new_from_slice(hash) else { + return Err(super::Error::Aes) + }; + for chunk in index.chunks_mut(16) { + decrypter.decrypt_block(aes::Block::from_mut_slice(chunk)) } + key = Some(decrypter); } let mut index = io::Cursor::new(index); let mount_point = index.read_string()?; @@ -72,4 +71,12 @@ impl Pak { .get(path) .map(|entry| entry.read(&mut self.reader, self.version, self.key.as_ref())) } + + pub fn files(&self) -> std::vec::IntoIter { + self.entries + .keys() + .cloned() + .collect::>() + .into_iter() + } }