forked from: SWF Analyzer
forked from SWF Analyzer (diff: 150)
やっつけSWF解析
ActionScript3 source code
/**
* Copyright ohisama ( http://wonderfl.net/user/ohisama )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/kaal
*/
// forked from hycro's SWF Analyzer
// やっつけSWF解析
package
{
import com.bit101.components.PushButton;
import com.bit101.components.TextArea;
import flash.display.Sprite;
import flash.events.Event;
import flash.net.FileFilter;
import flash.net.FileReference;
import flash.utils.ByteArray;
[SWF(frameRate="30", width="465", height="465", backgroundColor="0xFFFFFF")]
public class SWFAnalyzerTest extends Sprite
{
private var _ta : TextArea;
private var _fileRef : FileReference;
public function SWFAnalyzerTest()
{
this.addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(evt:Event=null):void
{
new PushButton(this, 5, 5, "load", selectFile);
_ta = new TextArea(this, 0, 30);
_ta.width = stage.stageWidth;
_ta.height = stage.stageHeight - 30;
}
private function selectFile(evt:Event):void
{
_fileRef = new FileReference();
_fileRef.addEventListener(Event.SELECT, onSelect);
_fileRef.addEventListener(Event.COMPLETE, onComplete);
_fileRef.browse([new FileFilter("SWF", "*.swf")]);
}
private function onSelect(evt:Event):void
{
_fileRef.load();
}
private function onComplete(evt:Event):void
{
var analyzer : SWFAnalyzer = new SWFAnalyzer(_fileRef.data);
try
import flash.utils.Endian;
class SWFAnalyzer
{
public var compressed : Boolean;
public var version : uint;
public var filesize : uint;
public var stageRect : Rectangle;
public var frameRate : Number;
public var numFrames : Number;
public var tags : Vector.<Tag>;
private var _data : ByteArray;
public function SWFAnalyzer(data : ByteArray)
{
_data = data;
_data.endian = Endian.LITTLE_ENDIAN;
tags = new Vector.<Tag>();
}
public function analyze() : void
{
readHeader();
if (compressed)
{
_data = uncompless(_data, 8);
_data.position = 8;
}
readHeader2();
readTags();
}
private function readHeader() : void
{
var cmp : String = _data.readUTFBytes(3);
if (cmp == "FWS")
{
this.compressed = false;
}
else if (cmp == "CWS")
{
this.compressed = true;
}
else
{
throw new Error();
}
this.version = _data.readUnsignedByte();
this.filesize = _data.readUnsignedInt();
}
private function readHeader2() : void
{
var bitReader : BitReader = new BitReader(_data);
var len : uint = bitReader.readUnsignedInt(5);
var x : uint = bitReader.readUnsignedInt(len);
var w : uint = bitReader.readUnsignedInt(len);
var y : uint = bitReader.readUnsignedInt(len);
var h : uint = bitReader.readUnsignedInt(len);
stageRect = new Rectangle(x / 20, y / 20, w / 20, h / 20);
var f : uint = _data.readUnsignedByte();
var d : uint = _data.readUnsignedByte();
frameRate = d + (f / 256);
numFrames = _data.readUnsignedShort();
}
private function readTags() : void
{
while (_data.bytesAvailable)
{
var tag : Tag = new Tag();
var typeAndLength : uint = _data.readUnsignedShort();
tag.type = (typeAndLength & 0xFFC0) >> 6;
tag.length = (typeAndLength & 0x3F);
if (tag.length == 0x3F)
{
tag.length = _data.readUnsignedInt();
}
if (tag.length)
{
_data.readBytes(tag.contents, 0, tag.length);
}
tags.push(tag);
}
}
private function uncompless(ba : ByteArray, offset : uint) : ByteArray
{
var rv : ByteArray = new ByteArray();
var tmp : ByteArray = new ByteArray();
rv.endian = ba.endian;
tmp.endian = ba.endian;
ba.position = offset;
ba.readBytes(tmp);
tmp.uncompress();
if (offset == 0)
{
return tmp;
}
ba.position = 0;
ba.readBytes(rv, 0, offset);
tmp.readBytes(rv, offset);
return rv;
}
private function dump(length : uint = 100) : void
{
var pos : uint = _data.position;
var count : uint = 0;
while (_data.bytesAvailable)
{
var str : String = "";
for (var i : uint = 0; i < 16 && _data.bytesAvailable; i++)
{
var b : uint = _data.readUnsignedByte();
for (var j : uint = 0; j < (8-b.toString(2).length); j++)
{
str += "0";
}
str += b.toString(2);
str += " ";
if (++count >= length)
{
trace(str);
_data.position = pos;
return;
}
}
trace(str);
}
_data.position = pos;
}
}
class Tag
{
public var type : uint;
public var length : uint;
public var contents : ByteArray;
public function Tag()
{
contents = new ByteArray();
}
public function toString() : String
{
switch (type)
{
case 0:
return "End";
case 1:
return "ShowFrame";
case 2:
return "DefineShape";
case 4:
return "PlaceObject";
case 5:
return "RemoveObject";
case 6:
return "DefineBits";
case 7:
return "DefineButton";
case 8:
return "JPEGTables";
case 9:
return "SetBackgroundColor";
case 10:
return "DefineFont"
case 11:
return "DefineText"
case 12:
return "DoAction"
case 13:
return "DefineFontInfo"
case 14:
return "DefineSound"
case 15:
return "StartSound"
case 17:
return "DefineButtonSound"
case 18:
return "SoundStreamHead"
case 19:
return "SoundStreamBlock"
case 20:
return "DefineBitsLossless"
case 21:
return "DefineBitsJPEG2"
case 22:
return "DefineShape2"
case 23:
return "DefineButtonCxform"
case 24:
return "Protect"
case 26:
return "PlaceObject2"
case 28:
return "RemoveObject2"
case 32:
return "DefineShape3"
case 33:
return "DefineText2"
case 34:
return "DefineButton2"
case 35:
return "DefineBitsJPEG3"
case 36:
return "DefineBitsLossless2"
case 37:
return "DefineEditText"
case 39:
return "DefineSprite"
case 43:
return "FrameLabel"
case 45:
return "SoundStreamHead2"
case 46:
return "DefineMorphShape"
case 48:
return "DefineFont2"
case 56:
return "ExportAssets"
case 57:
return "ImportAssets"
case 58:
return "EnableDebugger"
case 59:
return "DoInitAction"
case 60:
return "DefineVideoStream"
case 61:
return "VideoFrame"
case 62:
return "DefineFontInfo2"
case 64:
return "EnableDebugger2"
case 65:
return "ScriptLimits"
case 66:
return "SetTabIndex"
case 69:
return "FileAttributes"
case 70:
return "PlaceObject3"
case 71:
return "ImportAssets2"
case 73:
return "DefineFontAlignZones"
case 74:
return "CSMTextSettings"
case 75:
return "DefineFont3"
case 76:
return "SymbolClass"
case 77:
return "Metadata"
case 78:
return "DefineScalingGrid"
case 82:
return "DoABC"
case 83:
return "DefineShape4"
case 84:
return "DefineMorphShape2"
case 86:
return "DefineSceneAndFrameLabelData"
case 87:
return "DefineBinaryData"
case 88:
return "DefineFontName"
case 89:
return "StartSound2"
case 90:
return "DefineBitsJPEG4"
case 91:
return "DefineFont4"
}
return "undefined? (" + type + ")";
}
}
class BitReader
{
private static const ONE : Boolean = true;
private static const ZERO : Boolean = false;
private var _input : ByteArray;
private var _currByte : uint;
private var _mask : uint;
public function BitReader(input : ByteArray)
{
_input = input;
_currByte = NaN;
_mask = 0;
}
public function readUnsignedInt(length : uint = 0) : uint
{
var rv : uint = 0;
length = Math.min(length, 32);
for (var i : int = length - 1; i >= 0; i--)
{
if (next() == ONE)
{
rv += Math.pow(2, i);
}
}
return rv;
}
private function next() : Boolean
{
if ((_mask >>= 1) == 0)
{
_currByte = _input.readUnsignedByte();
_mask = 0x80;
}
return (_currByte & _mask) ? ONE : ZERO;
}
public function floor() : void
{
_mask = 0;
}
}