swf: Support SWZ files

This commit is contained in:
EmperorBale 2022-09-23 18:10:24 -07:00 committed by EmperorBale
parent 10c19fef57
commit 5c9bf3ffc0
4 changed files with 53 additions and 1 deletions

23
Cargo.lock generated
View File

@ -2443,6 +2443,17 @@ dependencies = [
"minimal-lexical", "minimal-lexical",
] ]
[[package]]
name = "num-bigint"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]] [[package]]
name = "num-complex" name = "num-complex"
version = "0.4.2" version = "0.4.2"
@ -3507,6 +3518,17 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3"
[[package]]
name = "simple_asn1"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "692ca13de57ce0613a363c8c2f1de925adebc81b04c923ac60c5488bb44abe4b"
dependencies = [
"chrono",
"num-bigint",
"num-traits",
]
[[package]] [[package]]
name = "slab" name = "slab"
version = "0.4.7" version = "0.4.7"
@ -3640,6 +3662,7 @@ dependencies = [
"lzma-rs", "lzma-rs",
"num-derive", "num-derive",
"num-traits", "num-traits",
"simple_asn1",
] ]
[[package]] [[package]]

View File

@ -32,7 +32,7 @@ use ruffle_render::utils::{determine_jpeg_tag_format, JpegTagFormat};
use std::fmt; use std::fmt;
use std::sync::{Arc, Mutex, Weak}; use std::sync::{Arc, Mutex, Weak};
use std::time::Duration; use std::time::Duration;
use swf::read::read_compression_type; use swf::read::{extract_swz, read_compression_type};
use thiserror::Error; use thiserror::Error;
use url::form_urlencoded; use url::form_urlencoded;
@ -1270,6 +1270,11 @@ impl<'gc> Loader<'gc> {
let sniffed_type = ContentType::sniff(data); let sniffed_type = ContentType::sniff(data);
let mut length = data.len(); let mut length = data.len();
if sniffed_type == ContentType::Unknown {
if let Ok(data) = extract_swz(data) {
return Self::movie_loader_data(handle, player, &data, url, loader_url, in_memory);
}
}
player.lock().unwrap().update(|uc| { player.lock().unwrap().update(|uc| {
let (clip, event_handler) = match uc.load_manager.get_loader(handle) { let (clip, event_handler) = match uc.load_manager.get_loader(handle) {
Some(Loader::Movie { Some(Loader::Movie {

View File

@ -21,6 +21,7 @@ log = "0.4"
flate2 = {version = "1.0", optional = true} flate2 = {version = "1.0", optional = true}
lzma-rs = {version = "0.2.0", optional = true } lzma-rs = {version = "0.2.0", optional = true }
enum-map = "2.4.0" enum-map = "2.4.0"
simple_asn1 = "0.4.1"
[features] [features]
default = ["flate2", "lzma"] default = ["flate2", "lzma"]

View File

@ -7,6 +7,7 @@ use crate::{
}; };
use bitstream_io::BitRead; use bitstream_io::BitRead;
use byteorder::{LittleEndian, ReadBytesExt}; use byteorder::{LittleEndian, ReadBytesExt};
use simple_asn1::ASN1Block;
use std::io::{self, Read}; use std::io::{self, Read};
/// Parse a decompressed SWF. /// Parse a decompressed SWF.
@ -28,6 +29,28 @@ pub fn parse_swf(swf_buf: &SwfBuf) -> Result<Swf<'_>> {
}) })
} }
/// Extracts an SWF inside of an SWZ file.
pub fn extract_swz(input: &[u8]) -> Result<Vec<u8>> {
let asn1_blocks =
simple_asn1::from_der(input).map_err(|_| Error::invalid_data("Invalid ASN1 blob"))?;
if let Some(ASN1Block::Sequence(_, s)) = asn1_blocks.into_iter().nth(0) {
for t in s {
if let ASN1Block::Explicit(_, _, _, block) = t {
if let ASN1Block::Sequence(_, s) = *block {
if let Some(ASN1Block::Sequence(_, s)) = s.into_iter().nth(2) {
if let Some(ASN1Block::Explicit(_, _, _, octet)) = s.into_iter().nth(1) {
if let ASN1Block::OctetString(_, bytes) = *octet {
return Ok(bytes);
}
}
}
}
}
}
}
Err(Error::invalid_data("Invalid ASN1 blob"))
}
/// Parses an SWF header and returns a `Reader` that can be used /// Parses an SWF header and returns a `Reader` that can be used
/// to read the SWF tags inside the SWF file. /// to read the SWF tags inside the SWF file.
/// ///