1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
use std::io::{BufRead, BufReader, Cursor, Read, Seek, SeekFrom};
use byteorder::{ReadBytesExt, LittleEndian};
use encoding::{Encoding, all::UTF_8};
use flate2::read::ZlibDecoder;
use crate::{PSB_MDF_SIGNATURE, PSB_SIGNATURE, PsbError, PsbErrorKind, PsbFile, PsbRefs, header::{MdfHeader, PsbHeader}, offsets::PsbOffsets, types::{PsbValue, binary_tree::PsbBinaryTree}};
pub struct PsbReader;
impl PsbReader {
pub fn open_psb<T: Read + Seek>(mut stream: T) -> Result<PsbFile<T>, PsbError> {
let start = stream.seek(SeekFrom::Current(0)).unwrap();
let signature = stream.read_u32::<LittleEndian>()?;
if signature != PSB_SIGNATURE {
return Err(PsbError::new(PsbErrorKind::InvalidFile, None));
}
let (_, header) = PsbHeader::from_bytes(&mut stream)?;
let _ = stream.read_u32::<LittleEndian>()?;
let (_, offsets) = PsbOffsets::from_bytes(header.version, &mut stream)?;
stream.seek(SeekFrom::Start(start + offsets.name_offset as u64))?;
let (_, names) = Self::read_names(&mut stream)?;
stream.seek(SeekFrom::Start(start + offsets.strings.offset_pos as u64))?;
let (_, strings) = Self::read_strings(offsets.strings.data_pos + start as u32, &mut stream)?;
let refs = PsbRefs::new(names, strings);
Ok(
PsbFile::new(
header,
refs,
offsets,
stream
)
)
}
pub fn read_names<T: Read + Seek>(stream: &mut T) -> Result<(u64, Vec<String>), PsbError> {
let mut names = Vec::<String>::new();
let (read, btree) = PsbBinaryTree::from_bytes(stream)?;
for raw_string in btree.unwrap() {
let name = UTF_8.decode(&raw_string, encoding::DecoderTrap::Replace).unwrap();
names.push(name);
}
Ok((read, names))
}
pub fn read_strings<T: Read + Seek>(data_pos: u32, stream: &mut T) -> Result<(u64, Vec<String>), PsbError> {
let mut strings = Vec::<String>::new();
let (offsets_read, string_offsets) = match PsbValue::from_bytes(stream)? {
(read, PsbValue::IntArray(array)) => Ok((read, array)),
_ => Err(PsbError::new(PsbErrorKind::InvalidOffsetTable, None))
}?;
let mut reader = BufReader::new(stream.by_ref());
let string_offsets = string_offsets.unwrap();
let mut read = 0_usize;
for offset in string_offsets {
let mut buffer = Vec::new();
reader.seek(SeekFrom::Start(data_pos as u64 + offset as u64))?;
read += reader.read_until(0x00, &mut buffer)?;
let string = UTF_8.decode(&buffer[..buffer.len() - 1], encoding::DecoderTrap::Replace).unwrap();
strings.push(string);
}
Ok((offsets_read + read as u64, strings))
}
}
pub struct MdfReader;
impl MdfReader {
pub fn open_mdf<T: Read + Seek>(mut stream: T) -> Result<PsbFile<Cursor<Vec<u8>>>, PsbError> {
let signature = stream.read_u32::<LittleEndian>()?;
if signature != PSB_MDF_SIGNATURE {
return Err(PsbError::new(PsbErrorKind::InvalidFile, None));
}
let (_, mdf_header) = MdfHeader::from_bytes(&mut stream)?;
let mut compressed_buffer = Vec::new();
stream.take(mdf_header.size as u64).read_to_end(&mut compressed_buffer)?;
let mut decoder = ZlibDecoder::new(&compressed_buffer[..]);
let mut buffer = Vec::new();
decoder.read_to_end(&mut buffer)?;
PsbReader::open_psb(Cursor::new(buffer))
}
}