Source for file SwfCompiler.php

Documentation is available at SwfCompiler.php

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

Documentation generated on Fri, 06 Jul 2007 19:54:52 +0100 by phpDocumentor 1.3.1