diff -r 5e7a0fedabdf -r 877f952ae2bd web/lib/Zend/Amf/Server.php --- a/web/lib/Zend/Amf/Server.php Thu Mar 21 17:31:31 2013 +0100 +++ b/web/lib/Zend/Amf/Server.php Thu Mar 21 19:50:53 2013 +0100 @@ -14,9 +14,9 @@ * * @category Zend * @package Zend_Amf - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License - * @version $Id: Server.php 23256 2010-10-26 12:51:54Z alexander $ + * @version $Id: Server.php 24593 2012-01-05 20:35:02Z matthew $ */ /** @see Zend_Server_Interface */ @@ -52,7 +52,7 @@ * @todo Make the reflection methods cache and autoload. * @package Zend_Amf * @subpackage Server - * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Amf_Server implements Zend_Server_Interface @@ -142,12 +142,18 @@ /** * Set authentication adapter * + * If the authentication adapter implements a "getAcl()" method, populate + * the ACL of this instance with it (if none exists already). + * * @param Zend_Amf_Auth_Abstract $auth * @return Zend_Amf_Server */ public function setAuth(Zend_Amf_Auth_Abstract $auth) { $this->_auth = $auth; + if ((null === $this->getAcl()) && method_exists($auth, 'getAcl')) { + $this->setAcl($auth->getAcl()); + } return $this; } /** @@ -317,6 +323,7 @@ throw new Zend_Amf_Server_Exception('Class "' . $className . '" does not exist: '.$e->getMessage(), 0, $e); } // Add the new loaded class to the server. + require_once 'Zend/Amf/Server/Exception.php'; $this->setClass($className, $source); } @@ -334,6 +341,8 @@ $params = array_merge($params, $argv); } + $params = $this->_castParameters($info, $params); + if ($info instanceof Zend_Server_Reflection_Function) { $func = $info->getName(); $this->_checkAcl(null, $func); @@ -494,66 +503,60 @@ // set response encoding $response->setObjectEncoding($objectEncoding); - $responseBody = $request->getAmfBodies(); - - $handleAuth = false; - if ($this->_auth) { - $headers = $request->getAmfHeaders(); - if (isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER]) && - isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->userid)) { - $handleAuth = true; + // Authenticate, if we have credential headers + $error = false; + $headers = $request->getAmfHeaders(); + if (isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER]) + && isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->userid) + && isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->password) + ) { + try { + if ($this->_handleAuth( + $headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->userid, + $headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->password + )) { + // use RequestPersistentHeader to clear credentials + $response->addAmfHeader( + new Zend_Amf_Value_MessageHeader( + Zend_Amf_Constants::PERSISTENT_HEADER, + false, + new Zend_Amf_Value_MessageHeader( + Zend_Amf_Constants::CREDENTIALS_HEADER, + false, null + ) + ) + ); + } + } catch (Exception $e) { + // Error during authentication; report it + $error = $this->_errorMessage( + $objectEncoding, + '', + $e->getMessage(), + $e->getTraceAsString(), + $e->getCode(), + $e->getLine() + ); + $responseType = Zend_AMF_Constants::STATUS_METHOD; } } // Iterate through each of the service calls in the AMF request - foreach($responseBody as $body) + foreach($request->getAmfBodies() as $body) { + if ($error) { + // Error during authentication; just report it and be done + $responseURI = $body->getResponseURI() . $responseType; + $newBody = new Zend_Amf_Value_MessageBody($responseURI, null, $error); + $response->addAmfBody($newBody); + continue; + } try { - if ($handleAuth) { - if ($this->_handleAuth( - $headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->userid, - $headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->password)) { - // use RequestPersistentHeader to clear credentials - $response->addAmfHeader( - new Zend_Amf_Value_MessageHeader( - Zend_Amf_Constants::PERSISTENT_HEADER, - false, - new Zend_Amf_Value_MessageHeader( - Zend_Amf_Constants::CREDENTIALS_HEADER, - false, null))); - $handleAuth = false; - } - } - - if ($objectEncoding == Zend_Amf_Constants::AMF0_OBJECT_ENCODING) { - // AMF0 Object Encoding - $targetURI = $body->getTargetURI(); - $message = ''; - - // Split the target string into its values. - $source = substr($targetURI, 0, strrpos($targetURI, '.')); - - if ($source) { - // Break off method name from namespace into source - $method = substr(strrchr($targetURI, '.'), 1); - $return = $this->_dispatch($method, $body->getData(), $source); - } else { - // Just have a method name. - $return = $this->_dispatch($targetURI, $body->getData()); - } - } else { - // AMF3 read message type - $message = $body->getData(); - if ($message instanceof Zend_Amf_Value_Messaging_CommandMessage) { - // async call with command message - $return = $this->_loadCommandMessage($message); - } elseif ($message instanceof Zend_Amf_Value_Messaging_RemotingMessage) { - require_once 'Zend/Amf/Value/Messaging/AcknowledgeMessage.php'; - $return = new Zend_Amf_Value_Messaging_AcknowledgeMessage($message); - $return->body = $this->_dispatch($message->operation, $message->body, $message->source); - } else { - // Amf3 message sent with netConnection + switch ($objectEncoding) { + case Zend_Amf_Constants::AMF0_OBJECT_ENCODING: + // AMF0 Object Encoding $targetURI = $body->getTargetURI(); + $message = ''; // Split the target string into its values. $source = substr($targetURI, 0, strrpos($targetURI, '.')); @@ -566,7 +569,35 @@ // Just have a method name. $return = $this->_dispatch($targetURI, $body->getData()); } - } + break; + case Zend_Amf_Constants::AMF3_OBJECT_ENCODING: + default: + // AMF3 read message type + $message = $body->getData(); + if ($message instanceof Zend_Amf_Value_Messaging_CommandMessage) { + // async call with command message + $return = $this->_loadCommandMessage($message); + } elseif ($message instanceof Zend_Amf_Value_Messaging_RemotingMessage) { + require_once 'Zend/Amf/Value/Messaging/AcknowledgeMessage.php'; + $return = new Zend_Amf_Value_Messaging_AcknowledgeMessage($message); + $return->body = $this->_dispatch($message->operation, $message->body, $message->source); + } else { + // Amf3 message sent with netConnection + $targetURI = $body->getTargetURI(); + + // Split the target string into its values. + $source = substr($targetURI, 0, strrpos($targetURI, '.')); + + if ($source) { + // Break off method name from namespace into source + $method = substr(strrchr($targetURI, '.'), 1); + $return = $this->_dispatch($method, $body->getData(), $source); + } else { + // Just have a method name. + $return = $this->_dispatch($targetURI, $body->getData()); + } + } + break; } $responseType = Zend_AMF_Constants::RESULT_METHOD; } catch (Exception $e) { @@ -933,4 +964,85 @@ { return array_keys($this->_table); } + + /** + * Cast parameters + * + * Takes the provided parameters from the request, and attempts to cast them + * to objects, if the prototype defines any as explicit object types + * + * @param Reflection $reflectionMethod + * @param array $params + * @return array + */ + protected function _castParameters($reflectionMethod, array $params) + { + $prototypes = $reflectionMethod->getPrototypes(); + $nonObjectTypes = array( + 'null', + 'mixed', + 'void', + 'unknown', + 'bool', + 'boolean', + 'number', + 'int', + 'integer', + 'double', + 'float', + 'string', + 'array', + 'object', + 'stdclass', + ); + $types = array(); + foreach ($prototypes as $prototype) { + foreach ($prototype->getParameters() as $parameter) { + $type = $parameter->getType(); + if (in_array(strtolower($type), $nonObjectTypes)) { + continue; + } + $position = $parameter->getPosition(); + $types[$position] = $type; + } + } + + if (empty($types)) { + return $params; + } + + foreach ($params as $position => $value) { + if (!isset($types[$position])) { + // No specific type to cast to? done + continue; + } + + $type = $types[$position]; + + if (!class_exists($type)) { + // Not a class, apparently. done + continue; + } + + if ($value instanceof $type) { + // Already of the right type? done + continue; + } + + if (!is_array($value) && !is_object($value)) { + // Can't cast scalars to objects easily; done + continue; + } + + // Create instance, and loop through value to set + $object = new $type; + foreach ($value as $property => $defined) { + $object->{$property} = $defined; + } + + $params[$position] = $object; + } + + return $params; + } }