web/lib/Zend/Amf/Server.php
changeset 807 877f952ae2bd
parent 207 621fa6caec0c
child 1230 68c69c656a2c
equal deleted inserted replaced
805:5e7a0fedabdf 807:877f952ae2bd
    12  * obtain it through the world-wide-web, please send an email
    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.
    13  * to license@zend.com so we can send you a copy immediately.
    14  *
    14  *
    15  * @category   Zend
    15  * @category   Zend
    16  * @package    Zend_Amf
    16  * @package    Zend_Amf
    17  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
    17  * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
    18  * @license    http://framework.zend.com/license/new-bsd     New BSD License
    18  * @license    http://framework.zend.com/license/new-bsd     New BSD License
    19  * @version    $Id: Server.php 23256 2010-10-26 12:51:54Z alexander $
    19  * @version    $Id: Server.php 24593 2012-01-05 20:35:02Z matthew $
    20  */
    20  */
    21 
    21 
    22 /** @see Zend_Server_Interface */
    22 /** @see Zend_Server_Interface */
    23 require_once 'Zend/Server/Interface.php';
    23 require_once 'Zend/Server/Interface.php';
    24 
    24 
    50  * Zend Framework
    50  * Zend Framework
    51  *
    51  *
    52  * @todo       Make the reflection methods cache and autoload.
    52  * @todo       Make the reflection methods cache and autoload.
    53  * @package    Zend_Amf
    53  * @package    Zend_Amf
    54  * @subpackage Server
    54  * @subpackage Server
    55  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
    55  * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
    56  * @license    http://framework.zend.com/license/new-bsd     New BSD License
    56  * @license    http://framework.zend.com/license/new-bsd     New BSD License
    57  */
    57  */
    58 class Zend_Amf_Server implements Zend_Server_Interface
    58 class Zend_Amf_Server implements Zend_Server_Interface
    59 {
    59 {
    60     /**
    60     /**
   140     }
   140     }
   141 
   141 
   142     /**
   142     /**
   143      * Set authentication adapter
   143      * Set authentication adapter
   144      *
   144      *
       
   145      * If the authentication adapter implements a "getAcl()" method, populate 
       
   146      * the ACL of this instance with it (if none exists already).
       
   147      *
   145      * @param  Zend_Amf_Auth_Abstract $auth
   148      * @param  Zend_Amf_Auth_Abstract $auth
   146      * @return Zend_Amf_Server
   149      * @return Zend_Amf_Server
   147      */
   150      */
   148     public function setAuth(Zend_Amf_Auth_Abstract $auth)
   151     public function setAuth(Zend_Amf_Auth_Abstract $auth)
   149     {
   152     {
   150         $this->_auth = $auth;
   153         $this->_auth = $auth;
       
   154         if ((null === $this->getAcl()) && method_exists($auth, 'getAcl')) {
       
   155             $this->setAcl($auth->getAcl());
       
   156         }
   151         return $this;
   157         return $this;
   152     }
   158     }
   153    /**
   159    /**
   154      * Get authentication adapter
   160      * Get authentication adapter
   155      *
   161      *
   315                 } catch (Exception $e) {
   321                 } catch (Exception $e) {
   316                     require_once 'Zend/Amf/Server/Exception.php';
   322                     require_once 'Zend/Amf/Server/Exception.php';
   317                     throw new Zend_Amf_Server_Exception('Class "' . $className . '" does not exist: '.$e->getMessage(), 0, $e);
   323                     throw new Zend_Amf_Server_Exception('Class "' . $className . '" does not exist: '.$e->getMessage(), 0, $e);
   318                 }
   324                 }
   319                 // Add the new loaded class to the server.
   325                 // Add the new loaded class to the server.
       
   326                     require_once 'Zend/Amf/Server/Exception.php';
   320                 $this->setClass($className, $source);
   327                 $this->setClass($className, $source);
   321             }
   328             }
   322 
   329 
   323             if (!isset($this->_table[$qualifiedName])) {
   330             if (!isset($this->_table[$qualifiedName])) {
   324                 // Source is null or doesn't contain specified method
   331                 // Source is null or doesn't contain specified method
   331         $argv = $info->getInvokeArguments();
   338         $argv = $info->getInvokeArguments();
   332 
   339 
   333         if (0 < count($argv)) {
   340         if (0 < count($argv)) {
   334             $params = array_merge($params, $argv);
   341             $params = array_merge($params, $argv);
   335         }
   342         }
       
   343 
       
   344         $params = $this->_castParameters($info, $params);
   336 
   345 
   337         if ($info instanceof Zend_Server_Reflection_Function) {
   346         if ($info instanceof Zend_Server_Reflection_Function) {
   338             $func = $info->getName();
   347             $func = $info->getName();
   339             $this->_checkAcl(null, $func);
   348             $this->_checkAcl(null, $func);
   340             $return = call_user_func_array($func, $params);
   349             $return = call_user_func_array($func, $params);
   492         $response = $this->getResponse();
   501         $response = $this->getResponse();
   493 
   502 
   494         // set response encoding
   503         // set response encoding
   495         $response->setObjectEncoding($objectEncoding);
   504         $response->setObjectEncoding($objectEncoding);
   496 
   505 
   497         $responseBody = $request->getAmfBodies();
   506         // Authenticate, if we have credential headers
   498 
   507         $error   = false;
   499         $handleAuth = false;
   508         $headers = $request->getAmfHeaders();
   500         if ($this->_auth) {
   509         if (isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER]) 
   501             $headers = $request->getAmfHeaders();
   510             && isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->userid)
   502             if (isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER]) &&
   511             && isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->password)
   503                 isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->userid)) {
   512         ) {
   504                 $handleAuth = true;
   513             try {
       
   514                 if ($this->_handleAuth(
       
   515                         $headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->userid,
       
   516                         $headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->password
       
   517                 )) {
       
   518                     // use RequestPersistentHeader to clear credentials
       
   519                     $response->addAmfHeader(
       
   520                         new Zend_Amf_Value_MessageHeader(
       
   521                             Zend_Amf_Constants::PERSISTENT_HEADER,
       
   522                             false,
       
   523                             new Zend_Amf_Value_MessageHeader(
       
   524                                 Zend_Amf_Constants::CREDENTIALS_HEADER,
       
   525                                 false, null
       
   526                             )
       
   527                         )
       
   528                     );
       
   529                 }
       
   530             } catch (Exception $e) {
       
   531                 // Error during authentication; report it
       
   532                 $error = $this->_errorMessage(
       
   533                     $objectEncoding, 
       
   534                     '', 
       
   535                     $e->getMessage(),
       
   536                     $e->getTraceAsString(),
       
   537                     $e->getCode(),
       
   538                     $e->getLine()
       
   539                 );
       
   540                 $responseType = Zend_AMF_Constants::STATUS_METHOD;
   505             }
   541             }
   506         }
   542         }
   507 
   543 
   508         // Iterate through each of the service calls in the AMF request
   544         // Iterate through each of the service calls in the AMF request
   509         foreach($responseBody as $body)
   545         foreach($request->getAmfBodies() as $body)
   510         {
   546         {
       
   547             if ($error) {
       
   548                 // Error during authentication; just report it and be done
       
   549                 $responseURI = $body->getResponseURI() . $responseType;
       
   550                 $newBody     = new Zend_Amf_Value_MessageBody($responseURI, null, $error);
       
   551                 $response->addAmfBody($newBody);
       
   552                 continue;
       
   553             }
   511             try {
   554             try {
   512                 if ($handleAuth) {
   555                 switch ($objectEncoding) {
   513                     if ($this->_handleAuth(
   556                     case Zend_Amf_Constants::AMF0_OBJECT_ENCODING:
   514                         $headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->userid,
   557                         // AMF0 Object Encoding
   515                         $headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->password)) {
       
   516                         // use RequestPersistentHeader to clear credentials
       
   517                         $response->addAmfHeader(
       
   518                             new Zend_Amf_Value_MessageHeader(
       
   519                                 Zend_Amf_Constants::PERSISTENT_HEADER,
       
   520                                 false,
       
   521                                 new Zend_Amf_Value_MessageHeader(
       
   522                                     Zend_Amf_Constants::CREDENTIALS_HEADER,
       
   523                                     false, null)));
       
   524                         $handleAuth = false;
       
   525                     }
       
   526                 }
       
   527 
       
   528                 if ($objectEncoding == Zend_Amf_Constants::AMF0_OBJECT_ENCODING) {
       
   529                     // AMF0 Object Encoding
       
   530                     $targetURI = $body->getTargetURI();
       
   531                     $message = '';
       
   532 
       
   533                     // Split the target string into its values.
       
   534                     $source = substr($targetURI, 0, strrpos($targetURI, '.'));
       
   535 
       
   536                     if ($source) {
       
   537                         // Break off method name from namespace into source
       
   538                         $method = substr(strrchr($targetURI, '.'), 1);
       
   539                         $return = $this->_dispatch($method, $body->getData(), $source);
       
   540                     } else {
       
   541                         // Just have a method name.
       
   542                         $return = $this->_dispatch($targetURI, $body->getData());
       
   543                     }
       
   544                 } else {
       
   545                     // AMF3 read message type
       
   546                     $message = $body->getData();
       
   547                     if ($message instanceof Zend_Amf_Value_Messaging_CommandMessage) {
       
   548                         // async call with command message
       
   549                         $return = $this->_loadCommandMessage($message);
       
   550                     } elseif ($message instanceof Zend_Amf_Value_Messaging_RemotingMessage) {
       
   551                         require_once 'Zend/Amf/Value/Messaging/AcknowledgeMessage.php';
       
   552                         $return = new Zend_Amf_Value_Messaging_AcknowledgeMessage($message);
       
   553                         $return->body = $this->_dispatch($message->operation, $message->body, $message->source);
       
   554                     } else {
       
   555                         // Amf3 message sent with netConnection
       
   556                         $targetURI = $body->getTargetURI();
   558                         $targetURI = $body->getTargetURI();
       
   559                         $message = '';
   557 
   560 
   558                         // Split the target string into its values.
   561                         // Split the target string into its values.
   559                         $source = substr($targetURI, 0, strrpos($targetURI, '.'));
   562                         $source = substr($targetURI, 0, strrpos($targetURI, '.'));
   560 
   563 
   561                         if ($source) {
   564                         if ($source) {
   564                             $return = $this->_dispatch($method, $body->getData(), $source);
   567                             $return = $this->_dispatch($method, $body->getData(), $source);
   565                         } else {
   568                         } else {
   566                             // Just have a method name.
   569                             // Just have a method name.
   567                             $return = $this->_dispatch($targetURI, $body->getData());
   570                             $return = $this->_dispatch($targetURI, $body->getData());
   568                         }
   571                         }
   569                     }
   572                         break;
       
   573                     case Zend_Amf_Constants::AMF3_OBJECT_ENCODING:
       
   574                     default:
       
   575                         // AMF3 read message type
       
   576                         $message = $body->getData();
       
   577                         if ($message instanceof Zend_Amf_Value_Messaging_CommandMessage) {
       
   578                             // async call with command message
       
   579                             $return = $this->_loadCommandMessage($message);
       
   580                         } elseif ($message instanceof Zend_Amf_Value_Messaging_RemotingMessage) {
       
   581                             require_once 'Zend/Amf/Value/Messaging/AcknowledgeMessage.php';
       
   582                             $return = new Zend_Amf_Value_Messaging_AcknowledgeMessage($message);
       
   583                             $return->body = $this->_dispatch($message->operation, $message->body, $message->source);
       
   584                         } else {
       
   585                             // Amf3 message sent with netConnection
       
   586                             $targetURI = $body->getTargetURI();
       
   587 
       
   588                             // Split the target string into its values.
       
   589                             $source = substr($targetURI, 0, strrpos($targetURI, '.'));
       
   590 
       
   591                             if ($source) {
       
   592                                 // Break off method name from namespace into source
       
   593                                 $method = substr(strrchr($targetURI, '.'), 1);
       
   594                                 $return = $this->_dispatch($method, $body->getData(), $source);
       
   595                             } else {
       
   596                                 // Just have a method name.
       
   597                                 $return = $this->_dispatch($targetURI, $body->getData());
       
   598                             }
       
   599                         }
       
   600                         break;
   570                 }
   601                 }
   571                 $responseType = Zend_AMF_Constants::RESULT_METHOD;
   602                 $responseType = Zend_AMF_Constants::RESULT_METHOD;
   572             } catch (Exception $e) {
   603             } catch (Exception $e) {
   573                 $return = $this->_errorMessage($objectEncoding, $message,
   604                 $return = $this->_errorMessage($objectEncoding, $message,
   574                     $e->getMessage(), $e->getTraceAsString(),$e->getCode(),  $e->getLine());
   605                     $e->getMessage(), $e->getTraceAsString(),$e->getCode(),  $e->getLine());
   931      */
   962      */
   932     public function listMethods()
   963     public function listMethods()
   933     {
   964     {
   934         return array_keys($this->_table);
   965         return array_keys($this->_table);
   935     }
   966     }
       
   967 
       
   968     /**
       
   969      * Cast parameters
       
   970      *
       
   971      * Takes the provided parameters from the request, and attempts to cast them
       
   972      * to objects, if the prototype defines any as explicit object types
       
   973      * 
       
   974      * @param  Reflection $reflectionMethod 
       
   975      * @param  array $params 
       
   976      * @return array
       
   977      */
       
   978     protected function _castParameters($reflectionMethod, array $params)
       
   979     {
       
   980         $prototypes = $reflectionMethod->getPrototypes();
       
   981         $nonObjectTypes = array(
       
   982             'null',
       
   983             'mixed',
       
   984             'void',
       
   985             'unknown',
       
   986             'bool',
       
   987             'boolean',
       
   988             'number',
       
   989             'int',
       
   990             'integer',
       
   991             'double',
       
   992             'float',
       
   993             'string',
       
   994             'array',
       
   995             'object',
       
   996             'stdclass',
       
   997         );
       
   998         $types      = array();
       
   999         foreach ($prototypes as $prototype) {
       
  1000             foreach ($prototype->getParameters() as $parameter) {
       
  1001                 $type = $parameter->getType();
       
  1002                 if (in_array(strtolower($type), $nonObjectTypes)) {
       
  1003                     continue;
       
  1004                 }
       
  1005                 $position = $parameter->getPosition();
       
  1006                 $types[$position] = $type;
       
  1007             }
       
  1008         }
       
  1009 
       
  1010         if (empty($types)) {
       
  1011             return $params;
       
  1012         }
       
  1013 
       
  1014         foreach ($params as $position => $value) {
       
  1015             if (!isset($types[$position])) {
       
  1016                 // No specific type to cast to? done
       
  1017                 continue;
       
  1018             }
       
  1019 
       
  1020             $type = $types[$position];
       
  1021 
       
  1022             if (!class_exists($type)) {
       
  1023                 // Not a class, apparently. done
       
  1024                 continue;
       
  1025             }
       
  1026 
       
  1027             if ($value instanceof $type) {
       
  1028                 // Already of the right type? done
       
  1029                 continue;
       
  1030             }
       
  1031 
       
  1032             if (!is_array($value) && !is_object($value)) {
       
  1033                 // Can't cast scalars to objects easily; done
       
  1034                 continue;
       
  1035             }
       
  1036 
       
  1037             // Create instance, and loop through value to set
       
  1038             $object = new $type;
       
  1039             foreach ($value as $property => $defined) {
       
  1040                 $object->{$property} = $defined;
       
  1041             }
       
  1042 
       
  1043             $params[$position] = $object;
       
  1044         }
       
  1045 
       
  1046         return $params;
       
  1047     }
   936 }
  1048 }