|
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 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) |
|
18 * @license http://framework.zend.com/license/new-bsd New BSD License |
|
19 * @version $Id: Request.php 20096 2010-01-06 02:05:09Z bkarwin $ |
|
20 */ |
|
21 |
|
22 /** @see Zend_Amf_Parse_InputStream */ |
|
23 require_once 'Zend/Amf/Parse/InputStream.php'; |
|
24 |
|
25 /** @see Zend_Amf_Parse_Amf0_Deserializer */ |
|
26 require_once 'Zend/Amf/Parse/Amf0/Deserializer.php'; |
|
27 |
|
28 /** @see Zend_Amf_Constants */ |
|
29 require_once 'Zend/Amf/Constants.php'; |
|
30 |
|
31 /** @see Zend_Amf_Value_MessageHeader */ |
|
32 require_once 'Zend/Amf/Value/MessageHeader.php'; |
|
33 |
|
34 /** @see Zend_Amf_Value_MessageBody */ |
|
35 require_once 'Zend/Amf/Value/MessageBody.php'; |
|
36 |
|
37 /** |
|
38 * Handle the incoming AMF request by deserializing the data to php object |
|
39 * types and storing the data for Zend_Amf_Server to handle for processing. |
|
40 * |
|
41 * @todo Currently not checking if the object needs to be Type Mapped to a server object. |
|
42 * @package Zend_Amf |
|
43 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) |
|
44 * @license http://framework.zend.com/license/new-bsd New BSD License |
|
45 */ |
|
46 class Zend_Amf_Request |
|
47 { |
|
48 /** |
|
49 * @var int AMF client type (AMF0, AMF3) |
|
50 */ |
|
51 protected $_clientType = 0; // default AMF0 |
|
52 |
|
53 /** |
|
54 * @var array Message bodies |
|
55 */ |
|
56 protected $_bodies = array(); |
|
57 |
|
58 /** |
|
59 * @var array Message headers |
|
60 */ |
|
61 protected $_headers = array(); |
|
62 |
|
63 /** |
|
64 * @var int Message encoding to use for objects in response |
|
65 */ |
|
66 protected $_objectEncoding = 0; |
|
67 |
|
68 /** |
|
69 * @var Zend_Amf_Parse_InputStream |
|
70 */ |
|
71 protected $_inputStream; |
|
72 |
|
73 /** |
|
74 * @var Zend_Amf_Parse_AMF0_Deserializer |
|
75 */ |
|
76 protected $_deserializer; |
|
77 |
|
78 /** |
|
79 * Time of the request |
|
80 * @var mixed |
|
81 */ |
|
82 protected $_time; |
|
83 |
|
84 /** |
|
85 * Prepare the AMF InputStream for parsing. |
|
86 * |
|
87 * @param string $request |
|
88 * @return Zend_Amf_Request |
|
89 */ |
|
90 public function initialize($request) |
|
91 { |
|
92 $this->_inputStream = new Zend_Amf_Parse_InputStream($request); |
|
93 $this->_deserializer = new Zend_Amf_Parse_Amf0_Deserializer($this->_inputStream); |
|
94 $this->readMessage($this->_inputStream); |
|
95 return $this; |
|
96 } |
|
97 |
|
98 /** |
|
99 * Takes the raw AMF input stream and converts it into valid PHP objects |
|
100 * |
|
101 * @param Zend_Amf_Parse_InputStream |
|
102 * @return Zend_Amf_Request |
|
103 */ |
|
104 public function readMessage(Zend_Amf_Parse_InputStream $stream) |
|
105 { |
|
106 $clientVersion = $stream->readUnsignedShort(); |
|
107 if (($clientVersion != Zend_Amf_Constants::AMF0_OBJECT_ENCODING) |
|
108 && ($clientVersion != Zend_Amf_Constants::AMF3_OBJECT_ENCODING) |
|
109 && ($clientVersion != Zend_Amf_Constants::FMS_OBJECT_ENCODING) |
|
110 ) { |
|
111 require_once 'Zend/Amf/Exception.php'; |
|
112 throw new Zend_Amf_Exception('Unknown Player Version ' . $clientVersion); |
|
113 } |
|
114 |
|
115 $this->_bodies = array(); |
|
116 $this->_headers = array(); |
|
117 $headerCount = $stream->readInt(); |
|
118 |
|
119 // Iterate through the AMF envelope header |
|
120 while ($headerCount--) { |
|
121 $this->_headers[] = $this->readHeader(); |
|
122 } |
|
123 |
|
124 // Iterate through the AMF envelope body |
|
125 $bodyCount = $stream->readInt(); |
|
126 while ($bodyCount--) { |
|
127 $this->_bodies[] = $this->readBody(); |
|
128 } |
|
129 |
|
130 return $this; |
|
131 } |
|
132 |
|
133 /** |
|
134 * Deserialize a message header from the input stream. |
|
135 * |
|
136 * A message header is structured as: |
|
137 * - NAME String |
|
138 * - MUST UNDERSTAND Boolean |
|
139 * - LENGTH Int |
|
140 * - DATA Object |
|
141 * |
|
142 * @return Zend_Amf_Value_MessageHeader |
|
143 */ |
|
144 public function readHeader() |
|
145 { |
|
146 $name = $this->_inputStream->readUTF(); |
|
147 $mustRead = (bool)$this->_inputStream->readByte(); |
|
148 $length = $this->_inputStream->readLong(); |
|
149 |
|
150 try { |
|
151 $data = $this->_deserializer->readTypeMarker(); |
|
152 } catch (Exception $e) { |
|
153 require_once 'Zend/Amf/Exception.php'; |
|
154 throw new Zend_Amf_Exception('Unable to parse ' . $name . ' header data: ' . $e->getMessage() . ' '. $e->getLine(), 0, $e); |
|
155 } |
|
156 |
|
157 $header = new Zend_Amf_Value_MessageHeader($name, $mustRead, $data, $length); |
|
158 return $header; |
|
159 } |
|
160 |
|
161 /** |
|
162 * Deserialize a message body from the input stream |
|
163 * |
|
164 * @return Zend_Amf_Value_MessageBody |
|
165 */ |
|
166 public function readBody() |
|
167 { |
|
168 $targetURI = $this->_inputStream->readUTF(); |
|
169 $responseURI = $this->_inputStream->readUTF(); |
|
170 $length = $this->_inputStream->readLong(); |
|
171 |
|
172 try { |
|
173 $data = $this->_deserializer->readTypeMarker(); |
|
174 } catch (Exception $e) { |
|
175 require_once 'Zend/Amf/Exception.php'; |
|
176 throw new Zend_Amf_Exception('Unable to parse ' . $targetURI . ' body data ' . $e->getMessage(), 0, $e); |
|
177 } |
|
178 |
|
179 // Check for AMF3 objectEncoding |
|
180 if ($this->_deserializer->getObjectEncoding() == Zend_Amf_Constants::AMF3_OBJECT_ENCODING) { |
|
181 /* |
|
182 * When and AMF3 message is sent to the server it is nested inside |
|
183 * an AMF0 array called Content. The following code gets the object |
|
184 * out of the content array and sets it as the message data. |
|
185 */ |
|
186 if(is_array($data) && $data[0] instanceof Zend_Amf_Value_Messaging_AbstractMessage){ |
|
187 $data = $data[0]; |
|
188 } |
|
189 |
|
190 // set the encoding so we return our message in AMF3 |
|
191 $this->_objectEncoding = Zend_Amf_Constants::AMF3_OBJECT_ENCODING; |
|
192 } |
|
193 |
|
194 $body = new Zend_Amf_Value_MessageBody($targetURI, $responseURI, $data); |
|
195 return $body; |
|
196 } |
|
197 |
|
198 /** |
|
199 * Return an array of the body objects that were found in the amf request. |
|
200 * |
|
201 * @return array {target, response, length, content} |
|
202 */ |
|
203 public function getAmfBodies() |
|
204 { |
|
205 return $this->_bodies; |
|
206 } |
|
207 |
|
208 /** |
|
209 * Accessor to private array of message bodies. |
|
210 * |
|
211 * @param Zend_Amf_Value_MessageBody $message |
|
212 * @return Zend_Amf_Request |
|
213 */ |
|
214 public function addAmfBody(Zend_Amf_Value_MessageBody $message) |
|
215 { |
|
216 $this->_bodies[] = $message; |
|
217 return $this; |
|
218 } |
|
219 |
|
220 /** |
|
221 * Return an array of headers that were found in the amf request. |
|
222 * |
|
223 * @return array {operation, mustUnderstand, length, param} |
|
224 */ |
|
225 public function getAmfHeaders() |
|
226 { |
|
227 return $this->_headers; |
|
228 } |
|
229 |
|
230 /** |
|
231 * Return the either 0 or 3 for respect AMF version |
|
232 * |
|
233 * @return int |
|
234 */ |
|
235 public function getObjectEncoding() |
|
236 { |
|
237 return $this->_objectEncoding; |
|
238 } |
|
239 |
|
240 /** |
|
241 * Set the object response encoding |
|
242 * |
|
243 * @param mixed $int |
|
244 * @return Zend_Amf_Request |
|
245 */ |
|
246 public function setObjectEncoding($int) |
|
247 { |
|
248 $this->_objectEncoding = $int; |
|
249 return $this; |
|
250 } |
|
251 } |