Deserializer.php 9.1 KB

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