2
0

Deserializer.php 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  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 license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Amf
  17. * @subpackage Parse_Amf0
  18. * @copyright Copyright (c) 2005-2015 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. /** Zend_Amf_Constants */
  23. require_once 'Zend/Amf/Constants.php';
  24. /** Zend_Xml_Security */
  25. require_once 'Zend/Xml/Security.php';
  26. /** @see Zend_Amf_Parse_Deserializer */
  27. require_once 'Zend/Amf/Parse/Deserializer.php';
  28. /**
  29. * Read an AMF0 input stream and convert it into PHP data types
  30. *
  31. * @todo Implement Typed Object Class Mapping
  32. * @todo Class could be implemented as Factory Class with each data type it's own class
  33. * @package Zend_Amf
  34. * @subpackage Parse_Amf0
  35. * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
  36. * @license http://framework.zend.com/license/new-bsd New BSD License
  37. */
  38. class Zend_Amf_Parse_Amf0_Deserializer extends Zend_Amf_Parse_Deserializer
  39. {
  40. /**
  41. * An array of objects used for recursively deserializing an object.
  42. * @var array
  43. */
  44. protected $_reference = array();
  45. /**
  46. * If AMF3 serialization occurs, update to AMF0 0x03
  47. *
  48. * @var int
  49. */
  50. protected $_objectEncoding = Zend_Amf_Constants::AMF0_OBJECT_ENCODING;
  51. /**
  52. * Read AMF markers and dispatch for deserialization
  53. *
  54. * Checks for AMF marker types and calls the appropriate methods
  55. * for deserializing those marker types. Markers are the data type of
  56. * the following value.
  57. *
  58. * @param integer $typeMarker
  59. * @return mixed whatever the data type is of the marker in php
  60. * @throws Zend_Amf_Exception for invalid type
  61. */
  62. public function readTypeMarker($typeMarker = null)
  63. {
  64. if ($typeMarker === null) {
  65. $typeMarker = $this->_stream->readByte();
  66. }
  67. switch($typeMarker) {
  68. // number
  69. case Zend_Amf_Constants::AMF0_NUMBER:
  70. return $this->_stream->readDouble();
  71. // boolean
  72. case Zend_Amf_Constants::AMF0_BOOLEAN:
  73. return (boolean) $this->_stream->readByte();
  74. // string
  75. case Zend_Amf_Constants::AMF0_STRING:
  76. return $this->_stream->readUTF();
  77. // object
  78. case Zend_Amf_Constants::AMF0_OBJECT:
  79. return $this->readObject();
  80. // null
  81. case Zend_Amf_Constants::AMF0_NULL:
  82. return null;
  83. // undefined
  84. case Zend_Amf_Constants::AMF0_UNDEFINED:
  85. return null;
  86. // Circular references are returned here
  87. case Zend_Amf_Constants::AMF0_REFERENCE:
  88. return $this->readReference();
  89. // mixed array with numeric and string keys
  90. case Zend_Amf_Constants::AMF0_MIXEDARRAY:
  91. return $this->readMixedArray();
  92. // array
  93. case Zend_Amf_Constants::AMF0_ARRAY:
  94. return $this->readArray();
  95. // date
  96. case Zend_Amf_Constants::AMF0_DATE:
  97. return $this->readDate();
  98. // longString strlen(string) > 2^16
  99. case Zend_Amf_Constants::AMF0_LONGSTRING:
  100. return $this->_stream->readLongUTF();
  101. //internal AS object, not supported
  102. case Zend_Amf_Constants::AMF0_UNSUPPORTED:
  103. return null;
  104. // XML
  105. case Zend_Amf_Constants::AMF0_XML:
  106. return $this->readXmlString();
  107. // typed object ie Custom Class
  108. case Zend_Amf_Constants::AMF0_TYPEDOBJECT:
  109. return $this->readTypedObject();
  110. //AMF3-specific
  111. case Zend_Amf_Constants::AMF0_AMF3:
  112. return $this->readAmf3TypeMarker();
  113. default:
  114. require_once 'Zend/Amf/Exception.php';
  115. throw new Zend_Amf_Exception('Unsupported marker type: ' . $typeMarker);
  116. }
  117. }
  118. /**
  119. * Read AMF objects and convert to PHP objects
  120. *
  121. * Read the name value pair objects form the php message and convert them to
  122. * a php object class.
  123. *
  124. * Called when the marker type is 3.
  125. *
  126. * @param array|null $object
  127. * @return object
  128. */
  129. public function readObject($object = null)
  130. {
  131. if ($object === null) {
  132. $object = array();
  133. }
  134. while (true) {
  135. $key = $this->_stream->readUTF();
  136. $typeMarker = $this->_stream->readByte();
  137. if ($typeMarker != Zend_Amf_Constants::AMF0_OBJECTTERM ){
  138. //Recursivly call readTypeMarker to get the types of properties in the object
  139. $object[$key] = $this->readTypeMarker($typeMarker);
  140. } else {
  141. //encountered AMF object terminator
  142. break;
  143. }
  144. }
  145. $this->_reference[] = $object;
  146. return (object) $object;
  147. }
  148. /**
  149. * Read reference objects
  150. *
  151. * Used to gain access to the private array of reference objects.
  152. * Called when marker type is 7.
  153. *
  154. * @return object
  155. * @throws Zend_Amf_Exception for invalid reference keys
  156. */
  157. public function readReference()
  158. {
  159. $key = $this->_stream->readInt();
  160. if (!array_key_exists($key, $this->_reference)) {
  161. require_once 'Zend/Amf/Exception.php';
  162. throw new Zend_Amf_Exception('Invalid reference key: '. $key);
  163. }
  164. return $this->_reference[$key];
  165. }
  166. /**
  167. * Reads an array with numeric and string indexes.
  168. *
  169. * Called when marker type is 8
  170. *
  171. * @todo As of Flash Player 9 there is not support for mixed typed arrays
  172. * so we handle this as an object. With the introduction of vectors
  173. * in Flash Player 10 this may need to be reconsidered.
  174. * @return array
  175. */
  176. public function readMixedArray()
  177. {
  178. $length = $this->_stream->readLong();
  179. return $this->readObject();
  180. }
  181. /**
  182. * Converts numerically indexed actiosncript arrays into php arrays.
  183. *
  184. * Called when marker type is 10
  185. *
  186. * @return array
  187. */
  188. public function readArray()
  189. {
  190. $length = $this->_stream->readLong();
  191. $array = array();
  192. while ($length--) {
  193. $array[] = $this->readTypeMarker();
  194. }
  195. return $array;
  196. }
  197. /**
  198. * Convert AS Date to Zend_Date
  199. *
  200. * @return Zend_Date
  201. */
  202. public function readDate()
  203. {
  204. // get the unix time stamp. Not sure why ActionScript does not use
  205. // milliseconds
  206. $timestamp = floor($this->_stream->readDouble() / 1000);
  207. // The timezone offset is never returned to the server; it is always 0,
  208. // so read and ignore.
  209. $offset = $this->_stream->readInt();
  210. require_once 'Zend/Date.php';
  211. $date = new Zend_Date($timestamp);
  212. return $date;
  213. }
  214. /**
  215. * Convert XML to SimpleXml
  216. * If user wants DomDocument they can use dom_import_simplexml
  217. *
  218. * @return SimpleXml Object
  219. */
  220. public function readXmlString()
  221. {
  222. $string = $this->_stream->readLongUTF();
  223. return Zend_Xml_Security::scan($string); //simplexml_load_string($string);
  224. }
  225. /**
  226. * Read Class that is to be mapped to a server class.
  227. *
  228. * Commonly used for Value Objects on the server
  229. *
  230. * @todo implement Typed Class mapping
  231. * @return object|array
  232. * @throws Zend_Amf_Exception if unable to load type
  233. */
  234. public function readTypedObject()
  235. {
  236. require_once 'Zend/Amf/Parse/TypeLoader.php';
  237. // get the remote class name
  238. $className = $this->_stream->readUTF();
  239. $loader = Zend_Amf_Parse_TypeLoader::loadType($className);
  240. $returnObject = new $loader();
  241. $properties = get_object_vars($this->readObject());
  242. foreach($properties as $key=>$value) {
  243. if($key) {
  244. $returnObject->$key = $value;
  245. }
  246. }
  247. if($returnObject instanceof Zend_Amf_Value_Messaging_ArrayCollection) {
  248. $returnObject = get_object_vars($returnObject);
  249. }
  250. return $returnObject;
  251. }
  252. /**
  253. * AMF3 data type encountered load AMF3 Deserializer to handle
  254. * type markers.
  255. *
  256. * @return string
  257. */
  258. public function readAmf3TypeMarker()
  259. {
  260. require_once 'Zend/Amf/Parse/Amf3/Deserializer.php';
  261. $deserializer = new Zend_Amf_Parse_Amf3_Deserializer($this->_stream);
  262. $this->_objectEncoding = Zend_Amf_Constants::AMF3_OBJECT_ENCODING;
  263. return $deserializer->readTypeMarker();
  264. }
  265. /**
  266. * Return the object encoding to check if an AMF3 object
  267. * is going to be return.
  268. *
  269. * @return int
  270. */
  271. public function getObjectEncoding()
  272. {
  273. return $this->_objectEncoding;
  274. }
  275. }