mirror of
https://github.com/lifegpc/msg-tool.git
synced 2026-06-10 23:18:47 +08:00
Fix audio and movie unpack issue
This commit is contained in:
@@ -57,3 +57,73 @@ impl<T: std::fmt::Debug> std::fmt::Debug for XoredStream<T> {
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// A stream that XORs data with a repeating key based on the current position.
|
||||
pub struct XoredKeyStream<T> {
|
||||
inner: T,
|
||||
key: Vec<u8>,
|
||||
base_position: u64,
|
||||
}
|
||||
|
||||
impl<T> XoredKeyStream<T> {
|
||||
pub fn new(inner: T, key: Vec<u8>, base_position: u64) -> Self {
|
||||
XoredKeyStream {
|
||||
inner,
|
||||
key,
|
||||
base_position,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Read + Seek> Read for XoredKeyStream<T> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
|
||||
let key_len = self.key.len();
|
||||
let start_pos =
|
||||
((self.inner.stream_position()? + self.base_position) % (key_len as u64)) as usize;
|
||||
let readed = self.inner.read(buf)?;
|
||||
for i in 0..readed {
|
||||
buf[i] ^= self.key[(start_pos + i) % key_len];
|
||||
}
|
||||
Ok(readed)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Seek> Seek for XoredKeyStream<T> {
|
||||
fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> {
|
||||
self.inner.seek(pos)
|
||||
}
|
||||
|
||||
fn rewind(&mut self) -> std::io::Result<()> {
|
||||
self.inner.rewind()
|
||||
}
|
||||
|
||||
fn stream_position(&mut self) -> std::io::Result<u64> {
|
||||
self.inner.stream_position()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Write + Seek> Write for XoredKeyStream<T> {
|
||||
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
|
||||
let key_len = self.key.len();
|
||||
let start_pos =
|
||||
((self.inner.stream_position()? + self.base_position) % (key_len as u64)) as usize;
|
||||
let mut encrypted_buf = buf.to_vec();
|
||||
for i in 0..buf.len() {
|
||||
encrypted_buf[i] ^= self.key[(start_pos + i) % key_len];
|
||||
}
|
||||
self.inner.write(&encrypted_buf)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> std::io::Result<()> {
|
||||
self.inner.flush()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: std::fmt::Debug> std::fmt::Debug for XoredKeyStream<T> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("XoredKeyStream")
|
||||
.field("inner", &self.inner)
|
||||
.field("base_position", &self.base_position)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user