Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/lib/zend/Zend/Amf/Server.php
Go to the documentation of this file.
00001 <?php
00023 require_once 'Zend/Server/Interface.php';
00024 
00026 require_once 'Zend/Server/Reflection.php';
00027 
00029 require_once 'Zend/Amf/Constants.php';
00030 
00032 require_once 'Zend/Amf/Value/MessageBody.php';
00033 
00035 require_once 'Zend/Amf/Value/MessageHeader.php';
00036 
00038 require_once 'Zend/Amf/Value/Messaging/CommandMessage.php';
00039 
00041 require_once 'Zend/Loader/PluginLoader.php';
00042 
00044 require_once 'Zend/Amf/Parse/TypeLoader.php';
00045 
00047 require_once 'Zend/Auth.php';
00058 class Zend_Amf_Server implements Zend_Server_Interface
00059 {
00064     protected $_methods = array();
00065 
00073     protected $_classAllowed = array();
00074 
00079     protected $_loader;
00080 
00084     protected $_production = true;
00085 
00090     protected $_request = null;
00091 
00096     protected $_response;
00097 
00102     protected $_table = array();
00103 
00108     protected $_session = false;
00109 
00114     protected $_sesionNamespace = 'zend_amf';
00115 
00120     protected $_sessionName = 'PHPSESSID';
00121 
00127     protected $_auth;
00133     protected $_acl;
00137     public function __construct()
00138     {
00139         Zend_Amf_Parse_TypeLoader::setResourceLoader(new Zend_Loader_PluginLoader(array("Zend_Amf_Parse_Resource" => "Zend/Amf/Parse/Resource")));
00140     }
00141 
00148     public function setAuth(Zend_Amf_Auth_Abstract $auth)
00149     {
00150         $this->_auth = $auth;
00151         return $this;
00152     }
00158     public function getAuth()
00159     {
00160         return $this->_auth;
00161     }
00162 
00169     public function setAcl(Zend_Acl $acl)
00170     {
00171         $this->_acl = $acl;
00172         return $this;
00173     }
00179     public function getAcl()
00180     {
00181         return $this->_acl;
00182     }
00183 
00190     public function setProduction($flag)
00191     {
00192         $this->_production = (bool) $flag;
00193         return $this;
00194     }
00195 
00201     public function isProduction()
00202     {
00203         return $this->_production;
00204     }
00205 
00210     public function setSession($namespace = 'Zend_Amf')
00211     {
00212         require_once 'Zend/Session.php';
00213         $this->_session = true;
00214         $this->_sesionNamespace = new Zend_Session_Namespace($namespace);
00215         return $this;
00216     }
00217 
00222     public function isSession()
00223     {
00224         return $this->_session;
00225     }
00226 
00234     protected function _checkAcl($object, $function)
00235     {
00236         if(!$this->_acl) {
00237             return true;
00238         }
00239         if($object) {
00240             $class = is_object($object)?get_class($object):$object;
00241             if(!$this->_acl->has($class)) {
00242                 require_once 'Zend/Acl/Resource.php';
00243                 $this->_acl->add(new Zend_Acl_Resource($class));
00244             }
00245             $call = array($object, "initAcl");
00246             if(is_callable($call) && !call_user_func($call, $this->_acl)) {
00247                 // if initAcl returns false, no ACL check
00248                 return true;
00249             }
00250         } else {
00251             $class = null;
00252         }
00253 
00254         $auth = Zend_Auth::getInstance();
00255         if($auth->hasIdentity()) {
00256             $role = $auth->getIdentity()->role;
00257         } else {
00258             if($this->_acl->hasRole(Zend_Amf_Constants::GUEST_ROLE)) {
00259                 $role = Zend_Amf_Constants::GUEST_ROLE;
00260             } else {
00261                 require_once 'Zend/Amf/Server/Exception.php';
00262                 throw new Zend_Amf_Server_Exception("Unauthenticated access not allowed");
00263             }
00264         }
00265         if($this->_acl->isAllowed($role, $class, $function)) {
00266             return true;
00267         } else {
00268             require_once 'Zend/Amf/Server/Exception.php';
00269             throw new Zend_Amf_Server_Exception("Access not allowed");
00270         }
00271     }
00272 
00278     protected function getLoader()
00279     {
00280         if(empty($this->_loader)) {
00281             require_once 'Zend/Loader/PluginLoader.php';
00282             $this->_loader = new Zend_Loader_PluginLoader();
00283         }
00284         return $this->_loader;
00285     }
00286 
00296     protected function _dispatch($method, $params = null, $source = null)
00297     {
00298         if($source) {
00299             if(($mapped = Zend_Amf_Parse_TypeLoader::getMappedClassName($source)) !== false) {
00300                 $source = $mapped;
00301             }
00302         }
00303         $qualifiedName = empty($source) ? $method : $source.".".$method;
00304 
00305         if (!isset($this->_table[$qualifiedName])) {
00306             // if source is null a method that was not defined was called.
00307             if ($source) {
00308                 $className = str_replace(".", "_", $source);
00309                 if(class_exists($className, false) && !isset($this->_classAllowed[$className])) {
00310                     require_once 'Zend/Amf/Server/Exception.php';
00311                     throw new Zend_Amf_Server_Exception('Can not call "' . $className . '" - use setClass()');
00312                 }
00313                 try {
00314                     $this->getLoader()->load($className);
00315                 } catch (Exception $e) {
00316                     require_once 'Zend/Amf/Server/Exception.php';
00317                     throw new Zend_Amf_Server_Exception('Class "' . $className . '" does not exist: '.$e->getMessage(), 0, $e);
00318                 }
00319                 // Add the new loaded class to the server.
00320                 $this->setClass($className, $source);
00321             } else {
00322                 require_once 'Zend/Amf/Server/Exception.php';
00323                 throw new Zend_Amf_Server_Exception('Method "' . $method . '" does not exist');
00324             }
00325         }
00326 
00327         $info = $this->_table[$qualifiedName];
00328         $argv = $info->getInvokeArguments();
00329 
00330         if (0 < count($argv)) {
00331             $params = array_merge($params, $argv);
00332         }
00333 
00334         if ($info instanceof Zend_Server_Reflection_Function) {
00335             $func = $info->getName();
00336             $this->_checkAcl(null, $func);
00337             $return = call_user_func_array($func, $params);
00338         } elseif ($info instanceof Zend_Server_Reflection_Method) {
00339             // Get class
00340             $class = $info->getDeclaringClass()->getName();
00341             if ('static' == $info->isStatic()) {
00342                 // for some reason, invokeArgs() does not work the same as
00343                 // invoke(), and expects the first argument to be an object.
00344                 // So, using a callback if the method is static.
00345                 $this->_checkAcl($class, $info->getName());
00346                 $return = call_user_func_array(array($class, $info->getName()), $params);
00347             } else {
00348                 // Object methods
00349                 try {
00350                     $object = $info->getDeclaringClass()->newInstance();
00351                 } catch (Exception $e) {
00352                     require_once 'Zend/Amf/Server/Exception.php';
00353                     throw new Zend_Amf_Server_Exception('Error instantiating class ' . $class . ' to invoke method ' . $info->getName() . ': '.$e->getMessage(), 621, $e);
00354                 }
00355                 $this->_checkAcl($object, $info->getName());
00356                 $return = $info->invokeArgs($object, $params);
00357             }
00358         } else {
00359             require_once 'Zend/Amf/Server/Exception.php';
00360             throw new Zend_Amf_Server_Exception('Method missing implementation ' . get_class($info));
00361         }
00362 
00363         return $return;
00364     }
00365 
00375     protected function _loadCommandMessage(Zend_Amf_Value_Messaging_CommandMessage $message)
00376     {
00377         require_once 'Zend/Amf/Value/Messaging/AcknowledgeMessage.php';
00378         switch($message->operation) {
00379             case Zend_Amf_Value_Messaging_CommandMessage::DISCONNECT_OPERATION :
00380             case Zend_Amf_Value_Messaging_CommandMessage::CLIENT_PING_OPERATION :
00381                 $return = new Zend_Amf_Value_Messaging_AcknowledgeMessage($message);
00382                 break;
00383             case Zend_Amf_Value_Messaging_CommandMessage::LOGIN_OPERATION :
00384                 $data = explode(':', base64_decode($message->body));
00385                 $userid = $data[0];
00386                 $password = isset($data[1])?$data[1]:"";
00387                 if(empty($userid)) {
00388                     require_once 'Zend/Amf/Server/Exception.php';
00389                     throw new Zend_Amf_Server_Exception('Login failed: username not supplied');
00390                 }
00391                 if(!$this->_handleAuth($userid, $password)) {
00392                     require_once 'Zend/Amf/Server/Exception.php';
00393                     throw new Zend_Amf_Server_Exception('Authentication failed');
00394                 }
00395                 $return = new Zend_Amf_Value_Messaging_AcknowledgeMessage($message);
00396                 break;
00397            case Zend_Amf_Value_Messaging_CommandMessage::LOGOUT_OPERATION :
00398                 if($this->_auth) {
00399                     Zend_Auth::getInstance()->clearIdentity();
00400                 }
00401                 $return = new Zend_Amf_Value_Messaging_AcknowledgeMessage($message);
00402                 break;
00403             default :
00404                 require_once 'Zend/Amf/Server/Exception.php';
00405                 throw new Zend_Amf_Server_Exception('CommandMessage::' . $message->operation . ' not implemented');
00406                 break;
00407         }
00408         return $return;
00409     }
00410 
00422     protected function _errorMessage($objectEncoding, $message, $description, $detail, $code, $line)
00423     {
00424         $return = null;
00425         switch ($objectEncoding) {
00426             case Zend_Amf_Constants::AMF0_OBJECT_ENCODING :
00427                 return array (
00428                         'description' => ($this->isProduction ()) ? '' : $description,
00429                         'detail' => ($this->isProduction ()) ? '' : $detail,
00430                         'line' => ($this->isProduction ()) ? 0 : $line,
00431                         'code' => $code
00432                 );
00433             case Zend_Amf_Constants::AMF3_OBJECT_ENCODING :
00434                 require_once 'Zend/Amf/Value/Messaging/ErrorMessage.php';
00435                 $return = new Zend_Amf_Value_Messaging_ErrorMessage ( $message );
00436                 $return->faultString = $this->isProduction () ? '' : $description;
00437                 $return->faultCode = $code;
00438                 $return->faultDetail = $this->isProduction () ? '' : $detail;
00439                 break;
00440         }
00441         return $return;
00442     }
00443 
00451     protected function _handleAuth( $userid,  $password)
00452     {
00453         if (!$this->_auth) {
00454             return true;
00455         }
00456         $this->_auth->setCredentials($userid, $password);
00457         $auth = Zend_Auth::getInstance();
00458         $result = $auth->authenticate($this->_auth);
00459         if ($result->isValid()) {
00460             if (!$this->isSession()) {
00461                 $this->setSession();
00462             }
00463             return true;
00464         } else {
00465             // authentication failed, good bye
00466             require_once 'Zend/Amf/Server/Exception.php';
00467             throw new Zend_Amf_Server_Exception(
00468                 "Authentication failed: " . join("\n",
00469                     $result->getMessages()), $result->getCode());
00470         }
00471 
00472     }
00473 
00483     protected function _handle(Zend_Amf_Request $request)
00484     {
00485         // Get the object encoding of the request.
00486         $objectEncoding = $request->getObjectEncoding();
00487 
00488         // create a response object to place the output from the services.
00489         $response = $this->getResponse();
00490 
00491         // set response encoding
00492         $response->setObjectEncoding($objectEncoding);
00493 
00494         $responseBody = $request->getAmfBodies();
00495 
00496         $handleAuth = false;
00497         if ($this->_auth) {
00498             $headers = $request->getAmfHeaders();
00499             if (isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER]) &&
00500                 isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->userid)) {
00501                 $handleAuth = true;
00502             }
00503         }
00504 
00505         // Iterate through each of the service calls in the AMF request
00506         foreach($responseBody as $body)
00507         {
00508             try {
00509                 if ($handleAuth) {
00510                     if ($this->_handleAuth(
00511                         $headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->userid,
00512                         $headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->password)) {
00513                         // use RequestPersistentHeader to clear credentials
00514                         $response->addAmfHeader(
00515                             new Zend_Amf_Value_MessageHeader(
00516                                 Zend_Amf_Constants::PERSISTENT_HEADER,
00517                                 false,
00518                                 new Zend_Amf_Value_MessageHeader(
00519                                     Zend_Amf_Constants::CREDENTIALS_HEADER,
00520                                     false, null)));
00521                         $handleAuth = false;
00522                     }
00523                 }
00524 
00525                 if ($objectEncoding == Zend_Amf_Constants::AMF0_OBJECT_ENCODING) {
00526                     // AMF0 Object Encoding
00527                     $targetURI = $body->getTargetURI();
00528                     $message = '';
00529 
00530                     // Split the target string into its values.
00531                     $source = substr($targetURI, 0, strrpos($targetURI, '.'));
00532 
00533                     if ($source) {
00534                         // Break off method name from namespace into source
00535                         $method = substr(strrchr($targetURI, '.'), 1);
00536                         $return = $this->_dispatch($method, $body->getData(), $source);
00537                     } else {
00538                         // Just have a method name.
00539                         $return = $this->_dispatch($targetURI, $body->getData());
00540                     }
00541                 } else {
00542                     // AMF3 read message type
00543                     $message = $body->getData();
00544                     if ($message instanceof Zend_Amf_Value_Messaging_CommandMessage) {
00545                         // async call with command message
00546                         $return = $this->_loadCommandMessage($message);
00547                     } elseif ($message instanceof Zend_Amf_Value_Messaging_RemotingMessage) {
00548                         require_once 'Zend/Amf/Value/Messaging/AcknowledgeMessage.php';
00549                         $return = new Zend_Amf_Value_Messaging_AcknowledgeMessage($message);
00550                         $return->body = $this->_dispatch($message->operation, $message->body, $message->source);
00551                     } else {
00552                         // Amf3 message sent with netConnection
00553                         $targetURI = $body->getTargetURI();
00554 
00555                         // Split the target string into its values.
00556                         $source = substr($targetURI, 0, strrpos($targetURI, '.'));
00557 
00558                         if ($source) {
00559                             // Break off method name from namespace into source
00560                             $method = substr(strrchr($targetURI, '.'), 1);
00561                             $return = $this->_dispatch($method, $body->getData(), $source);
00562                         } else {
00563                             // Just have a method name.
00564                             $return = $this->_dispatch($targetURI, $body->getData());
00565                         }
00566                     }
00567                 }
00568                 $responseType = Zend_AMF_Constants::RESULT_METHOD;
00569             } catch (Exception $e) {
00570                 $return = $this->_errorMessage($objectEncoding, $message,
00571                     $e->getMessage(), $e->getTraceAsString(),$e->getCode(),  $e->getLine());
00572                 $responseType = Zend_AMF_Constants::STATUS_METHOD;
00573             }
00574 
00575             $responseURI = $body->getResponseURI() . $responseType;
00576             $newBody     = new Zend_Amf_Value_MessageBody($responseURI, null, $return);
00577             $response->addAmfBody($newBody);
00578         }
00579         // Add a session header to the body if session is requested.
00580         if($this->isSession()) {
00581            $currentID = session_id();
00582            $joint = "?";
00583            if(isset($_SERVER['QUERY_STRING'])) {
00584                if(!strpos($_SERVER['QUERY_STRING'], $currentID) !== FALSE) {
00585                    if(strrpos($_SERVER['QUERY_STRING'], "?") !== FALSE) {
00586                        $joint = "&";
00587                    }
00588                }
00589            }
00590 
00591             // create a new AMF message header with the session id as a variable.
00592             $sessionValue = $joint . $this->_sessionName . "=" . $currentID;
00593             $sessionHeader = new Zend_Amf_Value_MessageHeader(Zend_Amf_Constants::URL_APPEND_HEADER, false, $sessionValue);
00594             $response->addAmfHeader($sessionHeader);
00595         }
00596 
00597         // serialize the response and return serialized body.
00598         $response->finalize();
00599     }
00600 
00607     public function handle($request = null)
00608     {
00609         // Check if request was passed otherwise get it from the server
00610         if (is_null($request) || !$request instanceof Zend_Amf_Request) {
00611             $request = $this->getRequest();
00612         } else {
00613             $this->setRequest($request);
00614         }
00615         if ($this->isSession()) {
00616              // Check if a session is being sent from the amf call
00617              if (isset($_COOKIE[$this->_sessionName])) {
00618                  session_id($_COOKIE[$this->_sessionName]);
00619              }
00620         }
00621 
00622         // Check for errors that may have happend in deserialization of Request.
00623         try {
00624             // Take converted PHP objects and handle service call.
00625             // Serialize to Zend_Amf_response for output stream
00626             $this->_handle($request);
00627             $response = $this->getResponse();
00628         } catch (Exception $e) {
00629             // Handle any errors in the serialization and service  calls.
00630             require_once 'Zend/Amf/Server/Exception.php';
00631             throw new Zend_Amf_Server_Exception('Handle error: ' . $e->getMessage() . ' ' . $e->getLine(), 0, $e);
00632         }
00633 
00634         // Return the Amf serialized output string
00635         return $response;
00636     }
00637 
00644     public function setRequest($request)
00645     {
00646         if (is_string($request) && class_exists($request)) {
00647             $request = new $request();
00648             if (!$request instanceof Zend_Amf_Request) {
00649                 require_once 'Zend/Amf/Server/Exception.php';
00650                 throw new Zend_Amf_Server_Exception('Invalid request class');
00651             }
00652         } elseif (!$request instanceof Zend_Amf_Request) {
00653             require_once 'Zend/Amf/Server/Exception.php';
00654             throw new Zend_Amf_Server_Exception('Invalid request object');
00655         }
00656         $this->_request = $request;
00657         return $this;
00658     }
00659 
00665     public function getRequest()
00666     {
00667         if (null === $this->_request) {
00668             require_once 'Zend/Amf/Request/Http.php';
00669             $this->setRequest(new Zend_Amf_Request_Http());
00670         }
00671 
00672         return $this->_request;
00673     }
00674 
00681     public function setResponse($response)
00682     {
00683         if (is_string($response) && class_exists($response)) {
00684             $response = new $response();
00685             if (!$response instanceof Zend_Amf_Response) {
00686                 require_once 'Zend/Amf/Server/Exception.php';
00687                 throw new Zend_Amf_Server_Exception('Invalid response class');
00688             }
00689         } elseif (!$response instanceof Zend_Amf_Response) {
00690             require_once 'Zend/Amf/Server/Exception.php';
00691             throw new Zend_Amf_Server_Exception('Invalid response object');
00692         }
00693         $this->_response = $response;
00694         return $this;
00695     }
00696 
00702     public function getResponse()
00703     {
00704         if (null === ($response = $this->_response)) {
00705             require_once 'Zend/Amf/Response/Http.php';
00706             $this->setResponse(new Zend_Amf_Response_Http());
00707         }
00708         return $this->_response;
00709     }
00710 
00726     public function setClass($class, $namespace = '', $argv = null)
00727     {
00728         if (is_string($class) && !class_exists($class)){
00729             require_once 'Zend/Amf/Server/Exception.php';
00730             throw new Zend_Amf_Server_Exception('Invalid method or class');
00731         } elseif (!is_string($class) && !is_object($class)) {
00732             require_once 'Zend/Amf/Server/Exception.php';
00733             throw new Zend_Amf_Server_Exception('Invalid method or class; must be a classname or object');
00734         }
00735 
00736         $argv = null;
00737         if (2 < func_num_args()) {
00738             $argv = array_slice(func_get_args(), 2);
00739         }
00740 
00741         // Use the class name as the name space by default.
00742 
00743         if ($namespace == '') {
00744             $namespace = is_object($class) ? get_class($class) : $class;
00745         }
00746 
00747         $this->_classAllowed[is_object($class) ? get_class($class) : $class] = true;
00748 
00749         $this->_methods[] = Zend_Server_Reflection::reflectClass($class, $argv, $namespace);
00750         $this->_buildDispatchTable();
00751 
00752         return $this;
00753     }
00754 
00767     public function addFunction($function, $namespace = '')
00768     {
00769         if (!is_string($function) && !is_array($function)) {
00770             require_once 'Zend/Amf/Server/Exception.php';
00771             throw new Zend_Amf_Server_Exception('Unable to attach function');
00772         }
00773 
00774         $argv = null;
00775         if (2 < func_num_args()) {
00776             $argv = array_slice(func_get_args(), 2);
00777         }
00778 
00779         $function = (array) $function;
00780         foreach ($function as $func) {
00781             if (!is_string($func) || !function_exists($func)) {
00782                 require_once 'Zend/Amf/Server/Exception.php';
00783                 throw new Zend_Amf_Server_Exception('Unable to attach function');
00784             }
00785             $this->_methods[] = Zend_Server_Reflection::reflectFunction($func, $argv, $namespace);
00786         }
00787 
00788         $this->_buildDispatchTable();
00789         return $this;
00790     }
00791 
00792 
00799     public function addDirectory($dir)
00800     {
00801         $this->getLoader()->addPrefixPath("", $dir);
00802     }
00803 
00809     public function getDirectory()
00810     {
00811         return $this->getLoader()->getPaths("");
00812     }
00813 
00822     protected function _buildDispatchTable()
00823     {
00824         $table = array();
00825         foreach ($this->_methods as $key => $dispatchable) {
00826             if ($dispatchable instanceof Zend_Server_Reflection_Function_Abstract) {
00827                 $ns   = $dispatchable->getNamespace();
00828                 $name = $dispatchable->getName();
00829                 $name = empty($ns) ? $name : $ns . '.' . $name;
00830 
00831                 if (isset($table[$name])) {
00832                     require_once 'Zend/Amf/Server/Exception.php';
00833                     throw new Zend_Amf_Server_Exception('Duplicate method registered: ' . $name);
00834                 }
00835                 $table[$name] = $dispatchable;
00836                 continue;
00837             }
00838 
00839             if ($dispatchable instanceof Zend_Server_Reflection_Class) {
00840                 foreach ($dispatchable->getMethods() as $method) {
00841                     $ns   = $method->getNamespace();
00842                     $name = $method->getName();
00843                     $name = empty($ns) ? $name : $ns . '.' . $name;
00844 
00845                     if (isset($table[$name])) {
00846                         require_once 'Zend/Amf/Server/Exception.php';
00847                         throw new Zend_Amf_Server_Exception('Duplicate method registered: ' . $name);
00848                     }
00849                     $table[$name] = $method;
00850                     continue;
00851                 }
00852             }
00853         }
00854         $this->_table = $table;
00855     }
00856 
00857 
00858 
00867     public function fault($fault = null, $code = 404)
00868     {
00869     }
00870 
00879     public function getFunctions()
00880     {
00881         return $this->_table;
00882     }
00883 
00892     public function setPersistence($mode)
00893     {
00894     }
00895 
00904     public function loadFunctions($definition)
00905     {
00906     }
00907 
00915     public function setClassMap($asClass, $phpClass)
00916     {
00917         require_once 'Zend/Amf/Parse/TypeLoader.php';
00918         Zend_Amf_Parse_TypeLoader::setMapping($asClass, $phpClass);
00919         return $this;
00920     }
00921 
00929     public function listMethods()
00930     {
00931         return array_keys($this->_table);
00932     }
00933 }
 All Data Structures Namespaces Files Functions Variables Enumerations