refactor: make LZMA support an optional feature
This commit is contained in:
parent
120f94711a
commit
5a0e7a8fd3
|
@ -14,7 +14,8 @@ byteorder = "1.0"
|
||||||
flate2 = "1.0"
|
flate2 = "1.0"
|
||||||
num-derive = "0.2"
|
num-derive = "0.2"
|
||||||
num-traits = "0.2"
|
num-traits = "0.2"
|
||||||
xz2 = "0.1.5"
|
xz2 = {version = "0.1.5", optional = true}
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
|
lzma-support = ["xz2"]
|
|
@ -14,6 +14,7 @@ extern crate flate2;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate num_derive;
|
extern crate num_derive;
|
||||||
extern crate num_traits;
|
extern crate num_traits;
|
||||||
|
#[cfg(feature = "lzma-support")]
|
||||||
extern crate xz2;
|
extern crate xz2;
|
||||||
|
|
||||||
pub mod avm1;
|
pub mod avm1;
|
||||||
|
|
53
src/read.rs
53
src/read.rs
|
@ -5,7 +5,6 @@ use flate2::read::ZlibDecoder;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::io::{Error, ErrorKind, Read, Result};
|
use std::io::{Error, ErrorKind, Read, Result};
|
||||||
use types::*;
|
use types::*;
|
||||||
use xz2::read::XzDecoder;
|
|
||||||
|
|
||||||
/// Reads SWF data from a stream.
|
/// Reads SWF data from a stream.
|
||||||
pub fn read_swf<R: Read>(input: R) -> Result<Swf> {
|
pub fn read_swf<R: Read>(input: R) -> Result<Swf> {
|
||||||
|
@ -24,22 +23,7 @@ fn read_swf_header<'a, R: Read + 'a>(mut input: R) -> Result<(Swf, Reader<Box<Re
|
||||||
let decompressed_input: Box<Read> = match compression {
|
let decompressed_input: Box<Read> = match compression {
|
||||||
Compression::None => Box::new(input),
|
Compression::None => Box::new(input),
|
||||||
Compression::Zlib => Box::new(ZlibDecoder::new(input)),
|
Compression::Zlib => Box::new(ZlibDecoder::new(input)),
|
||||||
Compression::Lzma => {
|
Compression::Lzma => make_lzma_reader(input)?,
|
||||||
// Flash uses a mangled LZMA header, so we have to massage it into the normal
|
|
||||||
// format.
|
|
||||||
use std::io::{Cursor, Write};
|
|
||||||
use xz2::stream::{Action, Stream};
|
|
||||||
use byteorder::WriteBytesExt;
|
|
||||||
input.read_u32::<LittleEndian>()?; // Compressed length
|
|
||||||
let mut lzma_properties = [0u8; 5];
|
|
||||||
input.read_exact(&mut lzma_properties)?;
|
|
||||||
let mut lzma_header = Cursor::new(Vec::with_capacity(13));
|
|
||||||
lzma_header.write_all(&lzma_properties)?;
|
|
||||||
lzma_header.write_u64::<LittleEndian>(uncompressed_length as u64)?;
|
|
||||||
let mut lzma_stream = Stream::new_lzma_decoder(u64::max_value())?;
|
|
||||||
lzma_stream.process(&lzma_header.into_inner(), &mut [0u8; 1], Action::Run)?;
|
|
||||||
Box::new(XzDecoder::new_stream(input, lzma_stream))
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut reader = Reader::new(decompressed_input, version);
|
let mut reader = Reader::new(decompressed_input, version);
|
||||||
|
@ -57,6 +41,29 @@ fn read_swf_header<'a, R: Read + 'a>(mut input: R) -> Result<(Swf, Reader<Box<Re
|
||||||
Ok((swf, reader))
|
Ok((swf, reader))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "lzma-support")]
|
||||||
|
fn make_lzma_reader<'a, R: Read + 'a>(mut input: R) -> Result<Box<Read + 'a>> {
|
||||||
|
// Flash uses a mangled LZMA header, so we have to massage it into the normal
|
||||||
|
// format.
|
||||||
|
use std::io::{Cursor, Write};
|
||||||
|
use xz2::stream::{Action, Stream};
|
||||||
|
use byteorder::WriteBytesExt;
|
||||||
|
input.read_u32::<LittleEndian>()?; // Compressed length
|
||||||
|
let mut lzma_properties = [0u8; 5];
|
||||||
|
input.read_exact(&mut lzma_properties)?;
|
||||||
|
let mut lzma_header = Cursor::new(Vec::with_capacity(13));
|
||||||
|
lzma_header.write_all(&lzma_properties)?;
|
||||||
|
lzma_header.write_u64::<LittleEndian>(uncompressed_length as u64)?;
|
||||||
|
let mut lzma_stream = Stream::new_lzma_decoder(u64::max_value())?;
|
||||||
|
lzma_stream.process(&lzma_header.into_inner(), &mut [0u8; 1], Action::Run)?;
|
||||||
|
Box::new(XzDecoder::new_stream(input, lzma_stream))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "lzma-support"))]
|
||||||
|
fn make_lzma_reader<'a, R: Read + 'a>(_: R) -> Result<Box<Read + 'a>> {
|
||||||
|
Err(Error::new(ErrorKind::InvalidData, "Support for LZMA compressed SWFs is not enabled."))
|
||||||
|
}
|
||||||
|
|
||||||
pub trait SwfRead<R: Read> {
|
pub trait SwfRead<R: Read> {
|
||||||
fn get_inner(&mut self) -> &mut R;
|
fn get_inner(&mut self) -> &mut R;
|
||||||
|
|
||||||
|
@ -409,7 +416,7 @@ impl<R: Read> Reader<R> {
|
||||||
|
|
||||||
fn read_tag(&mut self) -> Result<Option<Tag>> {
|
fn read_tag(&mut self) -> Result<Option<Tag>> {
|
||||||
use num_traits::FromPrimitive;
|
use num_traits::FromPrimitive;
|
||||||
|
|
||||||
let (tag_code, length) = self.read_tag_code_and_length()?;
|
let (tag_code, length) = self.read_tag_code_and_length()?;
|
||||||
|
|
||||||
let mut tag_reader = Reader::new(self.input.by_ref().take(length as u64), self.version);
|
let mut tag_reader = Reader::new(self.input.by_ref().take(length as u64), self.version);
|
||||||
|
@ -2669,10 +2676,12 @@ pub mod tests {
|
||||||
read_from_file("tests/swfs/zlib.swf").compression,
|
read_from_file("tests/swfs/zlib.swf").compression,
|
||||||
Compression::Zlib
|
Compression::Zlib
|
||||||
);
|
);
|
||||||
assert_eq!(
|
if cfg!(feature = "lzma-support") {
|
||||||
read_from_file("tests/swfs/lzma.swf").compression,
|
assert_eq!(
|
||||||
Compression::Lzma
|
read_from_file("tests/swfs/lzma.swf").compression,
|
||||||
);
|
Compression::Lzma
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
43
src/write.rs
43
src/write.rs
|
@ -9,7 +9,6 @@ use std::collections::HashSet;
|
||||||
use std::io::{Error, ErrorKind, Result, Write};
|
use std::io::{Error, ErrorKind, Result, Write};
|
||||||
use tag_codes::TagCode;
|
use tag_codes::TagCode;
|
||||||
use types::*;
|
use types::*;
|
||||||
use xz2::write::XzEncoder;
|
|
||||||
|
|
||||||
pub fn write_swf<W: Write>(swf: &Swf, mut output: W) -> Result<()> {
|
pub fn write_swf<W: Write>(swf: &Swf, mut output: W) -> Result<()> {
|
||||||
let signature = match swf.compression {
|
let signature = match swf.compression {
|
||||||
|
@ -52,22 +51,32 @@ pub fn write_swf<W: Write>(swf: &Swf, mut output: W) -> Result<()> {
|
||||||
// SWF format has a mangled LZMA header, so we have to do some magic to conver the
|
// SWF format has a mangled LZMA header, so we have to do some magic to conver the
|
||||||
// standard LZMA header to SWF format.
|
// standard LZMA header to SWF format.
|
||||||
// https://adobe.ly/2s8oYzn
|
// https://adobe.ly/2s8oYzn
|
||||||
Compression::Lzma => {
|
Compression::Lzma => write_lzma_swf(&mut output)?,
|
||||||
use xz2::stream::{Action, LzmaOptions, Stream};
|
|
||||||
let mut stream = Stream::new_lzma_encoder(&LzmaOptions::new_preset(9)?)?;
|
|
||||||
let mut lzma_header = [0; 13];
|
|
||||||
stream.process(&[], &mut lzma_header, Action::Run)?;
|
|
||||||
// Compressed length. We just write out a dummy value.
|
|
||||||
output.write_u32::<LittleEndian>(0xffffffff)?;
|
|
||||||
output.write_all(&lzma_header[0..5])?; // LZMA property bytes.
|
|
||||||
let mut encoder = XzEncoder::new_stream(&mut output, stream);
|
|
||||||
encoder.write_all(&swf_body)?;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "lzma-support")]
|
||||||
|
fn write_lzma_swf<W: Write>(mut output: W) -> Result<()> {
|
||||||
|
use xz2::write::XzEncoder;
|
||||||
|
use xz2::stream::{Action, LzmaOptions, Stream};
|
||||||
|
let mut stream = Stream::new_lzma_encoder(&LzmaOptions::new_preset(9)?)?;
|
||||||
|
let mut lzma_header = [0; 13];
|
||||||
|
stream.process(&[], &mut lzma_header, Action::Run)?;
|
||||||
|
// Compressed length. We just write out a dummy value.
|
||||||
|
output.write_u32::<LittleEndian>(0xffffffff)?;
|
||||||
|
output.write_all(&lzma_header[0..5])?; // LZMA property bytes.
|
||||||
|
let mut encoder = XzEncoder::new_stream(&mut output, stream);
|
||||||
|
encoder.write_all(&swf_body)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "lzma-support"))]
|
||||||
|
fn write_lzma_swf<W: Write>(_: W) -> Result<()> {
|
||||||
|
Err(Error::new(ErrorKind::InvalidData, "Support for LZMA compressed SWFs is not enabled."))
|
||||||
|
}
|
||||||
|
|
||||||
pub trait SwfWrite<W: Write> {
|
pub trait SwfWrite<W: Write> {
|
||||||
fn get_inner(&mut self) -> &mut W;
|
fn get_inner(&mut self) -> &mut W;
|
||||||
|
|
||||||
|
@ -2691,10 +2700,12 @@ mod tests {
|
||||||
write_dummy_swf(Compression::Zlib).is_ok(),
|
write_dummy_swf(Compression::Zlib).is_ok(),
|
||||||
"Failed to write zlib SWF."
|
"Failed to write zlib SWF."
|
||||||
);
|
);
|
||||||
assert!(
|
if cfg!(feature = "lzma-support") {
|
||||||
write_dummy_swf(Compression::Lzma).is_ok(),
|
assert!(
|
||||||
"Failed to write LZMA SWF."
|
write_dummy_swf(Compression::Lzma).is_ok(),
|
||||||
);
|
"Failed to write LZMA SWF."
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Reference in New Issue