forked from: SWF Analyzer

by ohisama forked from SWF Analyzer (diff: 150)
やっつけSWF解析
♥0 | Line 350 | Modified 2013-01-31 13:12:56 | MIT License
play

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;
    }
}