File indexing completed on 2024-06-23 05:55:01

0001 <?php
0002 /**
0003  * Zend Framework
0004  *
0005  * LICENSE
0006  *
0007  * This source file is subject to the new BSD license that is bundled
0008  * with this package in the file LICENSE.txt.
0009  * It is also available through the world-wide-web at this URL:
0010  * http://framework.zend.com/license/new-bsd
0011  * If you did not receive a copy of the license and are unable to
0012  * obtain it through the world-wide-web, please send an email
0013  * to license@zend.com so we can send you a copy immediately.
0014  *
0015  * @category   Zend
0016  * @package    Zend_Amf
0017  * @subpackage Parse_Amf0
0018  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0019  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0020  * @version    $Id$
0021  */
0022 
0023 /** Zend_Amf_Constants */
0024 // require_once 'Zend/Amf/Constants.php';
0025 
0026 /** Zend_Xml_Security */
0027 // require_once 'Zend/Xml/Security.php';
0028 
0029 /** @see Zend_Amf_Parse_Deserializer */
0030 // require_once 'Zend/Amf/Parse/Deserializer.php';
0031 
0032 /**
0033  * Read an AMF0 input stream and convert it into PHP data types
0034  *
0035  * @todo       Implement Typed Object Class Mapping
0036  * @todo       Class could be implemented as Factory Class with each data type it's own class
0037  * @package    Zend_Amf
0038  * @subpackage Parse_Amf0
0039  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0040  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0041  */
0042 class Zend_Amf_Parse_Amf0_Deserializer extends Zend_Amf_Parse_Deserializer
0043 {
0044     /**
0045      * An array of objects used for recursively deserializing an object.
0046      * @var array
0047      */
0048     protected $_reference = array();
0049 
0050     /**
0051      * If AMF3 serialization occurs, update to AMF0 0x03
0052      *
0053      * @var int
0054      */
0055     protected $_objectEncoding = Zend_Amf_Constants::AMF0_OBJECT_ENCODING;
0056 
0057     /**
0058      * Read AMF markers and dispatch for deserialization
0059      *
0060      * Checks for AMF marker types and calls the appropriate methods
0061      * for deserializing those marker types. Markers are the data type of
0062      * the following value.
0063      *
0064      * @param  integer $typeMarker
0065      * @return mixed whatever the data type is of the marker in php
0066      * @throws Zend_Amf_Exception for invalid type
0067      */
0068     public function readTypeMarker($typeMarker = null)
0069     {
0070         if ($typeMarker === null) {
0071             $typeMarker = $this->_stream->readByte();
0072         }
0073 
0074         switch($typeMarker) {
0075             // number
0076             case Zend_Amf_Constants::AMF0_NUMBER:
0077                 return $this->_stream->readDouble();
0078 
0079             // boolean
0080             case Zend_Amf_Constants::AMF0_BOOLEAN:
0081                 return (boolean) $this->_stream->readByte();
0082 
0083             // string
0084             case Zend_Amf_Constants::AMF0_STRING:
0085                 return $this->_stream->readUTF();
0086 
0087             // object
0088             case Zend_Amf_Constants::AMF0_OBJECT:
0089                 return $this->readObject();
0090 
0091             // null
0092             case Zend_Amf_Constants::AMF0_NULL:
0093                 return null;
0094 
0095             // undefined
0096             case Zend_Amf_Constants::AMF0_UNDEFINED:
0097                 return null;
0098 
0099             // Circular references are returned here
0100             case Zend_Amf_Constants::AMF0_REFERENCE:
0101                 return $this->readReference();
0102 
0103             // mixed array with numeric and string keys
0104             case Zend_Amf_Constants::AMF0_MIXEDARRAY:
0105                 return $this->readMixedArray();
0106 
0107             // array
0108             case Zend_Amf_Constants::AMF0_ARRAY:
0109                 return $this->readArray();
0110 
0111             // date
0112             case Zend_Amf_Constants::AMF0_DATE:
0113                 return $this->readDate();
0114 
0115             // longString  strlen(string) > 2^16
0116             case Zend_Amf_Constants::AMF0_LONGSTRING:
0117                 return $this->_stream->readLongUTF();
0118 
0119             //internal AS object,  not supported
0120             case Zend_Amf_Constants::AMF0_UNSUPPORTED:
0121                 return null;
0122 
0123             // XML
0124             case Zend_Amf_Constants::AMF0_XML:
0125                 return $this->readXmlString();
0126 
0127             // typed object ie Custom Class
0128             case Zend_Amf_Constants::AMF0_TYPEDOBJECT:
0129                 return $this->readTypedObject();
0130 
0131             //AMF3-specific
0132             case Zend_Amf_Constants::AMF0_AMF3:
0133                 return $this->readAmf3TypeMarker();
0134 
0135             default:
0136                 // require_once 'Zend/Amf/Exception.php';
0137                 throw new Zend_Amf_Exception('Unsupported marker type: ' . $typeMarker);
0138         }
0139     }
0140 
0141     /**
0142      * Read AMF objects and convert to PHP objects
0143      *
0144      * Read the name value pair objects form the php message and convert them to
0145      * a php object class.
0146      *
0147      * Called when the marker type is 3.
0148      *
0149      * @param  array|null $object
0150      * @return object
0151      */
0152     public function readObject($object = null)
0153     {
0154         if ($object === null) {
0155             $object = array();
0156         }
0157 
0158         while (true) {
0159             $key        = $this->_stream->readUTF();
0160             $typeMarker = $this->_stream->readByte();
0161             if ($typeMarker != Zend_Amf_Constants::AMF0_OBJECTTERM ){
0162                 //Recursivly call readTypeMarker to get the types of properties in the object
0163                 $object[$key] = $this->readTypeMarker($typeMarker);
0164             } else {
0165                 //encountered AMF object terminator
0166                 break;
0167             }
0168         }
0169         $this->_reference[] = $object;
0170         return (object) $object;
0171     }
0172 
0173     /**
0174      * Read reference objects
0175      *
0176      * Used to gain access to the private array of reference objects.
0177      * Called when marker type is 7.
0178      *
0179      * @return object
0180      * @throws Zend_Amf_Exception for invalid reference keys
0181      */
0182     public function readReference()
0183     {
0184         $key = $this->_stream->readInt();
0185         if (!array_key_exists($key, $this->_reference)) {
0186             // require_once 'Zend/Amf/Exception.php';
0187             throw new Zend_Amf_Exception('Invalid reference key: '. $key);
0188         }
0189         return $this->_reference[$key];
0190     }
0191 
0192     /**
0193      * Reads an array with numeric and string indexes.
0194      *
0195      * Called when marker type is 8
0196      *
0197      * @todo   As of Flash Player 9 there is not support for mixed typed arrays
0198      *         so we handle this as an object. With the introduction of vectors
0199      *         in Flash Player 10 this may need to be reconsidered.
0200      * @return array
0201      */
0202     public function readMixedArray()
0203     {
0204         $length = $this->_stream->readLong();
0205         return $this->readObject();
0206     }
0207 
0208     /**
0209      * Converts numerically indexed actiosncript arrays into php arrays.
0210      *
0211      * Called when marker type is 10
0212      *
0213      * @return array
0214      */
0215     public function readArray()
0216     {
0217         $length = $this->_stream->readLong();
0218         $array = array();
0219         while ($length--) {
0220             $array[] = $this->readTypeMarker();
0221         }
0222         return $array;
0223     }
0224 
0225     /**
0226      * Convert AS Date to Zend_Date
0227      *
0228      * @return Zend_Date
0229      */
0230     public function readDate()
0231     {
0232         // get the unix time stamp. Not sure why ActionScript does not use
0233         // milliseconds
0234         $timestamp = floor($this->_stream->readDouble() / 1000);
0235 
0236         // The timezone offset is never returned to the server; it is always 0,
0237         // so read and ignore.
0238         $offset = $this->_stream->readInt();
0239 
0240         // require_once 'Zend/Date.php';
0241         $date   = new Zend_Date($timestamp);
0242         return $date;
0243     }
0244 
0245     /**
0246      * Convert XML to SimpleXml
0247      * If user wants DomDocument they can use dom_import_simplexml
0248      *
0249      * @return SimpleXml Object
0250      */
0251     public function readXmlString()
0252     {
0253         $string = $this->_stream->readLongUTF();
0254         return Zend_Xml_Security::scan($string); //simplexml_load_string($string);
0255     }
0256 
0257     /**
0258      * Read Class that is to be mapped to a server class.
0259      *
0260      * Commonly used for Value Objects on the server
0261      *
0262      * @todo   implement Typed Class mapping
0263      * @return object|array
0264      * @throws Zend_Amf_Exception if unable to load type
0265      */
0266     public function readTypedObject()
0267     {
0268          // require_once 'Zend/Amf/Parse/TypeLoader.php';
0269         // get the remote class name
0270         $className = $this->_stream->readUTF();
0271         $loader = Zend_Amf_Parse_TypeLoader::loadType($className);
0272         $returnObject = new $loader();
0273         $properties = get_object_vars($this->readObject());
0274         foreach($properties as $key=>$value) {
0275             if($key) {
0276                 $returnObject->$key = $value;
0277             }
0278         }
0279         if($returnObject instanceof Zend_Amf_Value_Messaging_ArrayCollection) {
0280             $returnObject = get_object_vars($returnObject);
0281         }
0282         return $returnObject;
0283     }
0284 
0285     /**
0286      * AMF3 data type encountered load AMF3 Deserializer to handle
0287      * type markers.
0288      *
0289      * @return string
0290      */
0291     public function readAmf3TypeMarker()
0292     {
0293         // require_once 'Zend/Amf/Parse/Amf3/Deserializer.php';
0294         $deserializer = new Zend_Amf_Parse_Amf3_Deserializer($this->_stream);
0295         $this->_objectEncoding = Zend_Amf_Constants::AMF3_OBJECT_ENCODING;
0296         return $deserializer->readTypeMarker();
0297     }
0298 
0299     /**
0300      * Return the object encoding to check if an AMF3 object
0301      * is going to be return.
0302      *
0303      * @return int
0304      */
0305     public function getObjectEncoding()
0306     {
0307         return $this->_objectEncoding;
0308     }
0309 }