web/lib/Zend/Amf/Server.php
changeset 807 877f952ae2bd
parent 207 621fa6caec0c
child 1230 68c69c656a2c
--- 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;
+    }
 }