PHP Code:
<?php
/**
* Extraction of tags from SWF file
*
* @author Antoinee <anb505.spam@outlook.fr>
* [MENTION=316612]Version[/MENTION] 0.0-20150804
* [MENTION=585868]Lice[/MENTION]nse [url]http://opensource.org/licenses/MIT[/url] MIT License
*/
define('INPUT_FILE', 'input.swf');
define('OUTPUT_DIRECTORY', './output');
chdir(__DIR__);
function swf_read_DefineBitsLossless2($raw_data) {
// Data length
$data_length = strlen($raw_data) - 7;
// Assuming that BitmapFormat = 5
$tag = unpack('vsymbol_id/Cformat/vwidth/vheight', $raw_data);
$data = gzuncompress(substr($raw_data, 7));
if ($tag['format'] != 5) {
echo "BitmapFormat = {$tag['format']}\tSkip this tag\r\n";
return [];
}
$im = imagecreatetruecolor($tag['width'], $tag['height']);
imagefill($im, 0, 0, 0x7fffffff);
for ($y = 0; $y < $tag['height']; $y++) {
for ($x = 0; $x < $tag['width']; $x++) {
list(, $color) = unpack('N', $data);
$data = substr($data, 4);
imagesetpixel($im, $x, $y, $color);
}
}
$tag['im'] = $im;
return $tag;
}
function swf_read_SymbolClass($raw_data) {
// Read the number of symbols
list(, $number_of_symbols) = unpack('v', substr($raw_data, 0, 2));
$raw_data = substr($raw_data, 2);
// Read all symbols
// for ($symbols = []; count($symbols) < $number_of_symbols; ) {
for ($symbols = []; strlen($raw_data); ) {
extract(unpack('vsymbol_id/Z*symbol_value', $raw_data));
$symbols[$symbol_id] = $symbol_value;
$raw_data = substr($raw_data, 2 + strlen($symbol_value) + 1);
}
return $symbols;
}
function swf_read_DefineBinaryData($raw_data) {
// Data length
$data_length = strlen($raw_data) - 6;
return unpack('vsymbol_id/V/Z' . $data_length . 'data', $raw_data);
}
function swf_extract($swf_file) {
// Read SWF file
$raw_data = file_get_contents($swf_file);
// Uncompress SWF data
if (substr($raw_data, 0, 3) == 'CWS') {
$raw_data = 'F' . substr($raw_data, 1, 7) . gzuncompress(substr($raw_data, 8));
}
// File length
list(, $file_length) = unpack('V', substr($raw_data, 4, 4));
// Header length
$header_length = 8 + 1 + ceil(((ord($raw_data[8]) >> 3) * 4 - 3) / 8) + 4;
// Output arrays
$pngs = [];
$xmls = [];
// Read tags
for ($cursor = $header_length; $cursor < $file_length; ) {
// Read tag header
list(, $tag_header) = unpack('v', substr($raw_data, $cursor, 2));
$cursor += 2;
list($tag_code, $tag_length) = [$tag_header >> 6, $tag_header & 0x3f];
// Read long tag header
if ($tag_length == 0x3f) {
list(, $tag_length) = unpack('V', substr($raw_data, $cursor, 4)); // Must be signed!
$cursor+= 4;
}
// Read tag body
switch ($tag_code) {
// DefineBitsLossless2
case 36:
$tag = swf_read_DefineBitsLossless2(substr($raw_data, $cursor, $tag_length));
$pngs[$tag['symbol_id']] = $tag['im'];
break;
// SymbolClass
case 76:
$symbols = swf_read_SymbolClass(substr($raw_data, $cursor, $tag_length));
break;
// DefineBinaryData
case 87:
$tag = swf_read_DefineBinaryData(substr($raw_data, $cursor, $tag_length));
$xmls[$tag['symbol_id']] = $tag['data'];
break;
}
// Go to the next tag
$cursor+= $tag_length;
// Exit loop if End tag
// $tag_code != 0 ? : break;
}
foreach ($xmls as $symbol_id => $xml) {
$name = isset($symbols[$symbol_id]) ? $symbols[$symbol_id] : 'symbol_' . $symbol_id;
// if (file_exists(OUTPUT_DIRECTORY . '/' .$name . '.xml')) {
// $name.= '_' . substr(md5(microtime(true)), 0, 8);
// echo $name,PHP_EOL;
// }
file_put_contents(OUTPUT_DIRECTORY . '/' . $name . '.xml', $xml);
}
foreach ($pngs as $symbol_id => $png) {
$name = isset($symbols[$symbol_id]) ? $symbols[$symbol_id] : 'symbol_' . $symbol_id;
// if (file_exists(OUTPUT_DIRECTORY . '/' .$name . '.png')) {
// $name.= '_' . substr(md5(microtime(true)), 0, 8);
// echo $name,PHP_EOL;
// }
imagepng($png, OUTPUT_DIRECTORY . '/' . $name . '.png');
}
}
swf_extract(INPUT_FILE);