#!/usr/bin/perl -w # # Example 8-1. SWFAnalyze use strict; my %tags = ( 0 => 'End', 1 => 'ShowFrame', 2 => 'DefineShape', 3 => 'FreeCharacter', 4 => 'PlaceObject', 5 => 'RemoveObject', 6 => 'DefineBits', 7 => 'DefineButton', 8 => 'JPEGTables', 9 => 'SetBackgroundColor', 10 => 'DefineFont', 11 => 'DefineText', 12 => 'DoAction', 13 => 'DefineFontInfo', 14 => 'DefineSound', 15 => 'StartSound', 17 => 'DefineButtonSound', 18 => 'SoundStreamHead', 19 => 'SoundStreamBlock', 20 => 'DefineBitsLossless', 21 => 'DefineBitsJPEG2', 22 => 'DefineShape2', 23 => 'DefineButtonCxform', 24 => 'Protect', 26 => 'PlaceObject2', 28 => 'RemoveObject2', 32 => 'DefineShape3', 33 => 'DefineText2', 34 => 'DefineButton2', 35 => 'DefineBitsJPEG3', 36 => 'DefineBitsLossless2', 37 => 'DefineEditText', 39 => 'DefineSprite', 40 => 'NameCharacter', 43 => 'FrameLabel', 45 => 'SoundStreamHead2', 46 => 'DefineMorphShape', 48 => 'DefineFont2' ); my $filename = shift; unless (defined($filename)) { die "Please provide the name of an SWF file.\n"; } open(SWF, $filename) or die "Couldn't open $filename: $!\n"; binmode(SWF); $/ = undef; my $buffer = ; $buffer = unpack("B".(length($buffer)*8), $buffer); my $pos = 0; my $frames = 0; my $signature = chr(read_ui8()). chr(read_ui8()). chr(read_ui8()); my $version = read_ui8(); my $file_length = read_ui32(); my @frame_size = read_rect(); my $frame_rate = read_ui16() >> 8; my $frame_count = read_ui16(); print "Header Information\n"; print "Signature/Version: $signature$version\n"; print "File length: $file_length bytes\n"; print "Min X: $frame_size[0] twips\n"; print "Max X: $frame_size[1] twips\n"; print "Min Y: $frame_size[2] twips\n"; print "Max Y: $frame_size[3] twips\n"; print "Frame rate: $frame_rate\n"; print "Frame count: $frame_count\n"; print "\n"; while ($pos < length($buffer)) { my $code = read_ui16(); # Read the tag code my $id = $code >> 6; # Extract the tag id my $length = $code & 0x3f; # and the length if ($length == 63) { $length = read_ui32(); # A Long tag; the length is in the next 32 bits } if (defined($tags{$id})) { print "Tag type: $tags{$id} ($length bytes)\n"; } else { print "Unidentified tag: $id ($length bytes)\n"; } if ($id == 1) { $frames++; } $pos += $length*8; # Skip remainder } print "Number of frames: $frames\n"; exit; sub get_bits { my $nbits = shift; my $bits = substr($buffer, $pos, $nbits) or die "Premature end of file!\n"; $pos += $nbits; return $bits; } sub move_to_byte_start { if ($pos % 8) { $pos += 8-($pos % 8); } } sub read_ui8 { move_to_byte_start(); # This type is byte-aligned my $ui8 = ord(pack("B8", get_bits(8))); return $ui8; } sub read_ui16 { move_to_byte_start(); # This type is byte-aligned my $ui16 = unpack("v", pack("B16", get_bits(16))); # Short, little-endian return $ui16; } sub read_ui32 { move_to_byte_start(); # This type is byte-aligned my $ui32 = unpack("V", pack("B32", get_bits(32))); # Long, little-endian return $ui32; } sub read_rect { my $nbits = ord(pack("B8", "000".get_bits(5))); my $pad = '0'x(32-$nbits); # Pad each of the values out to 32 bits my @rect = (); for (my $i=0; $i<4; $i++) { push @rect, unpack("N",pack("B32", # big-endian byte order $pad.get_bits($nbits))); } return (@rect); }