Skip to content

Instantly share code, notes, and snippets.

@Yasushi
Created May 20, 2014 13:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Yasushi/f4fba89603196e388396 to your computer and use it in GitHub Desktop.
Save Yasushi/f4fba89603196e388396 to your computer and use it in GitHub Desktop.
package main
import (
"bufio"
"bytes"
"compress/zlib"
"encoding/binary"
"io/ioutil"
"log"
"os"
)
func readString(r *bufio.Reader) (s string, err error) {
if bytes, e := r.ReadBytes(0); e != nil {
err = e
return
} else {
s = string(bytes[:len(bytes)-1])
return
}
}
func newReader(signature byte, raw []byte) (*bufio.Reader, error) {
switch signature {
case 'C':
zr, err := zlib.NewReader(bytes.NewReader(raw))
if err != nil {
return nil, err
}
return bufio.NewReader(zr), nil
default:
return bufio.NewReader(bytes.NewReader(raw)), nil
}
}
type DefineBinaryData struct {
tag uint16
reserved uint32
data []byte
}
type ExportAsset struct {
id uint16
name string
}
type Rect struct {
nbits byte
xy []byte
}
type Swf struct {
signature byte
frameSize Rect
frameRate uint16
frameCount uint16
binaryData map[uint16]DefineBinaryData
exportAssets map[string]ExportAsset
}
func main() {
data, err := ioutil.ReadFile(os.Args[1])
if err != nil {
log.Panic(err)
}
r, err := newReader(data[0], data[8:])
if err != nil {
log.Panic(err)
}
var swf Swf
swf.signature = data[0]
// frameSize
if err := binary.Read(r, binary.LittleEndian, &swf.frameSize.nbits); err != nil {
log.Panic(err)
}
swf.frameSize.xy = make([]byte, ((swf.frameSize.nbits>>3)*4-3+8)/8)
if err := binary.Read(r, binary.LittleEndian, &swf.frameSize.xy); err != nil {
log.Panic(err)
}
if err := binary.Read(r, binary.LittleEndian, &swf.frameRate); err != nil {
log.Panic(err)
}
if err := binary.Read(r, binary.LittleEndian, &swf.frameCount); err != nil {
log.Panic(err)
}
//log.Printf("header %+v", swf)
swf.binaryData = make(map[uint16]DefineBinaryData)
// tags
Loop:
for {
var i uint16
if err := binary.Read(r, binary.LittleEndian, &i); err != nil {
log.Panic(err)
}
tag := i >> 6
length := uint32(i & 0x3f)
if length == 0x3f {
if err := binary.Read(r, binary.LittleEndian, &length); err != nil {
log.Panic(err)
}
}
switch tag {
case 0: // End
//log.Printf("End")
break Loop
case 56, 76: // exportAssets, SymbolClass
var count uint16
if err := binary.Read(r, binary.LittleEndian, &count); err != nil {
log.Panic(err)
}
swf.exportAssets = make(map[string]ExportAsset, count)
for ; count > 0; count-- {
var aid uint16
if err := binary.Read(r, binary.LittleEndian, &aid); err != nil {
log.Panic(err)
}
aname, err := readString(r)
if err != nil {
log.Panic(err)
}
swf.exportAssets[aname] = ExportAsset{aid, aname}
}
//prefix := "ExportAssets"
//if tag == 76 {
// prefix = "SymbolClass"
//}
//log.Printf("%s: %v", prefix, swf.exportAssets)
case 87: // DefineBinaryData
var tag uint16
if err := binary.Read(r, binary.LittleEndian, &tag); err != nil {
log.Panic(err)
}
var reserved uint32
if err := binary.Read(r, binary.LittleEndian, &reserved); err != nil {
log.Panic(err)
}
bindata := make([]byte, length-6)
if err := binary.Read(r, binary.LittleEndian, &bindata); err != nil {
log.Panic(err)
}
swf.binaryData[tag] = DefineBinaryData{tag, reserved, bindata}
default:
body := make([]byte, length)
if err := binary.Read(r, binary.LittleEndian, &body); err != nil {
log.Panic(err)
}
//log.Printf("Tag %d, Length %d", tag, length)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment