[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/lib/zend/Zend/Amf/Parse/Amf3/ -> Deserializer.php (source)

   1  <?php
   2  /**
   3   * Zend Framework
   4   *
   5   * LICENSE
   6   *
   7   * This source file is subject to the new BSD license that is bundled
   8   * with this package in the file LICENSE.txt.
   9   * It is also available through the world-wide-web at this URL:
  10   * http://framework.zend.com/license/new-bsd
  11   * If you did not receive a copy of the license and are unable to
  12   * obtain it through the world-wide-web, please send an email
  13   * to [email protected] so we can send you a copy immediately.
  14   *
  15   * @category   Zend
  16   * @package    Zend_Amf
  17   * @subpackage Parse_Amf3
  18   * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  19   * @license    http://framework.zend.com/license/new-bsd     New BSD License
  20   * @version    $Id$
  21   */
  22  
  23  /** Zend_Amf_Parse_Deserializer */
  24  require_once 'Zend/Amf/Parse/Deserializer.php';
  25  
  26  /** Zend_Amf_Parse_TypeLoader */
  27  require_once 'Zend/Amf/Parse/TypeLoader.php';
  28  
  29  /**
  30   * Read an AMF3 input stream and convert it into PHP data types.
  31   *
  32   * @todo       readObject to handle Typed Objects
  33   * @todo       readXMLStrimg to be implemented.
  34   * @todo       Class could be implemented as Factory Class with each data type it's own class.
  35   * @package    Zend_Amf
  36   * @subpackage Parse_Amf3
  37   * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  38   * @license    http://framework.zend.com/license/new-bsd     New BSD License
  39   */
  40  class Zend_Amf_Parse_Amf3_Deserializer extends Zend_Amf_Parse_Deserializer
  41  {
  42      /**
  43       * Total number of objects in the referenceObject array
  44       * @var int
  45       */
  46      protected $_objectCount;
  47  
  48      /**
  49       * An array of reference objects per amf body
  50       * @var array
  51       */
  52      protected $_referenceObjects = array();
  53  
  54      /**
  55       * An array of reference strings per amf body
  56       * @var array
  57       */
  58      protected $_referenceStrings = array();
  59  
  60      /**
  61       * An array of reference class definitions per body
  62       * @var array
  63       */
  64      protected $_referenceDefinitions = array();
  65  
  66      /**
  67       * Read AMF markers and dispatch for deserialization
  68       *
  69       * Checks for AMF marker types and calls the appropriate methods
  70       * for deserializing those marker types. markers are the data type of
  71       * the following value.
  72       *
  73       * @param  integer $typeMarker
  74       * @return mixed Whatever the corresponding PHP data type is
  75       * @throws Zend_Amf_Exception for unidentified marker type
  76       */
  77      public function readTypeMarker($typeMarker = null)
  78      {
  79          if(null === $typeMarker) {
  80              $typeMarker = $this->_stream->readByte();
  81          }
  82  
  83          switch($typeMarker) {
  84              case Zend_Amf_Constants::AMF3_UNDEFINED:
  85                   return null;
  86              case Zend_Amf_Constants::AMF3_NULL:
  87                   return null;
  88              case Zend_Amf_Constants::AMF3_BOOLEAN_FALSE:
  89                   return false;
  90              case Zend_Amf_Constants::AMF3_BOOLEAN_TRUE:
  91                   return true;
  92              case Zend_Amf_Constants::AMF3_INTEGER:
  93                   return $this->readInteger();
  94              case Zend_Amf_Constants::AMF3_NUMBER:
  95                   return $this->_stream->readDouble();
  96              case Zend_Amf_Constants::AMF3_STRING:
  97                   return $this->readString();
  98              case Zend_Amf_Constants::AMF3_DATE:
  99                   return $this->readDate();
 100              case Zend_Amf_Constants::AMF3_ARRAY:
 101                   return $this->readArray();
 102              case Zend_Amf_Constants::AMF3_OBJECT:
 103                   return $this->readObject();
 104              case Zend_Amf_Constants::AMF3_XML:
 105              case Zend_Amf_Constants::AMF3_XMLSTRING:
 106                   return $this->readXmlString();
 107              case Zend_Amf_Constants::AMF3_BYTEARRAY:
 108                   return $this->readString();
 109              default:
 110                  require_once 'Zend/Amf/Exception.php';
 111                  throw new Zend_Amf_Exception('Unsupported type marker: ' . $typeMarker);
 112          }
 113      }
 114  
 115      /**
 116       * Read and deserialize an integer
 117       *
 118       * AMF 3 represents smaller integers with fewer bytes using the most
 119       * significant bit of each byte. The worst case uses 32-bits
 120       * to represent a 29-bit number, which is what we would have
 121       * done with no compression.
 122       * - 0x00000000 - 0x0000007F : 0xxxxxxx
 123       * - 0x00000080 - 0x00003FFF : 1xxxxxxx 0xxxxxxx
 124       * - 0x00004000 - 0x001FFFFF : 1xxxxxxx 1xxxxxxx 0xxxxxxx
 125       * - 0x00200000 - 0x3FFFFFFF : 1xxxxxxx 1xxxxxxx 1xxxxxxx xxxxxxxx
 126       * - 0x40000000 - 0xFFFFFFFF : throw range exception
 127       *
 128       * 0x04 -> integer type code, followed by up to 4 bytes of data.
 129       *
 130       * Parsing integers on OSFlash for the AMF3 integer data format:
 131       * @link http://osflash.org/amf3/parsing_integers
 132       * @return int|float
 133       */
 134      public function readInteger()
 135      {
 136          $count        = 1;
 137          $intReference = $this->_stream->readByte();
 138          $result       = 0;
 139          while ((($intReference & 0x80) != 0) && $count < 4) {
 140              $result       <<= 7;
 141              $result        |= ($intReference & 0x7f);
 142              $intReference   = $this->_stream->readByte();
 143              $count++;
 144          }
 145          if ($count < 4) {
 146              $result <<= 7;
 147              $result  |= $intReference;
 148          } else {
 149              // Use all 8 bits from the 4th byte
 150              $result <<= 8;
 151              $result  |= $intReference;
 152  
 153              // Check if the integer should be negative
 154              if (($result & 0x10000000) != 0) {
 155                  //and extend the sign bit
 156                  $result |= ~0xFFFFFFF;
 157              }
 158          }
 159          return $result;
 160      }
 161  
 162      /**
 163       * Read and deserialize a string
 164       *
 165       * Strings can be sent as a reference to a previously
 166       * occurring String by using an index to the implicit string reference table.
 167       * Strings are encoding using UTF-8 - however the header may either
 168       * describe a string literal or a string reference.
 169       *
 170       * - string = 0x06 string-data
 171       * - string-data = integer-data [ modified-utf-8 ]
 172       * - modified-utf-8 = *OCTET
 173       *
 174       * @return String
 175       */
 176      public function readString()
 177      {
 178          $stringReference = $this->readInteger();
 179  
 180          //Check if this is a reference string
 181          if (($stringReference & 0x01) == 0) {
 182              // reference string
 183              $stringReference = $stringReference >> 1;
 184              if ($stringReference >= count($this->_referenceStrings)) {
 185                  require_once 'Zend/Amf/Exception.php';
 186                  throw new Zend_Amf_Exception('Undefined string reference: ' . $stringReference);
 187              }
 188              // reference string found
 189              return $this->_referenceStrings[$stringReference];
 190          }
 191  
 192          $length = $stringReference >> 1;
 193          if ($length) {
 194              $string = $this->_stream->readBytes($length);
 195              $this->_referenceStrings[] = $string;
 196          } else {
 197              $string = "";
 198          }
 199          return $string;
 200      }
 201  
 202      /**
 203       * Read and deserialize a date
 204       *
 205       * Data is the number of milliseconds elapsed since the epoch
 206       * of midnight, 1st Jan 1970 in the UTC time zone.
 207       * Local time zone information is not sent to flash.
 208       *
 209       * - date = 0x08 integer-data [ number-data ]
 210       *
 211       * @return Zend_Date
 212       */
 213      public function readDate()
 214      {
 215          $dateReference = $this->readInteger();
 216          if (($dateReference & 0x01) == 0) {
 217              $dateReference = $dateReference >> 1;
 218              if ($dateReference>=count($this->_referenceObjects)) {
 219                  require_once 'Zend/Amf/Exception.php';
 220                  throw new Zend_Amf_Exception('Undefined date reference: ' . $dateReference);
 221              }
 222              return $this->_referenceObjects[$dateReference];
 223          }
 224  
 225          $timestamp = floor($this->_stream->readDouble() / 1000);
 226  
 227          require_once 'Zend/Date.php';
 228          $dateTime  = new Zend_Date((int) $timestamp);
 229          $this->_referenceObjects[] = $dateTime;
 230          return $dateTime;
 231      }
 232  
 233      /**
 234       * Read amf array to PHP array
 235       *
 236       * - array = 0x09 integer-data ( [ 1OCTET *amf3-data ] | [OCTET *amf3-data 1] | [ OCTET *amf-data ] )
 237       *
 238       * @return array
 239       */
 240      public function readArray()
 241      {
 242          $arrayReference = $this->readInteger();
 243          if (($arrayReference & 0x01)==0){
 244              $arrayReference = $arrayReference >> 1;
 245              if ($arrayReference>=count($this->_referenceObjects)) {
 246                  require_once 'Zend/Amf/Exception.php';
 247                  throw new Zend_Amf_Exception('Unknow array reference: ' . $arrayReference);
 248              }
 249              return $this->_referenceObjects[$arrayReference];
 250          }
 251  
 252          // Create a holder for the array in the reference list
 253          $data = array();
 254          $this->_referenceObjects[] =& $data;
 255          $key = $this->readString();
 256  
 257          // Iterating for string based keys.
 258          while ($key != '') {
 259              $data[$key] = $this->readTypeMarker();
 260              $key = $this->readString();
 261          }
 262  
 263          $arrayReference = $arrayReference >>1;
 264  
 265          //We have a dense array
 266          for ($i=0; $i < $arrayReference; $i++) {
 267              $data[] = $this->readTypeMarker();
 268          }
 269  
 270          return $data;
 271      }
 272  
 273      /**
 274       * Read an object from the AMF stream and convert it into a PHP object
 275       *
 276       * @todo   Rather than using an array of traitsInfo create Zend_Amf_Value_TraitsInfo
 277       * @return object|array
 278       */
 279      public function readObject()
 280      {
 281          $traitsInfo   = $this->readInteger();
 282          $storedObject = ($traitsInfo & 0x01)==0;
 283          $traitsInfo   = $traitsInfo >> 1;
 284  
 285          // Check if the Object is in the stored Objects reference table
 286          if ($storedObject) {
 287              $ref = $traitsInfo;
 288              if (!isset($this->_referenceObjects[$ref])) {
 289                  require_once 'Zend/Amf/Exception.php';
 290                  throw new Zend_Amf_Exception('Unknown Object reference: ' . $ref);
 291              }
 292              $returnObject = $this->_referenceObjects[$ref];
 293          } else {
 294              // Check if the Object is in the stored Definitions reference table
 295              $storedClass = ($traitsInfo & 0x01) == 0;
 296              $traitsInfo  = $traitsInfo >> 1;
 297              if ($storedClass) {
 298                  $ref = $traitsInfo;
 299                  if (!isset($this->_referenceDefinitions[$ref])) {
 300                      require_once 'Zend/Amf/Exception.php';
 301                      throw new Zend_Amf_Exception('Unknows Definition reference: '. $ref);
 302                  }
 303                  // Populate the reference attributes
 304                  $className     = $this->_referenceDefinitions[$ref]['className'];
 305                  $encoding      = $this->_referenceDefinitions[$ref]['encoding'];
 306                  $propertyNames = $this->_referenceDefinitions[$ref]['propertyNames'];
 307              } else {
 308                  // The class was not in the reference tables. Start reading rawdata to build traits.
 309                  // Create a traits table. Zend_Amf_Value_TraitsInfo would be ideal
 310                  $className     = $this->readString();
 311                  $encoding      = $traitsInfo & 0x03;
 312                  $propertyNames = array();
 313                  $traitsInfo    = $traitsInfo >> 2;
 314              }
 315  
 316              // We now have the object traits defined in variables. Time to go to work:
 317              if (!$className) {
 318                  // No class name generic object
 319                  $returnObject = new stdClass();
 320              } else {
 321                  // Defined object
 322                  // Typed object lookup against registered classname maps
 323                  if ($loader = Zend_Amf_Parse_TypeLoader::loadType($className)) {
 324                      $returnObject = new $loader();
 325                  } else {
 326                      //user defined typed object
 327                      require_once 'Zend/Amf/Exception.php';
 328                      throw new Zend_Amf_Exception('Typed object not found: '. $className . ' ');
 329                  }
 330              }
 331  
 332              // Add the Object to the reference table
 333              $this->_referenceObjects[] = $returnObject;
 334  
 335              $properties = array(); // clear value
 336              // Check encoding types for additional processing.
 337              switch ($encoding) {
 338                  case (Zend_Amf_Constants::ET_EXTERNAL):
 339                      // Externalizable object such as {ArrayCollection} and {ObjectProxy}
 340                      if (!$storedClass) {
 341                          $this->_referenceDefinitions[] = array(
 342                              'className'     => $className,
 343                              'encoding'      => $encoding,
 344                              'propertyNames' => $propertyNames,
 345                          );
 346                      }
 347                      $returnObject->externalizedData = $this->readTypeMarker();
 348                      break;
 349                  case (Zend_Amf_Constants::ET_DYNAMIC):
 350                      // used for Name-value encoding
 351                      if (!$storedClass) {
 352                          $this->_referenceDefinitions[] = array(
 353                              'className'     => $className,
 354                              'encoding'      => $encoding,
 355                              'propertyNames' => $propertyNames,
 356                          );
 357                      }
 358                      // not a reference object read name value properties from byte stream
 359                      do {
 360                          $property = $this->readString();
 361                          if ($property != "") {
 362                              $propertyNames[]       = $property;
 363                              $properties[$property] = $this->readTypeMarker();
 364                          }
 365                      } while ($property !="");
 366                      break;
 367                  default:
 368                      // basic property list object.
 369                      if (!$storedClass) {
 370                          $count = $traitsInfo; // Number of properties in the list
 371                          for($i=0; $i< $count; $i++) {
 372                              $propertyNames[] = $this->readString();
 373                          }
 374                          // Add a reference to the class.
 375                          $this->_referenceDefinitions[] = array(
 376                              'className'     => $className,
 377                              'encoding'      => $encoding,
 378                              'propertyNames' => $propertyNames,
 379                          );
 380                      }
 381                      foreach ($propertyNames as $property) {
 382                          $properties[$property] = $this->readTypeMarker();
 383                      }
 384                      break;
 385              }
 386  
 387              // Add properties back to the return object.
 388              foreach($properties as $key=>$value) {
 389                  if($key) {
 390                      $returnObject->$key = $value;
 391                  }
 392              }
 393  
 394  
 395          }
 396  
 397         if ($returnObject instanceof Zend_Amf_Value_Messaging_ArrayCollection) {
 398              if (isset($returnObject->externalizedData)) {
 399                  $returnObject = $returnObject->externalizedData;
 400              } else {
 401                  $returnObject = get_object_vars($returnObject);
 402              }
 403         }
 404  
 405          return $returnObject;
 406      }
 407  
 408      /**
 409       * Convert XML to SimpleXml
 410       * If user wants DomDocument they can use dom_import_simplexml
 411       *
 412       * @return SimpleXml Object
 413       */
 414      public function readXmlString()
 415      {
 416          $xmlReference = $this->readInteger();
 417          $length = $xmlReference >> 1;
 418          $string = $this->_stream->readBytes($length);
 419          return simplexml_load_string($string);
 420      }
 421  }


Generated: Fri Nov 28 20:29:05 2014 Cross-referenced by PHPXref 0.7.1