|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00024 require_once 'Zend/Amf/Parse/Deserializer.php'; 00025 00027 require_once 'Zend/Amf/Parse/TypeLoader.php'; 00028 00040 class Zend_Amf_Parse_Amf3_Deserializer extends Zend_Amf_Parse_Deserializer 00041 { 00046 protected $_objectCount; 00047 00052 protected $_referenceObjects = array(); 00053 00058 protected $_referenceStrings = array(); 00059 00064 protected $_referenceDefinitions = array(); 00065 00077 public function readTypeMarker($typeMarker = null) 00078 { 00079 if(null === $typeMarker) { 00080 $typeMarker = $this->_stream->readByte(); 00081 } 00082 00083 switch($typeMarker) { 00084 case Zend_Amf_Constants::AMF3_UNDEFINED: 00085 return null; 00086 case Zend_Amf_Constants::AMF3_NULL: 00087 return null; 00088 case Zend_Amf_Constants::AMF3_BOOLEAN_FALSE: 00089 return false; 00090 case Zend_Amf_Constants::AMF3_BOOLEAN_TRUE: 00091 return true; 00092 case Zend_Amf_Constants::AMF3_INTEGER: 00093 return $this->readInteger(); 00094 case Zend_Amf_Constants::AMF3_NUMBER: 00095 return $this->_stream->readDouble(); 00096 case Zend_Amf_Constants::AMF3_STRING: 00097 return $this->readString(); 00098 case Zend_Amf_Constants::AMF3_DATE: 00099 return $this->readDate(); 00100 case Zend_Amf_Constants::AMF3_ARRAY: 00101 return $this->readArray(); 00102 case Zend_Amf_Constants::AMF3_OBJECT: 00103 return $this->readObject(); 00104 case Zend_Amf_Constants::AMF3_XML: 00105 case Zend_Amf_Constants::AMF3_XMLSTRING: 00106 return $this->readXmlString(); 00107 case Zend_Amf_Constants::AMF3_BYTEARRAY: 00108 return $this->readString(); 00109 default: 00110 require_once 'Zend/Amf/Exception.php'; 00111 throw new Zend_Amf_Exception('Unsupported type marker: ' . $typeMarker); 00112 } 00113 } 00114 00134 public function readInteger() 00135 { 00136 $count = 1; 00137 $intReference = $this->_stream->readByte(); 00138 $result = 0; 00139 while ((($intReference & 0x80) != 0) && $count < 4) { 00140 $result <<= 7; 00141 $result |= ($intReference & 0x7f); 00142 $intReference = $this->_stream->readByte(); 00143 $count++; 00144 } 00145 if ($count < 4) { 00146 $result <<= 7; 00147 $result |= $intReference; 00148 } else { 00149 // Use all 8 bits from the 4th byte 00150 $result <<= 8; 00151 $result |= $intReference; 00152 00153 // Check if the integer should be negative 00154 if (($result & 0x10000000) != 0) { 00155 //and extend the sign bit 00156 $result |= ~0xFFFFFFF; 00157 } 00158 } 00159 return $result; 00160 } 00161 00176 public function readString() 00177 { 00178 $stringReference = $this->readInteger(); 00179 00180 //Check if this is a reference string 00181 if (($stringReference & 0x01) == 0) { 00182 // reference string 00183 $stringReference = $stringReference >> 1; 00184 if ($stringReference >= count($this->_referenceStrings)) { 00185 require_once 'Zend/Amf/Exception.php'; 00186 throw new Zend_Amf_Exception('Undefined string reference: ' . $stringReference); 00187 } 00188 // reference string found 00189 return $this->_referenceStrings[$stringReference]; 00190 } 00191 00192 $length = $stringReference >> 1; 00193 if ($length) { 00194 $string = $this->_stream->readBytes($length); 00195 $this->_referenceStrings[] = $string; 00196 } else { 00197 $string = ""; 00198 } 00199 return $string; 00200 } 00201 00213 public function readDate() 00214 { 00215 $dateReference = $this->readInteger(); 00216 if (($dateReference & 0x01) == 0) { 00217 $dateReference = $dateReference >> 1; 00218 if ($dateReference>=count($this->_referenceObjects)) { 00219 require_once 'Zend/Amf/Exception.php'; 00220 throw new Zend_Amf_Exception('Undefined date reference: ' . $dateReference); 00221 } 00222 return $this->_referenceObjects[$dateReference]; 00223 } 00224 00225 $timestamp = floor($this->_stream->readDouble() / 1000); 00226 00227 require_once 'Zend/Date.php'; 00228 $dateTime = new Zend_Date((int) $timestamp); 00229 $this->_referenceObjects[] = $dateTime; 00230 return $dateTime; 00231 } 00232 00240 public function readArray() 00241 { 00242 $arrayReference = $this->readInteger(); 00243 if (($arrayReference & 0x01)==0){ 00244 $arrayReference = $arrayReference >> 1; 00245 if ($arrayReference>=count($this->_referenceObjects)) { 00246 require_once 'Zend/Amf/Exception.php'; 00247 throw new Zend_Amf_Exception('Unknow array reference: ' . $arrayReference); 00248 } 00249 return $this->_referenceObjects[$arrayReference]; 00250 } 00251 00252 // Create a holder for the array in the reference list 00253 $data = array(); 00254 $this->_referenceObjects[] =& $data; 00255 $key = $this->readString(); 00256 00257 // Iterating for string based keys. 00258 while ($key != '') { 00259 $data[$key] = $this->readTypeMarker(); 00260 $key = $this->readString(); 00261 } 00262 00263 $arrayReference = $arrayReference >>1; 00264 00265 //We have a dense array 00266 for ($i=0; $i < $arrayReference; $i++) { 00267 $data[] = $this->readTypeMarker(); 00268 } 00269 00270 return $data; 00271 } 00272 00279 public function readObject() 00280 { 00281 $traitsInfo = $this->readInteger(); 00282 $storedObject = ($traitsInfo & 0x01)==0; 00283 $traitsInfo = $traitsInfo >> 1; 00284 00285 // Check if the Object is in the stored Objects reference table 00286 if ($storedObject) { 00287 $ref = $traitsInfo; 00288 if (!isset($this->_referenceObjects[$ref])) { 00289 require_once 'Zend/Amf/Exception.php'; 00290 throw new Zend_Amf_Exception('Unknown Object reference: ' . $ref); 00291 } 00292 $returnObject = $this->_referenceObjects[$ref]; 00293 } else { 00294 // Check if the Object is in the stored Definitions reference table 00295 $storedClass = ($traitsInfo & 0x01) == 0; 00296 $traitsInfo = $traitsInfo >> 1; 00297 if ($storedClass) { 00298 $ref = $traitsInfo; 00299 if (!isset($this->_referenceDefinitions[$ref])) { 00300 require_once 'Zend/Amf/Exception.php'; 00301 throw new Zend_Amf_Exception('Unknows Definition reference: '. $ref); 00302 } 00303 // Populate the reference attributes 00304 $className = $this->_referenceDefinitions[$ref]['className']; 00305 $encoding = $this->_referenceDefinitions[$ref]['encoding']; 00306 $propertyNames = $this->_referenceDefinitions[$ref]['propertyNames']; 00307 } else { 00308 // The class was not in the reference tables. Start reading rawdata to build traits. 00309 // Create a traits table. Zend_Amf_Value_TraitsInfo would be ideal 00310 $className = $this->readString(); 00311 $encoding = $traitsInfo & 0x03; 00312 $propertyNames = array(); 00313 $traitsInfo = $traitsInfo >> 2; 00314 } 00315 00316 // We now have the object traits defined in variables. Time to go to work: 00317 if (!$className) { 00318 // No class name generic object 00319 $returnObject = new stdClass(); 00320 } else { 00321 // Defined object 00322 // Typed object lookup against registered classname maps 00323 if ($loader = Zend_Amf_Parse_TypeLoader::loadType($className)) { 00324 $returnObject = new $loader(); 00325 } else { 00326 //user defined typed object 00327 require_once 'Zend/Amf/Exception.php'; 00328 throw new Zend_Amf_Exception('Typed object not found: '. $className . ' '); 00329 } 00330 } 00331 00332 // Add the Object to the reference table 00333 $this->_referenceObjects[] = $returnObject; 00334 00335 $properties = array(); // clear value 00336 // Check encoding types for additional processing. 00337 switch ($encoding) { 00338 case (Zend_Amf_Constants::ET_EXTERNAL): 00339 // Externalizable object such as {ArrayCollection} and {ObjectProxy} 00340 if (!$storedClass) { 00341 $this->_referenceDefinitions[] = array( 00342 'className' => $className, 00343 'encoding' => $encoding, 00344 'propertyNames' => $propertyNames, 00345 ); 00346 } 00347 $returnObject->externalizedData = $this->readTypeMarker(); 00348 break; 00349 case (Zend_Amf_Constants::ET_DYNAMIC): 00350 // used for Name-value encoding 00351 if (!$storedClass) { 00352 $this->_referenceDefinitions[] = array( 00353 'className' => $className, 00354 'encoding' => $encoding, 00355 'propertyNames' => $propertyNames, 00356 ); 00357 } 00358 // not a reference object read name value properties from byte stream 00359 do { 00360 $property = $this->readString(); 00361 if ($property != "") { 00362 $propertyNames[] = $property; 00363 $properties[$property] = $this->readTypeMarker(); 00364 } 00365 } while ($property !=""); 00366 break; 00367 default: 00368 // basic property list object. 00369 if (!$storedClass) { 00370 $count = $traitsInfo; // Number of properties in the list 00371 for($i=0; $i< $count; $i++) { 00372 $propertyNames[] = $this->readString(); 00373 } 00374 // Add a reference to the class. 00375 $this->_referenceDefinitions[] = array( 00376 'className' => $className, 00377 'encoding' => $encoding, 00378 'propertyNames' => $propertyNames, 00379 ); 00380 } 00381 foreach ($propertyNames as $property) { 00382 $properties[$property] = $this->readTypeMarker(); 00383 } 00384 break; 00385 } 00386 00387 // Add properties back to the return object. 00388 foreach($properties as $key=>$value) { 00389 if($key) { 00390 $returnObject->$key = $value; 00391 } 00392 } 00393 00394 00395 } 00396 00397 if ($returnObject instanceof Zend_Amf_Value_Messaging_ArrayCollection) { 00398 if (isset($returnObject->externalizedData)) { 00399 $returnObject = $returnObject->externalizedData; 00400 } else { 00401 $returnObject = get_object_vars($returnObject); 00402 } 00403 } 00404 00405 return $returnObject; 00406 } 00407 00414 public function readXmlString() 00415 { 00416 $xmlReference = $this->readInteger(); 00417 $length = $xmlReference >> 1; 00418 $string = $this->_stream->readBytes($length); 00419 return simplexml_load_string($string); 00420 } 00421 }