PageRenderTime 47ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/Server/SWXPHP/2.00/php/core/swx/SwxAS2Assembler.php

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