mirror of
https://github.com/xavo95/repak.git
synced 2025-01-18 19:04:07 +00:00
reconfigure for entry reading and api
This commit is contained in:
parent
c440ca6707
commit
7d1fd167e1
3 changed files with 55 additions and 30 deletions
|
@ -34,6 +34,7 @@ pub struct Entry {
|
||||||
|
|
||||||
impl Entry {
|
impl Entry {
|
||||||
pub fn new<R: io::Read>(reader: &mut R, version: super::Version) -> Result<Self, super::Error> {
|
pub fn new<R: io::Read>(reader: &mut R, version: super::Version) -> Result<Self, super::Error> {
|
||||||
|
// since i need the compression flags, i have to store these as variables which is mildly annoying
|
||||||
let offset = reader.read_u64::<LE>()?;
|
let offset = reader.read_u64::<LE>()?;
|
||||||
let compressed = reader.read_u64::<LE>()?;
|
let compressed = reader.read_u64::<LE>()?;
|
||||||
let uncompressed = reader.read_u64::<LE>()?;
|
let uncompressed = reader.read_u64::<LE>()?;
|
||||||
|
@ -66,9 +67,10 @@ impl Entry {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read<R: io::Read + io::Seek>(
|
pub fn read<R: io::Read + io::Seek>(
|
||||||
self,
|
&self,
|
||||||
reader: &mut R,
|
reader: &mut R,
|
||||||
version: super::Version,
|
version: super::Version,
|
||||||
|
key: Option<&aes::Aes256Dec>,
|
||||||
) -> Result<Vec<u8>, super::Error> {
|
) -> Result<Vec<u8>, super::Error> {
|
||||||
let buf = io::BufWriter::new(Vec::new());
|
let buf = io::BufWriter::new(Vec::new());
|
||||||
todo!("read the stuff");
|
todo!("read the stuff");
|
||||||
|
|
|
@ -10,8 +10,8 @@ pub struct Footer {
|
||||||
pub encrypted: bool,
|
pub encrypted: bool,
|
||||||
pub magic: u32,
|
pub magic: u32,
|
||||||
pub version: Version,
|
pub version: Version,
|
||||||
pub offset: u64,
|
pub index_offset: u64,
|
||||||
pub size: u64,
|
pub index_size: u64,
|
||||||
pub hash: [u8; 20],
|
pub hash: [u8; 20],
|
||||||
pub frozen: bool,
|
pub frozen: bool,
|
||||||
pub compression: Vec<Compression>,
|
pub compression: Vec<Compression>,
|
||||||
|
@ -27,8 +27,8 @@ impl Footer {
|
||||||
encrypted: version >= Version::IndexEncryption && reader.read_bool()?,
|
encrypted: version >= Version::IndexEncryption && reader.read_bool()?,
|
||||||
magic: reader.read_u32::<LE>()?,
|
magic: reader.read_u32::<LE>()?,
|
||||||
version: Version::from_repr(reader.read_u32::<LE>()?).unwrap_or(version),
|
version: Version::from_repr(reader.read_u32::<LE>()?).unwrap_or(version),
|
||||||
offset: reader.read_u64::<LE>()?,
|
index_offset: reader.read_u64::<LE>()?,
|
||||||
size: reader.read_u64::<LE>()?,
|
index_size: reader.read_u64::<LE>()?,
|
||||||
hash: reader.read_guid()?,
|
hash: reader.read_guid()?,
|
||||||
frozen: version == Version::FrozenIndex && reader.read_bool()?,
|
frozen: version == Version::FrozenIndex && reader.read_bool()?,
|
||||||
compression: {
|
compression: {
|
||||||
|
|
73
src/pak.rs
73
src/pak.rs
|
@ -1,53 +1,76 @@
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
use super::ReadExt;
|
|
||||||
use aes::cipher::{BlockDecrypt, KeyInit};
|
|
||||||
use byteorder::{ReadBytesExt, LE};
|
|
||||||
|
|
||||||
use super::Version;
|
use super::Version;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Pak {
|
pub struct Pak<R: io::Read + io::Seek> {
|
||||||
pub version: Version,
|
version: Version,
|
||||||
pub footer: super::Footer,
|
mount_point: String,
|
||||||
pub mount_point: String,
|
key: Option<aes::Aes256Dec>,
|
||||||
pub entries: hashbrown::HashMap<String, super::Entry>,
|
entries: hashbrown::HashMap<String, super::Entry>,
|
||||||
|
reader: R,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Pak {
|
impl<R: io::Read + io::Seek> Pak<R> {
|
||||||
pub fn new<R: io::Read + io::Seek>(
|
pub fn new(
|
||||||
mut reader: R,
|
mut reader: R,
|
||||||
version: super::Version,
|
version: super::Version,
|
||||||
key: Option<&[u8]>,
|
key_hash: Option<&[u8]>,
|
||||||
) -> Result<Self, super::Error> {
|
) -> Result<Self, super::Error> {
|
||||||
|
use super::ReadExt;
|
||||||
|
use byteorder::{ReadBytesExt, LE};
|
||||||
|
// read footer to get index, encryption & compression info
|
||||||
reader.seek(io::SeekFrom::End(-version.size()))?;
|
reader.seek(io::SeekFrom::End(-version.size()))?;
|
||||||
let footer = super::Footer::new(&mut reader, version)?;
|
let footer = super::Footer::new(&mut reader, version)?;
|
||||||
reader.seek(io::SeekFrom::Start(footer.offset))?;
|
// read index to get all the entry info
|
||||||
let mut index = reader.read_len(footer.size as usize)?;
|
reader.seek(io::SeekFrom::Start(footer.index_offset))?;
|
||||||
if let Some(key) = key {
|
let mut index = reader.read_len(footer.index_size as usize)?;
|
||||||
match aes::Aes256Dec::new_from_slice(key) {
|
let mut key = None;
|
||||||
Ok(key) => {
|
// decrypt index if needed
|
||||||
for chunk in index.chunks_mut(16) {
|
if footer.encrypted {
|
||||||
key.decrypt_block(aes::Block::from_mut_slice(chunk))
|
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),
|
||||||
}
|
}
|
||||||
Err(_) => return Err(super::Error::Aes),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mount_point = reader.read_string()?;
|
let mut index = io::Cursor::new(index);
|
||||||
let len = reader.read_u32::<LE>()? as usize;
|
let mount_point = index.read_string()?;
|
||||||
|
let len = index.read_u32::<LE>()? as usize;
|
||||||
let mut entries = hashbrown::HashMap::with_capacity(len);
|
let mut entries = hashbrown::HashMap::with_capacity(len);
|
||||||
for _ in 0..len {
|
for _ in 0..len {
|
||||||
entries.insert(
|
entries.insert(
|
||||||
reader.read_string()?,
|
index.read_string()?,
|
||||||
super::Entry::new(&mut reader, version)?,
|
super::Entry::new(&mut index, version)?,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
version,
|
version,
|
||||||
footer,
|
|
||||||
mount_point,
|
mount_point,
|
||||||
|
key,
|
||||||
entries,
|
entries,
|
||||||
|
reader,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn version(&self) -> super::Version {
|
||||||
|
self.version
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mount_point(&self) -> &str {
|
||||||
|
&self.mount_point
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(&mut self, path: &str) -> Option<Result<Vec<u8>, super::Error>> {
|
||||||
|
self.entries
|
||||||
|
.get(path)
|
||||||
|
.map(|entry| entry.read(&mut self.reader, self.version, self.key.as_ref()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue