stream.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. import struct, math
  2. from .data import *
  3. from .actions import *
  4. from .filters import SWFFilterFactory
  5. from functools import reduce
  6. class SWFStream(object):
  7. """
  8. SWF File stream
  9. """
  10. FLOAT16_EXPONENT_BASE = 15
  11. def __init__(self, file):
  12. """ Initialize with a file object """
  13. self.f = file
  14. self._bits_pending = 0
  15. self._partial_byte = None
  16. self._make_masks()
  17. def bin(self, s):
  18. """ Return a value as a binary string """
  19. return str(s) if s<=1 else bin(s>>1) + str(s&1)
  20. def calc_max_bits(self, signed, values):
  21. """ Calculates the maximim needed bits to represent a value """
  22. b = 0
  23. vmax = -10000000
  24. for val in values:
  25. if signed:
  26. b = b | val if val >= 0 else b | ~val << 1
  27. vmax = val if vmax < val else vmax
  28. else:
  29. b |= val;
  30. bits = 0
  31. if b > 0:
  32. bits = len(self.bin(b)) - 2
  33. if signed and vmax > 0 and len(self.bin(vmax)) - 2 >= bits:
  34. bits += 1
  35. return bits
  36. def close(self):
  37. """ Closes the stream """
  38. if self.f:
  39. self.f.close()
  40. def _make_masks(self):
  41. self._masks = [(1 << x) - 1 for x in range(9)]
  42. def _read_bytes_aligned(self, bytes):
  43. buf = self.f.read(bytes)
  44. return reduce(lambda x, y: x << 8 | ord(chr(y)), buf, 0)
  45. def readbits(self, bits):
  46. """
  47. Read the specified number of bits from the stream.
  48. Returns 0 for bits == 0.
  49. """
  50. if bits == 0:
  51. return 0
  52. # fast byte-aligned path
  53. if bits % 8 == 0 and self._bits_pending == 0:
  54. return self._read_bytes_aligned(bits // 8)
  55. out = 0
  56. masks = self._masks
  57. def transfer_bits(x, y, n, t):
  58. """
  59. transfers t bits from the top of y_n to the bottom of x.
  60. then returns x and the remaining bits in y
  61. """
  62. if n == t:
  63. # taking all
  64. return (x << t) | y, 0
  65. mask = masks[t] # (1 << t) - 1
  66. remainmask = masks[n - t] # (1 << n - t) - 1
  67. taken = ((y >> n - t) & mask)
  68. return (x << t) | taken, y & remainmask
  69. while bits > 0:
  70. if self._bits_pending > 0:
  71. assert self._partial_byte is not None
  72. take = min(self._bits_pending, bits)
  73. out, self._partial_byte = transfer_bits(out, self._partial_byte, self._bits_pending, take)
  74. if take == self._bits_pending:
  75. # we took them all
  76. self._partial_byte = None
  77. self._bits_pending -= take
  78. bits -= take
  79. continue
  80. r = self.f.read(1)
  81. if r == '':
  82. raise EOFError
  83. self._partial_byte = ord(r)
  84. self._bits_pending = 8
  85. return out
  86. def readFB(self, bits):
  87. """ Read a float using the specified number of bits """
  88. return float(self.readSB(bits)) / 65536.0
  89. def readSB(self, bits):
  90. """ Read a signed int using the specified number of bits """
  91. shift = 32 - bits
  92. return int32(self.readbits(bits) << shift) >> shift
  93. def readUB(self, bits):
  94. """ Read a unsigned int using the specified number of bits """
  95. return self.readbits(bits)
  96. def readSI8(self):
  97. """ Read a signed byte """
  98. self.reset_bits_pending();
  99. return struct.unpack('b', self.f.read(1))[0]
  100. def readUI8(self):
  101. """ Read a unsigned byte """
  102. self.reset_bits_pending();
  103. return struct.unpack('B', self.f.read(1))[0]
  104. def readSI16(self):
  105. """ Read a signed short """
  106. self.reset_bits_pending();
  107. return struct.unpack('h', self.f.read(2))[0]
  108. def readUI16(self):
  109. """ Read a unsigned short """
  110. self.reset_bits_pending();
  111. return struct.unpack('H', self.f.read(2))[0]
  112. def readSI32(self):
  113. """ Read a signed int """
  114. self.reset_bits_pending();
  115. return struct.unpack('<i', self.f.read(4))[0]
  116. def readUI32(self):
  117. """ Read a unsigned int """
  118. self.reset_bits_pending();
  119. return struct.unpack('<I', self.f.read(4))[0]
  120. def readUI64(self):
  121. """ Read a uint64_t """
  122. self.reset_bits_pending();
  123. return struct.unpack('<Q', self.f.read(8))[0]
  124. def readEncodedU32(self):
  125. """ Read a encoded unsigned int """
  126. self.reset_bits_pending();
  127. result = self.readUI8();
  128. if result & 0x80 != 0:
  129. result = (result & 0x7f) | (self.readUI8() << 7)
  130. if result & 0x4000 != 0:
  131. result = (result & 0x3fff) | (self.readUI8() << 14)
  132. if result & 0x200000 != 0:
  133. result = (result & 0x1fffff) | (self.readUI8() << 21)
  134. if result & 0x10000000 != 0:
  135. result = (result & 0xfffffff) | (self.readUI8() << 28)
  136. return result
  137. def readFLOAT(self):
  138. """ Read a float """
  139. self.reset_bits_pending();
  140. return struct.unpack('f', self.f.read(4))[0]
  141. def readFLOAT16(self):
  142. """ Read a 2 byte float """
  143. self.reset_bits_pending()
  144. word = self.readUI16()
  145. sign = -1 if ((word & 0x8000) != 0) else 1
  146. exponent = (word >> 10) & 0x1f
  147. significand = word & 0x3ff
  148. if exponent == 0:
  149. if significand == 0:
  150. return 0.0
  151. else:
  152. return sign * math.pow(2, 1 - SWFStream.FLOAT16_EXPONENT_BASE) * (significand / 1024.0)
  153. if exponent == 31:
  154. if significand == 0:
  155. return float('-inf') if sign < 0 else float('inf')
  156. else:
  157. return float('nan')
  158. # normal number
  159. return sign * math.pow(2, exponent - SWFStream.FLOAT16_EXPONENT_BASE) * (1 + significand / 1024.0)
  160. def readFIXED(self):
  161. """ Read a 16.16 fixed value """
  162. self.reset_bits_pending()
  163. return self.readSI32() / 65536.0
  164. def readFIXED8(self):
  165. """ Read a 8.8 fixed value """
  166. self.reset_bits_pending()
  167. return self.readSI16() / 256.0
  168. def readCXFORM(self):
  169. """ Read a SWFColorTransform """
  170. return SWFColorTransform(self)
  171. def readCXFORMWITHALPHA(self):
  172. """ Read a SWFColorTransformWithAlpha """
  173. return SWFColorTransformWithAlpha(self)
  174. def readGLYPHENTRY(self, glyphBits, advanceBits):
  175. """ Read a SWFGlyphEntry """
  176. return SWFGlyphEntry(self, glyphBits, advanceBits)
  177. def readGRADIENT(self, level=1):
  178. """ Read a SWFGradient """
  179. return SWFGradient(self, level)
  180. def readFOCALGRADIENT(self, level=1):
  181. """ Read a SWFFocalGradient """
  182. return SWFFocalGradient(self, level)
  183. def readGRADIENTRECORD(self, level=1):
  184. """ Read a SWFColorTransformWithAlpha """
  185. return SWFGradientRecord(self, level)
  186. def readKERNINGRECORD(self, wideCodes):
  187. """ Read a SWFKerningRecord """
  188. return SWFKerningRecord(self, wideCodes)
  189. def readLANGCODE(self):
  190. """ Read a language code """
  191. self.reset_bits_pending()
  192. return self.readUI8()
  193. def readMATRIX(self):
  194. """ Read a SWFMatrix """
  195. return SWFMatrix(self)
  196. def readRECT(self):
  197. """ Read a SWFMatrix """
  198. r = SWFRectangle()
  199. r.parse(self)
  200. return r
  201. def readSHAPE(self, unit_divisor=20):
  202. """ Read a SWFShape """
  203. return SWFShape(self, 1, unit_divisor)
  204. def readSHAPEWITHSTYLE(self, level=1, unit_divisor=20):
  205. """ Read a SWFShapeWithStyle """
  206. return SWFShapeWithStyle(self, level, unit_divisor)
  207. def readCURVEDEDGERECORD(self, num_bits):
  208. """ Read a SWFShapeRecordCurvedEdge """
  209. return SWFShapeRecordCurvedEdge(self, num_bits)
  210. def readSTRAIGHTEDGERECORD(self, num_bits):
  211. """ Read a SWFShapeRecordStraightEdge """
  212. return SWFShapeRecordStraightEdge(self, num_bits)
  213. def readSTYLECHANGERECORD(self, states, fill_bits, line_bits, level = 1):
  214. """ Read a SWFShapeRecordStyleChange """
  215. return SWFShapeRecordStyleChange(self, states, fill_bits, line_bits, level)
  216. def readFILLSTYLE(self, level=1):
  217. """ Read a SWFFillStyle """
  218. return SWFFillStyle(self, level)
  219. def readTEXTRECORD(self, glyphBits, advanceBits, previousRecord=None, level=1):
  220. """ Read a SWFTextRecord """
  221. if self.readUI8() == 0:
  222. return None
  223. else:
  224. self.seek(self.tell() - 1)
  225. return SWFTextRecord(self, glyphBits, advanceBits, previousRecord, level)
  226. def readLINESTYLE(self, level=1):
  227. """ Read a SWFLineStyle """
  228. return SWFLineStyle(self, level)
  229. def readLINESTYLE2(self, level=1):
  230. """ Read a SWFLineStyle2 """
  231. return SWFLineStyle2(self, level)
  232. def readMORPHFILLSTYLE(self, level=1):
  233. """ Read a SWFMorphFillStyle """
  234. return SWFMorphFillStyle(self, level)
  235. def readMORPHLINESTYLE(self, level=1):
  236. """ Read a SWFMorphLineStyle """
  237. return SWFMorphLineStyle(self, level)
  238. def readMORPHLINESTYLE2(self, level=1):
  239. """ Read a SWFMorphLineStyle2 """
  240. return SWFMorphLineStyle2(self, level)
  241. def readMORPHGRADIENT(self, level=1):
  242. """ Read a SWFTextRecord """
  243. return SWFMorphGradient(self, level)
  244. def readMORPHGRADIENTRECORD(self):
  245. """ Read a SWFTextRecord """
  246. return SWFMorphGradientRecord(self)
  247. def readACTIONRECORD(self):
  248. """ Read a SWFActionRecord """
  249. action = None
  250. actionCode = self.readUI8()
  251. if actionCode != 0:
  252. actionLength = self.readUI16() if actionCode >= 0x80 else 0
  253. #print "0x%x"%actionCode, actionLength
  254. action = SWFActionFactory.create(actionCode, actionLength)
  255. action.parse(self)
  256. return action
  257. def readACTIONRECORDs(self):
  258. """ Read zero or more button records (zero-terminated) """
  259. out = []
  260. while 1:
  261. action = self.readACTIONRECORD()
  262. if action:
  263. out.append(action)
  264. else:
  265. break
  266. return out
  267. def readCLIPACTIONS(self, version):
  268. """ Read a SWFClipActions """
  269. return SWFClipActions(self, version)
  270. def readCLIPACTIONRECORD(self, version):
  271. """ Read a SWFClipActionRecord """
  272. pos = self.tell()
  273. flags = self.readUI32() if version >= 6 else self.readUI16()
  274. if flags == 0:
  275. return None
  276. else:
  277. self.seek(pos)
  278. return SWFClipActionRecord(self, version)
  279. def readCLIPEVENTFLAGS(self, version):
  280. """ Read a SWFClipEventFlags """
  281. return SWFClipEventFlags(self, version)
  282. def readRGB(self):
  283. """ Read a RGB color """
  284. self.reset_bits_pending();
  285. r = self.readUI8()
  286. g = self.readUI8()
  287. b = self.readUI8()
  288. return (0xff << 24) | (r << 16) | (g << 8) | b
  289. def readRGBA(self):
  290. """ Read a RGBA color """
  291. self.reset_bits_pending();
  292. r = self.readUI8()
  293. g = self.readUI8()
  294. b = self.readUI8()
  295. a = self.readUI8()
  296. return (a << 24) | (r << 16) | (g << 8) | b
  297. def readSYMBOL(self):
  298. """ Read a SWFSymbol """
  299. return SWFSymbol(self)
  300. def readString(self):
  301. """ Read a string """
  302. s = self.f.read(1)
  303. string = ""
  304. while ord(s) > 0:
  305. string += str(s)
  306. s = self.f.read(1)
  307. return string
  308. def readFILTER(self):
  309. """ Read a SWFFilter """
  310. filterId = self.readUI8()
  311. filter = SWFFilterFactory.create(filterId)
  312. filter.parse(self)
  313. return filter
  314. def readFILTERLIST(self):
  315. """ Read a length-prefixed list of FILTERs """
  316. number = self.readUI8()
  317. return [self.readFILTER() for _ in range(number)]
  318. def readZONEDATA(self):
  319. """ Read a SWFZoneData """
  320. return SWFZoneData(self)
  321. def readZONERECORD(self):
  322. """ Read a SWFZoneRecord """
  323. return SWFZoneRecord(self)
  324. def readSOUNDINFO(self):
  325. """ Read a SWFSoundInfo """
  326. return SWFSoundInfo(self)
  327. def readSOUNDENVELOPE(self):
  328. """ Read a SWFSoundEnvelope """
  329. return SWFSoundEnvelope(self)
  330. def readBUTTONRECORD(self, version):
  331. rc = SWFButtonRecord(data = self, version = version)
  332. return rc if rc.valid else None
  333. def readBUTTONRECORDs(self, version):
  334. """ Read zero or more button records (zero-terminated) """
  335. out = []
  336. while 1:
  337. button = self.readBUTTONRECORD(version)
  338. if button:
  339. out.append(button)
  340. else:
  341. break
  342. return out
  343. def readBUTTONCONDACTION(self):
  344. """ Read a size-prefixed BUTTONCONDACTION """
  345. size = self.readUI16()
  346. if size == 0:
  347. return None
  348. return SWFButtonCondAction(self)
  349. def readBUTTONCONDACTIONSs(self):
  350. """ Read zero or more button-condition actions """
  351. out = []
  352. while 1:
  353. action = self.readBUTTONCONDACTION()
  354. if action:
  355. out.append(action)
  356. else:
  357. break
  358. return out
  359. def readEXPORT(self):
  360. """ Read a SWFExport """
  361. return SWFExport(self)
  362. def readMORPHFILLSTYLEARRAY(self):
  363. count = self.readUI8()
  364. if count == 0xff:
  365. count = self.readUI16()
  366. return [self.readMORPHFILLSTYLE() for _ in range(count)]
  367. def readMORPHLINESTYLEARRAY(self, version):
  368. count = self.readUI8()
  369. if count == 0xff:
  370. count = self.readUI16()
  371. kind = self.readMORPHLINESTYLE if version == 1 else self.readMORPHLINESTYLE2
  372. return [kind() for _ in range(count)]
  373. def readraw_tag(self):
  374. """ Read a SWFRawTag """
  375. return SWFRawTag(self)
  376. def readtag_header(self):
  377. """ Read a tag header """
  378. pos = self.tell()
  379. tag_type_and_length = self.readUI16()
  380. tag_length = tag_type_and_length & 0x003f
  381. if tag_length == 0x3f:
  382. # The SWF10 spec sez that this is a signed int.
  383. # Shouldn't it be an unsigned int?
  384. tag_length = self.readSI32();
  385. return SWFRecordHeader(tag_type_and_length >> 6, tag_length, self.tell() - pos)
  386. def skip_bytes(self, length):
  387. """ Skip over the specified number of bytes """
  388. self.f.seek(self.tell() + length)
  389. def reset_bits_pending(self):
  390. """ Reset the bit array """
  391. self._bits_pending = 0
  392. def read(self, count=0):
  393. """ Read """
  394. return self.f.read(count) if count > 0 else self.f.read()
  395. def seek(self, pos, whence=0):
  396. """ Seek """
  397. self.f.seek(pos, whence)
  398. def tell(self):
  399. """ Tell """
  400. return self.f.tell()
  401. def int32(x):
  402. """ Return a signed or unsigned int """
  403. if x>0xFFFFFFFF:
  404. raise OverflowError
  405. if x>0x7FFFFFFF:
  406. x=int(0x100000000-x)
  407. if x<2147483648:
  408. return -x
  409. else:
  410. return -2147483648
  411. return x