-
Notifications
You must be signed in to change notification settings - Fork 10
/
swf2lzma.py
executable file
·75 lines (57 loc) · 2.14 KB
/
swf2lzma.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#!/usr/bin/python
import os
import pylzma
import sys
import struct
import zlib
def check(test, msg):
test or exit(msg)
def convert(infile, outfile):
fi = open(infile, "rb")
swf_size = os.path.getsize(infile)
swf_data = fi.read()
fi.close()
check((swf_data[1] == 'W') and (swf_data[2] == 'S'), "not a SWF file")
check((ord(swf_data[3]) >= 13), "only SWF version 13 or higher is supported")
check((swf_data[0] != 'Z'), "already LZMA compressed")
dfilesize = struct.unpack("<I", swf_data[4:8])[0] - 8
if swf_data[0] == 'C':
# compressed SWF
ddata = zlib.decompress(swf_data[8:])
else:
# uncompressed SWF
check((swf_data[0] == 'F'), "not a SWF file")
ddata = swf_data[8:]
check((dfilesize == len(ddata)), 'decompression failure')
zdata = pylzma.compress(ddata, eos=1)
# 5 accounts for lzma props
zsize = len(zdata) - 5
zheader = list(struct.unpack("<12B", swf_data[0:12]))
zheader[0] = ord('Z')
zheader[8] = (zsize) & 0xFF
zheader[9] = (zsize >> 8) & 0xFF
zheader[10] = (zsize >> 16) & 0xFF
zheader[11] = (zsize >> 24) & 0xFF
fo = open(outfile, 'wb')
fo.write(struct.pack("<12B", *zheader))
fo.write(zdata)
fo.close()
print 'compression: %d%%' % round(100 - (100.0 * zsize / swf_size))
# Format of SWF when LZMA is used:
#
# | 4 bytes | 4 bytes | 4 bytes | 5 bytes | n bytes | 6 bytes |
# | 'ZWS'+version | scriptLen | compressedLen | LZMA props | LZMA data | LZMA end marker |
#
# scriptLen is the uncompressed length of the SWF data. Includes 4 bytes SWF header and
# 4 bytes for scriptLen it
#
# compressedLen does not include header (4+4+4 bytes) or lzma props (5 bytes)
# compressedLen does include LZMA end marker (6 bytes)
if __name__ == "__main__":
check((len(sys.argv) == 3), 'usage: swf2lzma input-swf output-swf')
infile = sys.argv[1]
check((infile[-4:].lower() == '.swf'), 'input file must be of type .swf')
outfile = sys.argv[2]
check((infile[-4:].lower() == '.swf'), 'output file must be of type .swf')
convert(infile, outfile)
sys.exit(0)