Simplified filter function and moved to read.rs
Filter now occurs only if SWF fails to parse and re-calls the parse method
This commit is contained in:
parent
a3d3959652
commit
6a3d4017db
|
@ -151,62 +151,15 @@ impl SwfMovie {
|
|||
Self::from_data(&data, url.into(), loader_url)
|
||||
}
|
||||
|
||||
/// Construct a movie based on the contents of a datastream.
|
||||
/// Construct a movie based on the contents of the SWF datastream.
|
||||
pub fn from_data(
|
||||
swf_data: &[u8],
|
||||
url: String,
|
||||
loader_url: Option<String>,
|
||||
) -> Result<Self, Error> {
|
||||
match Self::filter_from_projector_bundle(swf_data) {
|
||||
Some(extracted_swf) => Self::from_swf_data(&extracted_swf, url, loader_url),
|
||||
None => Self::from_swf_data(swf_data, url, loader_url),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get an SWF from data if the data is a swf/projector bundle
|
||||
fn filter_from_projector_bundle(data: &[u8]) -> Option<Vec<u8>> {
|
||||
let len = data.len();
|
||||
if len < 8 {
|
||||
return None;
|
||||
}
|
||||
|
||||
let signature = u32::from_le_bytes(
|
||||
data[len - 8..len - 4]
|
||||
.try_into()
|
||||
.expect("4 bytes make a u32"),
|
||||
);
|
||||
|
||||
if signature != 0xFA123456 {
|
||||
return None;
|
||||
}
|
||||
|
||||
let swf_size = usize::try_from(u32::from_le_bytes(
|
||||
data[len - 4..len].try_into().expect("4 bytes make a u32"),
|
||||
))
|
||||
.expect("size should be at least 32 bits");
|
||||
|
||||
if swf_size > len - 8 {
|
||||
//catch possible overflow
|
||||
return None;
|
||||
}
|
||||
|
||||
let offset = len - swf_size - 8;
|
||||
let mut swf_data = Vec::with_capacity(swf_size);
|
||||
for i in 0..swf_size {
|
||||
swf_data.push(data[i + offset]);
|
||||
}
|
||||
|
||||
Some(swf_data)
|
||||
}
|
||||
|
||||
/// Construct a movie based on the contents of the SWF datastream.
|
||||
fn from_swf_data(
|
||||
swf_data: &[u8],
|
||||
url: String,
|
||||
loader_url: Option<String>,
|
||||
) -> Result<Self, Error> {
|
||||
let compressed_len = swf_data.len();
|
||||
let swf_buf = swf::read::decompress_swf(swf_data)?;
|
||||
let swf_buf = swf::read::decompress_swf(swf_data)
|
||||
.or_else(|_| swf::read::decompress_projector_bundle(swf_data))?;
|
||||
let encoding = swf::SwfStr::encoding_for_version(swf_buf.header.version());
|
||||
let mut movie = Self {
|
||||
header: swf_buf.header,
|
||||
|
|
|
@ -52,6 +52,33 @@ pub fn extract_swz(input: &[u8]) -> Result<Vec<u8>> {
|
|||
Err(Error::invalid_data("Invalid ASN1 blob"))
|
||||
}
|
||||
|
||||
/// Parses an SWF from data in an SWF projector bundle
|
||||
/// Returns an `Error` if this is not a valid SWF projector bundle.
|
||||
pub fn decompress_projector_bundle(data: &[u8]) -> Result<SwfBuf> {
|
||||
let len = data.len();
|
||||
if len < 8 {
|
||||
return Err(Error::invalid_data("Invalid SWF projector bundle data"));
|
||||
}
|
||||
if data[len - 8..len - 4] != [0x56, 0x34, 0x12, 0xFA] {
|
||||
return Err(Error::invalid_data(
|
||||
"Invalid SWF projector bundle signature",
|
||||
));
|
||||
}
|
||||
|
||||
let swf_size = u32::from_le_bytes(
|
||||
data[len - 4..]
|
||||
.try_into()
|
||||
.unwrap_or([0xFF, 0xFF, 0xFF, 0xFF]),
|
||||
) as usize;
|
||||
|
||||
if swf_size > len - 8 {
|
||||
//catch possible overflow
|
||||
return Err(Error::invalid_data("Invalid SWF projector bundle size"));
|
||||
}
|
||||
|
||||
decompress_swf(&data[len - 8 - swf_size..len - 8])
|
||||
}
|
||||
|
||||
/// Parses an SWF header and returns a `Reader` that can be used
|
||||
/// to read the SWF tags inside the SWF file.
|
||||
///
|
||||
|
|
Loading…
Reference in New Issue