File indexing completed on 2025-01-26 05:29:15
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 /** @see Zend_Amf_Parse_Serializer */ 0027 // require_once 'Zend/Amf/Parse/Serializer.php'; 0028 0029 /** 0030 * Serializer PHP misc types back to there corresponding AMF0 Type Marker. 0031 * 0032 * @uses Zend_Amf_Parse_Serializer 0033 * @package Zend_Amf 0034 * @subpackage Parse_Amf0 0035 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0036 * @license http://framework.zend.com/license/new-bsd New BSD License 0037 */ 0038 class Zend_Amf_Parse_Amf0_Serializer extends Zend_Amf_Parse_Serializer 0039 { 0040 /** 0041 * @var string Name of the class to be returned 0042 */ 0043 protected $_className = ''; 0044 0045 /** 0046 * An array of reference objects 0047 * @var array 0048 */ 0049 protected $_referenceObjects = array(); 0050 0051 /** 0052 * Determine type and serialize accordingly 0053 * 0054 * Checks to see if the type was declared and then either 0055 * auto negotiates the type or relies on the user defined markerType to 0056 * serialize the data into amf 0057 * 0058 * @param mixed $data 0059 * @param mixed $markerType 0060 * @param mixed $dataByVal 0061 * @return Zend_Amf_Parse_Amf0_Serializer 0062 * @throws Zend_Amf_Exception for unrecognized types or data 0063 */ 0064 public function writeTypeMarker(&$data, $markerType = null, $dataByVal = false) 0065 { 0066 // Workaround for PHP5 with E_STRICT enabled complaining about "Only 0067 // variables should be passed by reference" 0068 if ((null === $data) && ($dataByVal !== false)) { 0069 $data = &$dataByVal; 0070 } 0071 if (null !== $markerType) { 0072 //try to reference the given object 0073 if (!$this->writeObjectReference($data, $markerType)) { 0074 // Write the Type Marker to denote the following action script data type 0075 $this->_stream->writeByte($markerType); 0076 switch($markerType) { 0077 case Zend_Amf_Constants::AMF0_NUMBER: 0078 $this->_stream->writeDouble($data); 0079 break; 0080 case Zend_Amf_Constants::AMF0_BOOLEAN: 0081 $this->_stream->writeByte($data); 0082 break; 0083 case Zend_Amf_Constants::AMF0_STRING: 0084 $this->_stream->writeUTF($data); 0085 break; 0086 case Zend_Amf_Constants::AMF0_OBJECT: 0087 $this->writeObject($data); 0088 break; 0089 case Zend_Amf_Constants::AMF0_NULL: 0090 break; 0091 case Zend_Amf_Constants::AMF0_REFERENCE: 0092 $this->_stream->writeInt($data); 0093 break; 0094 case Zend_Amf_Constants::AMF0_MIXEDARRAY: 0095 // Write length of numeric keys as zero. 0096 $this->_stream->writeLong(0); 0097 $this->writeObject($data); 0098 break; 0099 case Zend_Amf_Constants::AMF0_ARRAY: 0100 $this->writeArray($data); 0101 break; 0102 case Zend_Amf_Constants::AMF0_DATE: 0103 $this->writeDate($data); 0104 break; 0105 case Zend_Amf_Constants::AMF0_LONGSTRING: 0106 $this->_stream->writeLongUTF($data); 0107 break; 0108 case Zend_Amf_Constants::AMF0_TYPEDOBJECT: 0109 $this->writeTypedObject($data); 0110 break; 0111 case Zend_Amf_Constants::AMF0_AMF3: 0112 $this->writeAmf3TypeMarker($data); 0113 break; 0114 default: 0115 // require_once 'Zend/Amf/Exception.php'; 0116 throw new Zend_Amf_Exception("Unknown Type Marker: " . $markerType); 0117 } 0118 } 0119 } else { 0120 if (is_resource($data)) { 0121 $data = Zend_Amf_Parse_TypeLoader::handleResource($data); 0122 } 0123 switch (true) { 0124 case (is_int($data) || is_float($data)): 0125 $markerType = Zend_Amf_Constants::AMF0_NUMBER; 0126 break; 0127 case (is_bool($data)): 0128 $markerType = Zend_Amf_Constants::AMF0_BOOLEAN; 0129 break; 0130 case (is_string($data) && (($this->_mbStringFunctionsOverloaded ? mb_strlen($data, '8bit') : strlen($data)) > 65536)): 0131 $markerType = Zend_Amf_Constants::AMF0_LONGSTRING; 0132 break; 0133 case (is_string($data)): 0134 $markerType = Zend_Amf_Constants::AMF0_STRING; 0135 break; 0136 case (is_object($data)): 0137 if (($data instanceof DateTime) || ($data instanceof Zend_Date)) { 0138 $markerType = Zend_Amf_Constants::AMF0_DATE; 0139 } else { 0140 0141 if($className = $this->getClassName($data)){ 0142 //Object is a Typed object set classname 0143 $markerType = Zend_Amf_Constants::AMF0_TYPEDOBJECT; 0144 $this->_className = $className; 0145 } else { 0146 // Object is a generic classname 0147 $markerType = Zend_Amf_Constants::AMF0_OBJECT; 0148 } 0149 break; 0150 } 0151 break; 0152 case (null === $data): 0153 $markerType = Zend_Amf_Constants::AMF0_NULL; 0154 break; 0155 case (is_array($data)): 0156 // check if it is an associative array 0157 $i = 0; 0158 foreach (array_keys($data) as $key) { 0159 // check if it contains non-integer keys 0160 if (!is_numeric($key) || intval($key) != $key) { 0161 $markerType = Zend_Amf_Constants::AMF0_OBJECT; 0162 break; 0163 // check if it is a sparse indexed array 0164 } else if ($key != $i) { 0165 $markerType = Zend_Amf_Constants::AMF0_MIXEDARRAY; 0166 break; 0167 } 0168 $i++; 0169 } 0170 // Dealing with a standard numeric array 0171 if(!$markerType){ 0172 $markerType = Zend_Amf_Constants::AMF0_ARRAY; 0173 break; 0174 } 0175 break; 0176 default: 0177 // require_once 'Zend/Amf/Exception.php'; 0178 throw new Zend_Amf_Exception('Unsupported data type: ' . gettype($data)); 0179 } 0180 0181 $this->writeTypeMarker($data, $markerType); 0182 } 0183 return $this; 0184 } 0185 0186 /** 0187 * Check if the given object is in the reference table, write the reference if it exists, 0188 * otherwise add the object to the reference table 0189 * 0190 * @param mixed $object object reference to check for reference 0191 * @param string $markerType AMF type of the object to write 0192 * @param mixed $objectByVal object to check for reference 0193 * @return Boolean true, if the reference was written, false otherwise 0194 */ 0195 protected function writeObjectReference(&$object, $markerType, $objectByVal = false) 0196 { 0197 // Workaround for PHP5 with E_STRICT enabled complaining about "Only 0198 // variables should be passed by reference" 0199 if ((null === $object) && ($objectByVal !== false)) { 0200 $object = &$objectByVal; 0201 } 0202 0203 if ($markerType == Zend_Amf_Constants::AMF0_OBJECT 0204 || $markerType == Zend_Amf_Constants::AMF0_MIXEDARRAY 0205 || $markerType == Zend_Amf_Constants::AMF0_ARRAY 0206 || $markerType == Zend_Amf_Constants::AMF0_TYPEDOBJECT 0207 ) { 0208 $ref = array_search($object, $this->_referenceObjects, true); 0209 //handle object reference 0210 if($ref !== false){ 0211 $this->writeTypeMarker($ref,Zend_Amf_Constants::AMF0_REFERENCE); 0212 return true; 0213 } 0214 0215 $this->_referenceObjects[] = $object; 0216 } 0217 0218 return false; 0219 } 0220 0221 /** 0222 * Write a PHP array with string or mixed keys. 0223 * 0224 * @param object $data 0225 * @return Zend_Amf_Parse_Amf0_Serializer 0226 */ 0227 public function writeObject($object) 0228 { 0229 // Loop each element and write the name of the property. 0230 foreach ($object as $key => &$value) { 0231 // skip variables starting with an _ private transient 0232 if( $key[0] == "_") continue; 0233 $this->_stream->writeUTF($key); 0234 $this->writeTypeMarker($value); 0235 } 0236 0237 // Write the end object flag 0238 $this->_stream->writeInt(0); 0239 $this->_stream->writeByte(Zend_Amf_Constants::AMF0_OBJECTTERM); 0240 return $this; 0241 } 0242 0243 /** 0244 * Write a standard numeric array to the output stream. If a mixed array 0245 * is encountered call writeTypeMarker with mixed array. 0246 * 0247 * @param array $array 0248 * @return Zend_Amf_Parse_Amf0_Serializer 0249 */ 0250 public function writeArray(&$array) 0251 { 0252 $length = count($array); 0253 if (!$length < 0) { 0254 // write the length of the array 0255 $this->_stream->writeLong(0); 0256 } else { 0257 // Write the length of the numeric array 0258 $this->_stream->writeLong($length); 0259 for ($i=0; $i<$length; $i++) { 0260 $value = isset($array[$i]) ? $array[$i] : null; 0261 $this->writeTypeMarker($value); 0262 } 0263 } 0264 return $this; 0265 } 0266 0267 /** 0268 * Convert the DateTime into an AMF Date 0269 * 0270 * @param DateTime|Zend_Date $data 0271 * @return Zend_Amf_Parse_Amf0_Serializer 0272 */ 0273 public function writeDate($data) 0274 { 0275 if ($data instanceof DateTime) { 0276 $dateString = $data->format('U'); 0277 } elseif ($data instanceof Zend_Date) { 0278 $dateString = $data->toString('U'); 0279 } else { 0280 // require_once 'Zend/Amf/Exception.php'; 0281 throw new Zend_Amf_Exception('Invalid date specified; must be a DateTime or Zend_Date object'); 0282 } 0283 $dateString *= 1000; 0284 0285 // Make the conversion and remove milliseconds. 0286 $this->_stream->writeDouble($dateString); 0287 0288 // Flash does not respect timezone but requires it. 0289 $this->_stream->writeInt(0); 0290 0291 return $this; 0292 } 0293 0294 /** 0295 * Write a class mapped object to the output stream. 0296 * 0297 * @param object $data 0298 * @return Zend_Amf_Parse_Amf0_Serializer 0299 */ 0300 public function writeTypedObject($data) 0301 { 0302 $this->_stream->writeUTF($this->_className); 0303 $this->writeObject($data); 0304 return $this; 0305 } 0306 0307 /** 0308 * Encountered and AMF3 Type Marker use AMF3 serializer. Once AMF3 is 0309 * encountered it will not return to AMf0. 0310 * 0311 * @param string $data 0312 * @return Zend_Amf_Parse_Amf0_Serializer 0313 */ 0314 public function writeAmf3TypeMarker(&$data) 0315 { 0316 // require_once 'Zend/Amf/Parse/Amf3/Serializer.php'; 0317 $serializer = new Zend_Amf_Parse_Amf3_Serializer($this->_stream); 0318 $serializer->writeTypeMarker($data); 0319 return $this; 0320 } 0321 0322 /** 0323 * Find if the class name is a class mapped name and return the 0324 * respective classname if it is. 0325 * 0326 * @param object $object 0327 * @return false|string $className 0328 */ 0329 protected function getClassName($object) 0330 { 0331 // require_once 'Zend/Amf/Parse/TypeLoader.php'; 0332 //Check to see if the object is a typed object and we need to change 0333 $className = ''; 0334 switch (true) { 0335 // the return class mapped name back to actionscript class name. 0336 case Zend_Amf_Parse_TypeLoader::getMappedClassName(get_class($object)): 0337 $className = Zend_Amf_Parse_TypeLoader::getMappedClassName(get_class($object)); 0338 break; 0339 // Check to see if the user has defined an explicit Action Script type. 0340 case isset($object->_explicitType): 0341 $className = $object->_explicitType; 0342 break; 0343 // Check if user has defined a method for accessing the Action Script type 0344 case method_exists($object, 'getASClassName'): 0345 $className = $object->getASClassName(); 0346 break; 0347 // No return class name is set make it a generic object 0348 case ($object instanceof stdClass): 0349 $className = ''; 0350 break; 0351 // By default, use object's class name 0352 default: 0353 $className = get_class($object); 0354 break; 0355 } 0356 if(!$className == '') { 0357 return $className; 0358 } else { 0359 return false; 0360 } 0361 } 0362 }