PageRenderTime 60ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/Server/SWXPHP/Prior Releases/1.01/php/SwxAssembler.php

http://swx-format.googlecode.com/
PHP | 788 lines | 376 code | 150 blank | 262 comment | 66 complexity | 166beea176bdf3df1f1ae8fd8d06057a MD5 | raw file
Possible License(s): LGPL-2.1, GPL-2.0
  1. <?php
  2. /**
  3. * SWX Assember class.
  4. *
  5. * Creates SWX SWF files.
  6. * Released under the GNU GPL license.
  7. *
  8. * Author: Aral Balkan
  9. * Copyright (c) 2007 Aral Balkan.
  10. * http://aralbalkan.com
  11. *
  12. * http://swxformat.org
  13. */
  14. // PHP 5 compatibility layer for PHP 4
  15. require_once('lib/str_split.php');
  16. // Constants
  17. define ('LITTLE_ENDIAN', 'little-endian');
  18. define ('BIG_ENDIAN', 'big-endian');
  19. define ('BI_ENDIAN', 'bi-endian');
  20. class SwxAssembler
  21. {
  22. var $stack = '';
  23. var $endian = NULL;
  24. function SwxAssembler()
  25. {
  26. global $endian;
  27. // Determine endianness of the system that this is running under
  28. // Adapted from: http://phpfer.com/rn45re877.html
  29. $ab = 0x6162;
  30. // Convert $ab to a binary string containing 32 bits
  31. // Do the conversion the way that the system architecture wants to
  32. switch (pack ('L', $ab))
  33. {
  34. // Compare the value to the same value converted in a Little-Endian fashion
  35. case pack ('V', $ab):
  36. $endian = LITTLE_ENDIAN;
  37. break;
  38. // Compare the value to the same value converted in a Big-Endian fashion
  39. // TODO: Test on a big-endian machine. Currently SWX is not supported on
  40. // big endian machines.
  41. case pack ('V', $ab):
  42. $endian = BIG_ENDIAN;
  43. break;
  44. // Bi-endian or middle endian. The biggest use case for this is
  45. // PowerPC architectures. In fact, take this to mean PowerPC support.
  46. default:
  47. $endian = BI_ENDIAN;
  48. }
  49. if (LOG_ALL) error_log ('[SWX] INFO Running on a '.$endian.' system.');
  50. }
  51. // From http://de.php.net/var_dump
  52. function getVarDump($mixed = null)
  53. {
  54. ob_start();
  55. var_dump($mixed);
  56. $content = ob_get_contents();
  57. ob_end_clean();
  58. return $content;
  59. }
  60. /**
  61. * Converts the passed object to arrays.
  62. *
  63. * @return void
  64. * @author Aral Balkan
  65. **/
  66. function objectToArray($data='')
  67. {
  68. $arr = array();
  69. foreach ($data as $key => $value )
  70. {
  71. if (gettype($value) == 'object')
  72. {
  73. $arr[$key] = $this->objectToArray($value);
  74. }
  75. else
  76. {
  77. $arr[$key] = $value;
  78. }
  79. }
  80. return $arr;
  81. }
  82. /**
  83. * Parses the given data structure (any type) and
  84. * returns SWF bytecode.
  85. *
  86. * @param any A PHP data structure
  87. * @return string Swf bytecode representation of the data structure.
  88. * @author Aral Balkan
  89. **/
  90. function dataToBytecode ($data)
  91. {
  92. $type = gettype($data);
  93. switch($type)
  94. {
  95. case 'array':
  96. $bytecode = $this->arrayToBytecode($data);
  97. break;
  98. case 'object':
  99. // TODO: Handle objects natively without
  100. // converting to an associative array.
  101. // Convert object to array
  102. $data = $this->objectToArray($data);
  103. // And then use the array encoder
  104. $bytecode = $this->arrayToBytecode($data);
  105. break;
  106. case 'string':
  107. $bytecode = $this->stringToBytecode($data);
  108. break;
  109. case 'integer':
  110. $bytecode = $this->integerToBytecode($data);
  111. break;
  112. case 'double':
  113. $bytecode = $this->doubleToBytecode($data);
  114. break;
  115. case 'boolean':
  116. $bytecode = $this->booleanToBytecode($data);
  117. break;
  118. case 'NULL':
  119. $bytecode = DATA_TYPE_NULL;
  120. break;
  121. default:
  122. trigger_error('Unhandled data type ('.$type.')', E_USER_ERROR);
  123. //error_log('[SWX] ERROR dataToBytecode() Unhandled data type: ' . $type);
  124. //$bytecode = "ERROR";
  125. }
  126. return $bytecode;
  127. }
  128. /**
  129. * Converts the passed array to SWF bytecode.
  130. *
  131. * @return string SWF bytecode.
  132. * @author Aral Balkan
  133. **/
  134. function arrayToBytecode($arr)
  135. {
  136. // Note: We are going to write the bytecode backwards,
  137. // starting from the end as it's easier that way.
  138. //$bytecode = '';
  139. // To count number of elements in the array
  140. $arrCount = count($arr);
  141. $bytecode = $this->integerToBytecode($arrCount);// . $bytecode;
  142. // Determine array type
  143. $keys = array_keys($arr);
  144. if ($arrCount == 0 || gettype($keys[0]) == 'integer')
  145. {
  146. // Reverse the array to mirror how they're stored in a SWF (this
  147. // won't affect associative arrays (objects in Flash) but it will
  148. // make regular arrays appear in the right order.
  149. // $arr = array_reverse($arr);
  150. $arrayType = ARRAY_TYPE_REGULAR;
  151. $bytecode .= ACTION_INIT_ARRAY; // . $bytecode;
  152. }
  153. else
  154. {
  155. $arrayType = ARRAY_TYPE_ASSOCIATIVE;
  156. $bytecode .= ACTION_INIT_OBJECT; // . $bytecode;
  157. }
  158. // Add the number of elements
  159. //
  160. // Optimized:
  161. // DATA_TYPE_INTEGER . strtoupper(str_pad($this->makeLittleEndian(dechex($arrCount)), 8, '0')) . $bytecode;
  162. //
  163. // Clear:
  164. // $this->integerToBytecode($arrCount) . $bytecode;
  165. //
  166. //$bytecode = $this->integerToBytecode($arrCount) . $bytecode;
  167. // Profiling:
  168. //$forLoopStartTime = $this->microtime_float();
  169. foreach ($arr as $key => $value)
  170. {
  171. // Check if the current bytecode length is approaching
  172. // the 64K (65535 byte) limit that we can store in a single push
  173. // and, if so, create a new push.
  174. // TODO: Refactor - pull out
  175. $bytecodeLenInDec = strlen($bytecode)/2;
  176. if ($bytecodeLenInDec >= 65520) // For testing use >= 2)
  177. {
  178. // Calculate bytecode length *without* counting the
  179. // init object or init array action
  180. $lastInstruction = substr($bytecode, -2);
  181. if ( $lastInstruction == ACTION_INIT_OBJECT || $lastInstruction == ACTION_INIT_ARRAY)
  182. {
  183. //error_log('(at end) IS COMPLEX - '.$lastInstruction);
  184. $bytecodeLenInDec -= 1;
  185. }
  186. // TODO: Refactor - pull out
  187. $bytecodeLenInHex = $this->getIntAsHex($bytecodeLenInDec, 2);
  188. $bytecode = $bytecodeLenInHex . $bytecode;
  189. $bytecode = '96' . $bytecode; // Push. TODO: Replace w. constant
  190. // Store current instruction on the stack
  191. $this->stack = $bytecode . $this->stack;
  192. // Reset the bytecode
  193. $bytecode = '';
  194. }
  195. // Convert objects to arrays.
  196. // TODO: Handle objects natively.
  197. if (gettype($value) == 'object')
  198. {
  199. $value = $this->objectToArray($value);
  200. }
  201. // Is this a simple data type or an array?
  202. if (gettype($value) == 'array')
  203. {
  204. // Element is an array, we need to *push* it on to
  205. // the stack separately. End the current push.
  206. // (Note: this produces bytecode that differs from
  207. // what the Adobe compiler in Flash produces but
  208. // it's easier.)
  209. $bytecodeLenInDec = strlen($bytecode)/2;
  210. // Calculate bytecode length *without* counting the
  211. // init object or init array action
  212. $lastInstruction = substr($bytecode, -2);
  213. if ( $lastInstruction == ACTION_INIT_OBJECT || $lastInstruction == ACTION_INIT_ARRAY)
  214. {
  215. //error_log('IS COMPLEX - '.$lastInstruction);
  216. $bytecodeLenInDec -= 1;
  217. }
  218. // If we haven't written any bytecode into the local
  219. // buffer yet (if it's empty), don't write a push statement.
  220. if ($bytecodeLenInDec != -1 && $bytecodeLenInDec != 0)
  221. {
  222. // TODO: Refactor - pull out
  223. $bytecodeLenInHex = $this->getIntAsHex($bytecodeLenInDec, 2);
  224. $bytecode = $bytecodeLenInHex . $bytecode;
  225. $bytecode = '96' . $bytecode; // Push. TODO: Replace w. constant
  226. }
  227. // Store current instruction on the stack
  228. $this->stack = $bytecode . $this->stack;
  229. // Reset the bytecode
  230. $bytecode = '';
  231. // Add the found array to the stack
  232. $this->arrayToBytecode($value);
  233. // If this is an element from an associative array, push the
  234. // key before you recurse:
  235. if ($arrayType == ARRAY_TYPE_ASSOCIATIVE)
  236. {
  237. $bytecode = $this->dataToBytecode($key) . $bytecode;
  238. }
  239. }
  240. else
  241. {
  242. // Simple data type
  243. // What type of array are we?
  244. if ($arrayType == ARRAY_TYPE_REGULAR)
  245. {
  246. // Regular
  247. $bytecode = $this->dataToBytecode($value).$bytecode;
  248. }
  249. else
  250. {
  251. // Associative (in Flash: object)
  252. $bytecode = $this->dataToBytecode($key)
  253. .$this->dataToBytecode($value)
  254. .$bytecode;
  255. }
  256. }
  257. }
  258. // Profiling:
  259. // error_log("For loop took" . (microtime_float()-$forLoopStartTime));
  260. if ($bytecode != '')
  261. {
  262. $bytecodeLenInDec = strlen($bytecode)/2;
  263. // TODO: Refactor - Pull out
  264. // Calculate bytecode length *without* counting the
  265. // init object or init array action
  266. $lastInstruction = substr($bytecode, -2);
  267. if ( $lastInstruction == ACTION_INIT_OBJECT || $lastInstruction == ACTION_INIT_ARRAY)
  268. {
  269. //error_log('(at end) IS COMPLEX - '.$lastInstruction);
  270. $bytecodeLenInDec -= 1;
  271. }
  272. // TODO: Refactor - pull this out into its own method now that
  273. // it is being used at the start of the loop also.
  274. $bytecodeLenInHex = $this->getIntAsHex($bytecodeLenInDec, 2);
  275. $bytecode = $bytecodeLenInHex . $bytecode;
  276. $bytecode = '96' . $bytecode; // Push. TODO: Replace w. constant
  277. // Store current instruction on the stack
  278. $this->stack = $bytecode . $this->stack;
  279. }
  280. else
  281. {
  282. //error_log('Bytecode is empty, skipping...');
  283. }
  284. //error_log('Returning stack: ' . $this->stack);
  285. return $this->stack;
  286. }
  287. /**
  288. * Converts the passed string to hex and returns the correct SWF bytecode for it.
  289. *
  290. * @param string The string to convert to bytecode.
  291. * @return string SWF bytecode for the passed string
  292. * @author Aral Balkan
  293. **/
  294. function stringToBytecode ($str)
  295. {
  296. $bytecode = strtoupper(DATA_TYPE_STRING . $this->strhex($str) . NULL_TERMINATOR);
  297. return $bytecode;
  298. }
  299. /**
  300. * Converts the passed integer to bytecode, padding it to
  301. * $numBytes bytes in little-endian.
  302. *
  303. * @param integer Number to convert to hex byte representation.
  304. * @param integer Number of bytes to pad to.
  305. * @return string Integer as hex string.
  306. * @author Aral Balkan
  307. **/
  308. function integerToBytecode($int)
  309. {
  310. $bytecode = DATA_TYPE_INTEGER . $this->getIntAsHex($int, 4);
  311. return $bytecode;
  312. }
  313. /**
  314. * Converts a double to its IEEE 754 representation (little-endian)
  315. *
  316. * Modified from Chung Leong's function.
  317. * (http://www.thescripts.com/forum/thread9237.html.)
  318. *
  319. * TODO: Works on 5.1.2 for me (OS X 10.4.9, Intel Core Duo, MAMP 1.2.1) but
  320. * waiting for report back from Alex Skinner for whom it is not working. Weird!
  321. *
  322. * @param double A PHP double.
  323. * @return string Little-endian Flash double in hex (variation on IEEE 754).
  324. * @author Aral Balkan
  325. **/
  326. function doubleToBytecode($f)
  327. {
  328. global $endian;
  329. $f = (double) $f;
  330. $b = pack("d", $f);
  331. $hex = "";
  332. // This test is here for PowerPC Macs which are bi-endian.
  333. if ($endian == BI_ENDIAN)
  334. {
  335. $b = strrev($b);
  336. }
  337. for($i = 0; $i < strlen($b); $i++)
  338. {
  339. $c = ord($b{$i});
  340. $hex .= sprintf("%02X", $c);
  341. }
  342. $hex = substr($hex, 8, 8).substr($hex, 0, 8);
  343. return DATA_TYPE_DOUBLE . $hex;
  344. }
  345. /**
  346. * Converts the passed boolean to SWF bytecode.
  347. *
  348. * @return string Boolean as SWF bytecode.
  349. * @author Aral Balkan
  350. **/
  351. function booleanToBytecode ($bool)
  352. {
  353. $boolBytecode = DATA_TYPE_BOOLEAN . ($bool ? '01':'00');
  354. return $boolBytecode;
  355. }
  356. /**
  357. * Wraps the SWF buffer in a doAction block, wraps that with
  358. * the SWF Header and the SWF footer (set variable, show frame, end SWF)
  359. * and writes out the SWF.
  360. *
  361. * @param Data to write out as a SWF.
  362. * @return void
  363. * @author Aral Balkan
  364. **/
  365. function writeSwf($data, $debug = false, $compressionLevel = 4, $url = '')
  366. {
  367. global $allowDomain;
  368. $pushTag = $this->datatoBytecode($data);
  369. if (gettype($data) != 'array' && gettype($data) != 'object')
  370. {
  371. // Not an array, add the push code and length:
  372. $bytecodeLenInDec = strlen($pushTag)/2;
  373. $bytecodeLenInHex = $this->getIntAsHex($bytecodeLenInDec, 2);
  374. $pushTag = '96' . $bytecodeLenInHex . $pushTag;
  375. }
  376. // error_log("type of data: ".gettype($data));
  377. // error_log("pushTag: $pushTag");
  378. // Add the 'result' variable name -- either
  379. // using the constant table if in debug mode
  380. // or as a regular string otherwise
  381. if ($debug)
  382. {
  383. $pushTag = '9602000800' . $pushTag;
  384. }
  385. else
  386. {
  387. $pushTag = '96080000726573756C7400' . $pushTag;
  388. }
  389. // Create the DoAction tag
  390. $doActionBlock = $pushTag;
  391. $doActionBlock .= ACTION_SET_VARIABLE;
  392. // Allow domain? If so add allow domain statement to the SWF
  393. if ($allowDomain === true)
  394. {
  395. if (LOG_ALL) error_log("[SWX] INFO Allow domain is on.");
  396. $doActionBlock = $doActionBlock . $this->getAllowDomainBytecode($url); // ALLOW_DOMAIN;
  397. }
  398. // Debug? If so, add the analyzer connector to the SWF
  399. if ($debug)
  400. {
  401. if (LOG_ALL) error_log('[SWX] INFO Debug mode is on.');
  402. $doActionBlock = DEBUG_START . $doActionBlock . DEBUG_END;
  403. }
  404. $doActionBlockSizeInBytes = $this->getStringLengthInBytesHex($doActionBlock, 4);
  405. $doActionBlock = ACTION_DO_ACTION . $doActionBlockSizeInBytes . $doActionBlock;
  406. // Create the whole SWF
  407. $headerType = ($compressionLevel > 0) ? COMPRESSED_SWF : UNCOMPRESSED_SWF;
  408. $swf = $headerType . HEADER . $doActionBlock . ACTION_SHOW_FRAME . ACTION_END_SWF;
  409. $swfSizeInBytes = $this->getStringLengthInBytesHex($swf, 4);
  410. $swf = str_replace('LLLLLLLL', $swfSizeInBytes, $swf);
  411. // Convert the SWF bytecode to a string (file)
  412. $swfFile = $this->hexstr ($swf);
  413. // Stats
  414. $uncompressedSize = strlen($swfFile);
  415. if (LOG_ALL) error_log('[SWX] INFO Uncompressed size of SWF: ' . $uncompressedSize . ' bytes.');
  416. // Compress the SWF if required
  417. // Profiling info: Performance impact of compression is negligible.
  418. if ($compressionLevel > 0)
  419. {
  420. $compressionStartTime = $this->microtime_float();
  421. // The first eight bytes are uncompressed
  422. $uncompressedBytes = substr($swfFile, 0, 8);
  423. // Remove first eight bytes
  424. $swfFile = substr_replace($swfFile, '', 0, 8);
  425. // Compress the rest of the SWF
  426. $swfFile = gzcompress($swfFile, $compressionLevel);
  427. // Add the uncompressed header
  428. $swfFile = $uncompressedBytes . $swfFile;
  429. $compressionDuration = $this->microtime_float() - $compressionStartTime;
  430. if (LOG_ALL) error_log('[SWX] PROFILING: SWF compression took ' . $compressionDuration . ' seconds.');
  431. // Stats
  432. $compressedSize = strlen($swfFile);
  433. if (LOG_ALL) error_log('[SWX] INFO Compressed size of SWF: ' . $compressedSize . ' bytes.');
  434. }
  435. header("Content-Type: application/swf;");
  436. header('Content-Disposition: inline; filename="data.swf"');
  437. header('Content-Length: ' . strlen($swfFile));
  438. echo $swfFile;
  439. // Enable the next line to write out a hex representation of
  440. // the SWF to the error log (helps with testing.)
  441. // error_log($this->prettyHex($swf));
  442. }
  443. function getAllowDomainBytecode($url)
  444. {
  445. if ($url === '')
  446. {
  447. // No URL passed -- possibly called by legacy code, use the old _parent._url version.
  448. if (LOG_ALL) error_log('[SWX] INFO: No URL passed from client. Defaulting to old behavior. You must call System.security.allowDomain on the dataHolder for cross domain data loading to work.');
  449. return ALLOW_DOMAIN;
  450. }
  451. if (LOG_ALL) error_log('[SWX] INFO: Data SWF will allow access from ' . $url);
  452. // URL is passed, write that into the returned code
  453. $allowDomainBytecode = $this->stringToBytecode($url);
  454. // The -13 is to accomodate the other elements being pushed to the
  455. // stack in the hard-coded part of the bytecode.
  456. $allowDomainBytecodeLengthDec = strlen($allowDomainBytecode)/2 + 13;
  457. $allowDomainBytecodeLength = $this->getIntAsHex($allowDomainBytecodeLengthDec, 2);
  458. $allowDomainBytecode = '96' . $allowDomainBytecodeLength . $allowDomainBytecode . SYSTEM_ALLOW_DOMAIN;
  459. return $allowDomainBytecode;
  460. }
  461. /**
  462. * Helper methods. (For data type conversions, formatting, etc.)
  463. */
  464. // Returns a string with the length of the passed hex string in bytes
  465. // padded to display in $numBytes bytes.
  466. function getStringLengthInBytesHex($strInHex, $numBytes)
  467. {
  468. // Divide length in chars by 2 to get length in bytes
  469. $bytecodeLenInDec = strlen($strInHex)/2;
  470. $bytecodeLenInHex = $this->getIntAsHex($bytecodeLenInDec, $numBytes);
  471. return $bytecodeLenInHex;
  472. }
  473. /**
  474. * Returns the hexadecimal representation of the passed integer,
  475. * padded to $numBytes bytes in little-endian.
  476. *
  477. * @param integer Number to convert to hex byte representation.
  478. * @param integer Number of bytes to pad to.
  479. * @return string Integer as hex string.
  480. * @author Aral Balkan
  481. **/
  482. function getIntAsHex($int, $numBytes=1)
  483. {
  484. $intAsHex = strtoupper(str_pad($this->makeLittleEndian(dechex($int)), $numBytes*2, '0'));
  485. return $intAsHex;
  486. }
  487. //////////////////////////////////////////////////////////////////////
  488. //
  489. // makeLittleEndian()
  490. //
  491. // Takes a hex string in big endian and coverts it to little endian
  492. //
  493. //////////////////////////////////////////////////////////////////////
  494. function makeLittleEndian($str)
  495. {
  496. $sLen = strlen($str);
  497. // Make sure that the string is padded to the byte boundary
  498. if ($sLen%2 == 1)
  499. {
  500. $sLen++;
  501. $str = '0'.$str;
  502. }
  503. $sLenInBytes = $sLen/2;
  504. $strArr = str_split($str, 2);
  505. $strArr = array_reverse($strArr);
  506. $strLittleEndian = implode('', $strArr);
  507. return $strLittleEndian;
  508. }
  509. //////////////////////////////////////////////////////////////////////
  510. //
  511. // prettyHex()
  512. //
  513. // Pretty prints hex string in 1 bytes groups, 10 to a line
  514. // and show number of bytes in the string.
  515. //
  516. //////////////////////////////////////////////////////////////////////
  517. function prettyHex ($h)
  518. {
  519. $pretty = "\n\n 01 02 03 04 05 06 07 08 09 10\n -----------------------------\n0001| ";
  520. $hArr = str_split($h, 2);
  521. $lineCount = 1;
  522. for ($i = 0; $i < count($hArr); $i++)
  523. {
  524. $pretty .= $hArr[$i] . ' ';
  525. if (($i+1)%10 == 0 )
  526. {
  527. $lineCount++;
  528. $pretty .= "\n".str_pad($lineCount, 4, "0", STR_PAD_LEFT).'| ';
  529. }
  530. }
  531. $pretty .= "\n\n$h\n\nNum bytes: ".count($hArr)."\n";
  532. return $pretty;
  533. }
  534. //////////////////////////////////////////////////////////////////////
  535. //
  536. // debug()
  537. //
  538. // Debug only displays debug messages if we
  539. // are not writing out a SWF.
  540. //
  541. //////////////////////////////////////////////////////////////////////
  542. function debug($str)
  543. {
  544. global $isPost;
  545. if ($isPost || isset($_GET['swf']))
  546. {
  547. return;
  548. }
  549. else
  550. {
  551. echo $str;
  552. }
  553. }
  554. /**
  555. * Converts a string of hexadecimal values to a string of ASCII characters.
  556. *
  557. * @return string String with ASCII characters
  558. * @author Paul Gregg <pgregg@pgregg.com>
  559. * @link http://www.pgregg.com/projects/php/code/hexstr.phps
  560. **/
  561. function hexstr($hexstr)
  562. {
  563. $hexstr = str_replace(' ', '', $hexstr);
  564. $retstr = pack('H*', $hexstr);
  565. return $retstr;
  566. }
  567. /**
  568. * Converts a string of ASCII characters to a string of hexadecimal byte values.
  569. *
  570. * @return string String with ASCII characters
  571. * @author Paul Gregg <pgregg@pgregg.com>
  572. * @author Aral Balkan (added PHP4 bug fix)
  573. * @link http://www.pgregg.com/projects/php/code/hexstr.phps
  574. **/
  575. function strhex($string)
  576. {
  577. $hexstr = unpack('H*', $string);
  578. // Fix for unpack bug
  579. // http://bugs.php.net/bug.php?id=36148
  580. // PHP 4 and 5 appear to give different results for the unpack
  581. // PHP 4.4.3+ exhibits same behavior as PHP 5.
  582. // PHP version 5.1.2 exhibits the same behavior as PHP 4.
  583. // Tested with: 4.4.2, 4.4.3, 4.4.4, 5.1.4, 5.1.6, 5.2.1.
  584. // Definitely *not* supported on 4.3.10 (or the 4.3 branch at all.)
  585. //
  586. // TODO: Look for a way to optimize this.
  587. $phpVer = phpversion();
  588. if ( (substr($phpVer,0,1) == '4' && intval(substr($phpVer,4, 1)) < 3) || $phpVer == '5.1.2')
  589. {
  590. // PHP 4
  591. return substr($hexstr[1], 0, -1);
  592. }
  593. else
  594. {
  595. // PHP 4.4.3+ and 5.1.4+
  596. return array_shift($hexstr);
  597. }
  598. }
  599. // Profiling
  600. function microtime_float()
  601. {
  602. list($usec, $sec) = explode(" ", microtime());
  603. return ((float)$usec + (float)$sec);
  604. }
  605. }
  606. //
  607. // SWF bytecode constants. Discovered through observation.
  608. //
  609. // Header - FCS (uncompressed), version Flash 6
  610. define('UNCOMPRESSED_SWF', '46');
  611. define('COMPRESSED_SWF', '43');
  612. define('HEADER', '575306LLLLLLLL300A00A0000101004302FFFFFF');
  613. // Action bytecodes
  614. define('ACTION_PUSH', '96LLLL');
  615. define('ACTION_SHOW_FRAME', '4000');
  616. define('ACTION_END_SWF', '0000');
  617. define('ACTION_SET_VARIABLE', '1D'); // 00
  618. define('ACTION_DO_ACTION', '3F03');
  619. define('ACTION_INIT_ARRAY', '42');
  620. define('ACTION_INIT_OBJECT', '43');
  621. // Data type codes
  622. define('DATA_TYPE_STRING', '00');
  623. define('DATA_TYPE_NULL', '02');
  624. define('DATA_TYPE_BOOLEAN', '05');
  625. define('DATA_TYPE_DOUBLE', '06');
  626. define('DATA_TYPE_INTEGER', '07');
  627. // Misc
  628. define('NULL_TERMINATOR', '00');
  629. // Non-bytecode constants
  630. define('ARRAY_TYPE_REGULAR', 'regular');
  631. define('ARRAY_TYPE_ASSOCIATIVE', 'associative');
  632. // Allow domain (*)
  633. define('ALLOW_DOMAIN', '960900005F706172656E74001C960600005F75726C004E960D0007010000000053797374656D001C960A00007365637572697479004E960D0000616C6C6F77446F6D61696E005217');
  634. define('SYSTEM_ALLOW_DOMAIN', '07010000000053797374656D001C960A00007365637572697479004E960D0000616C6C6F77446F6D61696E005217');
  635. // Debug SWX bytecode. Creates a local connection to the SWX Debugger front-end.)
  636. define('DEBUG_START','883C000700726573756C74006C63004C6F63616C436F6E6E656374696F6E005F737778446562756767657200636F6E6E6563740064656275670073656E6400');
  637. define('DEBUG_END', '960D0008010600000000000000000802403C9609000803070100000008011C9602000804521796020008001C960500070100000042960B0008050803070300000008011C96020008065217');
  638. ?>