PageRenderTime 26ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/library/Zend/Amf/Parser/Amf0/Deserializer.php

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