PageRenderTime 50ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/src/application/libraries/Zend/Amf/Server.php

https://bitbucket.org/masnug/grc276-blog-laravel
PHP | 964 lines | 526 code | 85 blank | 353 comment | 80 complexity | 68a6f00b2bb64ba4705212982859c9dd MD5 | raw file
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  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.
  14. *
  15. * @category Zend
  16. * @package Zend_Amf
  17. * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
  18. * @license http://framework.zend.com/license/new-bsd New BSD License
  19. * @version $Id: Server.php 24206 2011-07-06 13:52:02Z matthew $
  20. */
  21. /** @see Zend_Server_Interface */
  22. require_once 'Zend/Server/Interface.php';
  23. /** @see Zend_Server_Reflection */
  24. require_once 'Zend/Server/Reflection.php';
  25. /** @see Zend_Amf_Constants */
  26. require_once 'Zend/Amf/Constants.php';
  27. /** @see Zend_Amf_Value_MessageBody */
  28. require_once 'Zend/Amf/Value/MessageBody.php';
  29. /** @see Zend_Amf_Value_MessageHeader */
  30. require_once 'Zend/Amf/Value/MessageHeader.php';
  31. /** @see Zend_Amf_Value_Messaging_CommandMessage */
  32. require_once 'Zend/Amf/Value/Messaging/CommandMessage.php';
  33. /** @see Zend_Loader_PluginLoader */
  34. require_once 'Zend/Loader/PluginLoader.php';
  35. /** @see Zend_Amf_Parse_TypeLoader */
  36. require_once 'Zend/Amf/Parse/TypeLoader.php';
  37. /** @see Zend_Auth */
  38. require_once 'Zend/Auth.php';
  39. /**
  40. * An AMF gateway server implementation to allow the connection of the Adobe Flash Player to
  41. * Zend Framework
  42. *
  43. * @todo Make the reflection methods cache and autoload.
  44. * @package Zend_Amf
  45. * @subpackage Server
  46. * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
  47. * @license http://framework.zend.com/license/new-bsd New BSD License
  48. */
  49. class Zend_Amf_Server implements Zend_Server_Interface
  50. {
  51. /**
  52. * Array of dispatchables
  53. * @var array
  54. */
  55. protected $_methods = array();
  56. /**
  57. * Array of classes that can be called without being explicitly loaded
  58. *
  59. * Keys are class names.
  60. *
  61. * @var array
  62. */
  63. protected $_classAllowed = array();
  64. /**
  65. * Loader for classes in added directories
  66. * @var Zend_Loader_PluginLoader
  67. */
  68. protected $_loader;
  69. /**
  70. * @var bool Production flag; whether or not to return exception messages
  71. */
  72. protected $_production = true;
  73. /**
  74. * Request processed
  75. * @var null|Zend_Amf_Request
  76. */
  77. protected $_request = null;
  78. /**
  79. * Class to use for responses
  80. * @var null|Zend_Amf_Response
  81. */
  82. protected $_response;
  83. /**
  84. * Dispatch table of name => method pairs
  85. * @var array
  86. */
  87. protected $_table = array();
  88. /**
  89. *
  90. * @var bool session flag; whether or not to add a session to each response.
  91. */
  92. protected $_session = false;
  93. /**
  94. * Namespace allows all AMF calls to not clobber other PHP session variables
  95. * @var Zend_Session_NameSpace default session namespace zend_amf
  96. */
  97. protected $_sesionNamespace = 'zend_amf';
  98. /**
  99. * Set the default session.name if php_
  100. * @var string
  101. */
  102. protected $_sessionName = 'PHPSESSID';
  103. /**
  104. * Authentication handler object
  105. *
  106. * @var Zend_Amf_Auth_Abstract
  107. */
  108. protected $_auth;
  109. /**
  110. * ACL handler object
  111. *
  112. * @var Zend_Acl
  113. */
  114. protected $_acl;
  115. /**
  116. * The server constructor
  117. */
  118. public function __construct()
  119. {
  120. Zend_Amf_Parse_TypeLoader::setResourceLoader(new Zend_Loader_PluginLoader(array("Zend_Amf_Parse_Resource" => "Zend/Amf/Parse/Resource")));
  121. }
  122. /**
  123. * Set authentication adapter
  124. *
  125. * If the authentication adapter implements a "getAcl()" method, populate
  126. * the ACL of this instance with it (if none exists already).
  127. *
  128. * @param Zend_Amf_Auth_Abstract $auth
  129. * @return Zend_Amf_Server
  130. */
  131. public function setAuth(Zend_Amf_Auth_Abstract $auth)
  132. {
  133. $this->_auth = $auth;
  134. if ((null === $this->getAcl()) && method_exists($auth, 'getAcl')) {
  135. $this->setAcl($auth->getAcl());
  136. }
  137. return $this;
  138. }
  139. /**
  140. * Get authentication adapter
  141. *
  142. * @return Zend_Amf_Auth_Abstract
  143. */
  144. public function getAuth()
  145. {
  146. return $this->_auth;
  147. }
  148. /**
  149. * Set ACL adapter
  150. *
  151. * @param Zend_Acl $acl
  152. * @return Zend_Amf_Server
  153. */
  154. public function setAcl(Zend_Acl $acl)
  155. {
  156. $this->_acl = $acl;
  157. return $this;
  158. }
  159. /**
  160. * Get ACL adapter
  161. *
  162. * @return Zend_Acl
  163. */
  164. public function getAcl()
  165. {
  166. return $this->_acl;
  167. }
  168. /**
  169. * Set production flag
  170. *
  171. * @param bool $flag
  172. * @return Zend_Amf_Server
  173. */
  174. public function setProduction($flag)
  175. {
  176. $this->_production = (bool) $flag;
  177. return $this;
  178. }
  179. /**
  180. * Whether or not the server is in production
  181. *
  182. * @return bool
  183. */
  184. public function isProduction()
  185. {
  186. return $this->_production;
  187. }
  188. /**
  189. * @param namespace of all incoming sessions defaults to Zend_Amf
  190. * @return Zend_Amf_Server
  191. */
  192. public function setSession($namespace = 'Zend_Amf')
  193. {
  194. require_once 'Zend/Session.php';
  195. $this->_session = true;
  196. $this->_sesionNamespace = new Zend_Session_Namespace($namespace);
  197. return $this;
  198. }
  199. /**
  200. * Whether of not the server is using sessions
  201. * @return bool
  202. */
  203. public function isSession()
  204. {
  205. return $this->_session;
  206. }
  207. /**
  208. * Check if the ACL allows accessing the function or method
  209. *
  210. * @param string|object $object Object or class being accessed
  211. * @param string $function Function or method being accessed
  212. * @return unknown_type
  213. */
  214. protected function _checkAcl($object, $function)
  215. {
  216. if(!$this->_acl) {
  217. return true;
  218. }
  219. if($object) {
  220. $class = is_object($object)?get_class($object):$object;
  221. if(!$this->_acl->has($class)) {
  222. require_once 'Zend/Acl/Resource.php';
  223. $this->_acl->add(new Zend_Acl_Resource($class));
  224. }
  225. $call = array($object, "initAcl");
  226. if(is_callable($call) && !call_user_func($call, $this->_acl)) {
  227. // if initAcl returns false, no ACL check
  228. return true;
  229. }
  230. } else {
  231. $class = null;
  232. }
  233. $auth = Zend_Auth::getInstance();
  234. if($auth->hasIdentity()) {
  235. $role = $auth->getIdentity()->role;
  236. } else {
  237. if($this->_acl->hasRole(Zend_Amf_Constants::GUEST_ROLE)) {
  238. $role = Zend_Amf_Constants::GUEST_ROLE;
  239. } else {
  240. require_once 'Zend/Amf/Server/Exception.php';
  241. throw new Zend_Amf_Server_Exception("Unauthenticated access not allowed");
  242. }
  243. }
  244. if($this->_acl->isAllowed($role, $class, $function)) {
  245. return true;
  246. } else {
  247. require_once 'Zend/Amf/Server/Exception.php';
  248. throw new Zend_Amf_Server_Exception("Access not allowed");
  249. }
  250. }
  251. /**
  252. * Get PluginLoader for the Server
  253. *
  254. * @return Zend_Loader_PluginLoader
  255. */
  256. protected function getLoader()
  257. {
  258. if(empty($this->_loader)) {
  259. require_once 'Zend/Loader/PluginLoader.php';
  260. $this->_loader = new Zend_Loader_PluginLoader();
  261. }
  262. return $this->_loader;
  263. }
  264. /**
  265. * Loads a remote class or method and executes the function and returns
  266. * the result
  267. *
  268. * @param string $method Is the method to execute
  269. * @param mixed $param values for the method
  270. * @return mixed $response the result of executing the method
  271. * @throws Zend_Amf_Server_Exception
  272. */
  273. protected function _dispatch($method, $params = null, $source = null)
  274. {
  275. if($source) {
  276. if(($mapped = Zend_Amf_Parse_TypeLoader::getMappedClassName($source)) !== false) {
  277. $source = $mapped;
  278. }
  279. }
  280. $qualifiedName = empty($source) ? $method : $source . '.' . $method;
  281. if (!isset($this->_table[$qualifiedName])) {
  282. // if source is null a method that was not defined was called.
  283. if ($source) {
  284. $className = str_replace('.', '_', $source);
  285. if(class_exists($className, false) && !isset($this->_classAllowed[$className])) {
  286. require_once 'Zend/Amf/Server/Exception.php';
  287. throw new Zend_Amf_Server_Exception('Can not call "' . $className . '" - use setClass()');
  288. }
  289. try {
  290. $this->getLoader()->load($className);
  291. } catch (Exception $e) {
  292. require_once 'Zend/Amf/Server/Exception.php';
  293. throw new Zend_Amf_Server_Exception('Class "' . $className . '" does not exist: '.$e->getMessage(), 0, $e);
  294. }
  295. // Add the new loaded class to the server.
  296. $this->setClass($className, $source);
  297. }
  298. if (!isset($this->_table[$qualifiedName])) {
  299. // Source is null or doesn't contain specified method
  300. require_once 'Zend/Amf/Server/Exception.php';
  301. throw new Zend_Amf_Server_Exception('Method "' . $method . '" does not exist');
  302. }
  303. }
  304. $info = $this->_table[$qualifiedName];
  305. $argv = $info->getInvokeArguments();
  306. if (0 < count($argv)) {
  307. $params = array_merge($params, $argv);
  308. }
  309. if ($info instanceof Zend_Server_Reflection_Function) {
  310. $func = $info->getName();
  311. $this->_checkAcl(null, $func);
  312. $return = call_user_func_array($func, $params);
  313. } elseif ($info instanceof Zend_Server_Reflection_Method) {
  314. // Get class
  315. $class = $info->getDeclaringClass()->getName();
  316. if ('static' == $info->isStatic()) {
  317. // for some reason, invokeArgs() does not work the same as
  318. // invoke(), and expects the first argument to be an object.
  319. // So, using a callback if the method is static.
  320. $this->_checkAcl($class, $info->getName());
  321. $return = call_user_func_array(array($class, $info->getName()), $params);
  322. } else {
  323. // Object methods
  324. try {
  325. $object = $info->getDeclaringClass()->newInstance();
  326. } catch (Exception $e) {
  327. require_once 'Zend/Amf/Server/Exception.php';
  328. throw new Zend_Amf_Server_Exception('Error instantiating class ' . $class . ' to invoke method ' . $info->getName() . ': '.$e->getMessage(), 621, $e);
  329. }
  330. $this->_checkAcl($object, $info->getName());
  331. $return = $info->invokeArgs($object, $params);
  332. }
  333. } else {
  334. require_once 'Zend/Amf/Server/Exception.php';
  335. throw new Zend_Amf_Server_Exception('Method missing implementation ' . get_class($info));
  336. }
  337. return $return;
  338. }
  339. /**
  340. * Handles each of the 11 different command message types.
  341. *
  342. * A command message is a flex.messaging.messages.CommandMessage
  343. *
  344. * @see Zend_Amf_Value_Messaging_CommandMessage
  345. * @param Zend_Amf_Value_Messaging_CommandMessage $message
  346. * @return Zend_Amf_Value_Messaging_AcknowledgeMessage
  347. */
  348. protected function _loadCommandMessage(Zend_Amf_Value_Messaging_CommandMessage $message)
  349. {
  350. require_once 'Zend/Amf/Value/Messaging/AcknowledgeMessage.php';
  351. switch($message->operation) {
  352. case Zend_Amf_Value_Messaging_CommandMessage::DISCONNECT_OPERATION :
  353. case Zend_Amf_Value_Messaging_CommandMessage::CLIENT_PING_OPERATION :
  354. $return = new Zend_Amf_Value_Messaging_AcknowledgeMessage($message);
  355. break;
  356. case Zend_Amf_Value_Messaging_CommandMessage::LOGIN_OPERATION :
  357. $data = explode(':', base64_decode($message->body));
  358. $userid = $data[0];
  359. $password = isset($data[1])?$data[1]:"";
  360. if(empty($userid)) {
  361. require_once 'Zend/Amf/Server/Exception.php';
  362. throw new Zend_Amf_Server_Exception('Login failed: username not supplied');
  363. }
  364. if(!$this->_handleAuth($userid, $password)) {
  365. require_once 'Zend/Amf/Server/Exception.php';
  366. throw new Zend_Amf_Server_Exception('Authentication failed');
  367. }
  368. $return = new Zend_Amf_Value_Messaging_AcknowledgeMessage($message);
  369. break;
  370. case Zend_Amf_Value_Messaging_CommandMessage::LOGOUT_OPERATION :
  371. if($this->_auth) {
  372. Zend_Auth::getInstance()->clearIdentity();
  373. }
  374. $return = new Zend_Amf_Value_Messaging_AcknowledgeMessage($message);
  375. break;
  376. default :
  377. require_once 'Zend/Amf/Server/Exception.php';
  378. throw new Zend_Amf_Server_Exception('CommandMessage::' . $message->operation . ' not implemented');
  379. break;
  380. }
  381. return $return;
  382. }
  383. /**
  384. * Create appropriate error message
  385. *
  386. * @param int $objectEncoding Current AMF encoding
  387. * @param string $message Message that was being processed when error happened
  388. * @param string $description Error description
  389. * @param mixed $detail Detailed data about the error
  390. * @param int $code Error code
  391. * @param int $line Error line
  392. * @return Zend_Amf_Value_Messaging_ErrorMessage|array
  393. */
  394. protected function _errorMessage($objectEncoding, $message, $description, $detail, $code, $line)
  395. {
  396. $return = null;
  397. switch ($objectEncoding) {
  398. case Zend_Amf_Constants::AMF0_OBJECT_ENCODING :
  399. return array (
  400. 'description' => ($this->isProduction ()) ? '' : $description,
  401. 'detail' => ($this->isProduction ()) ? '' : $detail,
  402. 'line' => ($this->isProduction ()) ? 0 : $line,
  403. 'code' => $code
  404. );
  405. case Zend_Amf_Constants::AMF3_OBJECT_ENCODING :
  406. require_once 'Zend/Amf/Value/Messaging/ErrorMessage.php';
  407. $return = new Zend_Amf_Value_Messaging_ErrorMessage ( $message );
  408. $return->faultString = $this->isProduction () ? '' : $description;
  409. $return->faultCode = $code;
  410. $return->faultDetail = $this->isProduction () ? '' : $detail;
  411. break;
  412. }
  413. return $return;
  414. }
  415. /**
  416. * Handle AMF authentication
  417. *
  418. * @param string $userid
  419. * @param string $password
  420. * @return boolean
  421. */
  422. protected function _handleAuth( $userid, $password)
  423. {
  424. if (!$this->_auth) {
  425. return true;
  426. }
  427. $this->_auth->setCredentials($userid, $password);
  428. $auth = Zend_Auth::getInstance();
  429. $result = $auth->authenticate($this->_auth);
  430. if ($result->isValid()) {
  431. if (!$this->isSession()) {
  432. $this->setSession();
  433. }
  434. return true;
  435. } else {
  436. // authentication failed, good bye
  437. require_once 'Zend/Amf/Server/Exception.php';
  438. throw new Zend_Amf_Server_Exception(
  439. "Authentication failed: " . join("\n",
  440. $result->getMessages()), $result->getCode());
  441. }
  442. }
  443. /**
  444. * Takes the deserialized AMF request and performs any operations.
  445. *
  446. * @todo should implement and SPL observer pattern for custom AMF headers
  447. * @todo DescribeService support
  448. * @param Zend_Amf_Request $request
  449. * @return Zend_Amf_Response
  450. * @throws Zend_Amf_server_Exception|Exception
  451. */
  452. protected function _handle(Zend_Amf_Request $request)
  453. {
  454. // Get the object encoding of the request.
  455. $objectEncoding = $request->getObjectEncoding();
  456. // create a response object to place the output from the services.
  457. $response = $this->getResponse();
  458. // set response encoding
  459. $response->setObjectEncoding($objectEncoding);
  460. // Authenticate, if we have credential headers
  461. $error = false;
  462. $headers = $request->getAmfHeaders();
  463. if (isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER])
  464. && isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->userid)
  465. && isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->password)
  466. ) {
  467. try {
  468. if ($this->_handleAuth(
  469. $headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->userid,
  470. $headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->password
  471. )) {
  472. // use RequestPersistentHeader to clear credentials
  473. $response->addAmfHeader(
  474. new Zend_Amf_Value_MessageHeader(
  475. Zend_Amf_Constants::PERSISTENT_HEADER,
  476. false,
  477. new Zend_Amf_Value_MessageHeader(
  478. Zend_Amf_Constants::CREDENTIALS_HEADER,
  479. false, null
  480. )
  481. )
  482. );
  483. }
  484. } catch (Exception $e) {
  485. // Error during authentication; report it
  486. $error = $this->_errorMessage(
  487. $objectEncoding,
  488. '',
  489. $e->getMessage(),
  490. $e->getTraceAsString(),
  491. $e->getCode(),
  492. $e->getLine()
  493. );
  494. $responseType = Zend_AMF_Constants::STATUS_METHOD;
  495. }
  496. }
  497. // Iterate through each of the service calls in the AMF request
  498. foreach($request->getAmfBodies() as $body)
  499. {
  500. if ($error) {
  501. // Error during authentication; just report it and be done
  502. $responseURI = $body->getResponseURI() . $responseType;
  503. $newBody = new Zend_Amf_Value_MessageBody($responseURI, null, $error);
  504. $response->addAmfBody($newBody);
  505. continue;
  506. }
  507. try {
  508. switch ($objectEncoding) {
  509. case Zend_Amf_Constants::AMF0_OBJECT_ENCODING:
  510. // AMF0 Object Encoding
  511. $targetURI = $body->getTargetURI();
  512. $message = '';
  513. // Split the target string into its values.
  514. $source = substr($targetURI, 0, strrpos($targetURI, '.'));
  515. if ($source) {
  516. // Break off method name from namespace into source
  517. $method = substr(strrchr($targetURI, '.'), 1);
  518. $return = $this->_dispatch($method, $body->getData(), $source);
  519. } else {
  520. // Just have a method name.
  521. $return = $this->_dispatch($targetURI, $body->getData());
  522. }
  523. break;
  524. case Zend_Amf_Constants::AMF3_OBJECT_ENCODING:
  525. default:
  526. // AMF3 read message type
  527. $message = $body->getData();
  528. if ($message instanceof Zend_Amf_Value_Messaging_CommandMessage) {
  529. // async call with command message
  530. $return = $this->_loadCommandMessage($message);
  531. } elseif ($message instanceof Zend_Amf_Value_Messaging_RemotingMessage) {
  532. require_once 'Zend/Amf/Value/Messaging/AcknowledgeMessage.php';
  533. $return = new Zend_Amf_Value_Messaging_AcknowledgeMessage($message);
  534. $return->body = $this->_dispatch($message->operation, $message->body, $message->source);
  535. } else {
  536. // Amf3 message sent with netConnection
  537. $targetURI = $body->getTargetURI();
  538. // Split the target string into its values.
  539. $source = substr($targetURI, 0, strrpos($targetURI, '.'));
  540. if ($source) {
  541. // Break off method name from namespace into source
  542. $method = substr(strrchr($targetURI, '.'), 1);
  543. $return = $this->_dispatch($method, $body->getData(), $source);
  544. } else {
  545. // Just have a method name.
  546. $return = $this->_dispatch($targetURI, $body->getData());
  547. }
  548. }
  549. break;
  550. }
  551. $responseType = Zend_AMF_Constants::RESULT_METHOD;
  552. } catch (Exception $e) {
  553. $return = $this->_errorMessage($objectEncoding, $message,
  554. $e->getMessage(), $e->getTraceAsString(),$e->getCode(), $e->getLine());
  555. $responseType = Zend_AMF_Constants::STATUS_METHOD;
  556. }
  557. $responseURI = $body->getResponseURI() . $responseType;
  558. $newBody = new Zend_Amf_Value_MessageBody($responseURI, null, $return);
  559. $response->addAmfBody($newBody);
  560. }
  561. // Add a session header to the body if session is requested.
  562. if($this->isSession()) {
  563. $currentID = session_id();
  564. $joint = "?";
  565. if(isset($_SERVER['QUERY_STRING'])) {
  566. if(!strpos($_SERVER['QUERY_STRING'], $currentID) !== FALSE) {
  567. if(strrpos($_SERVER['QUERY_STRING'], "?") !== FALSE) {
  568. $joint = "&";
  569. }
  570. }
  571. }
  572. // create a new AMF message header with the session id as a variable.
  573. $sessionValue = $joint . $this->_sessionName . "=" . $currentID;
  574. $sessionHeader = new Zend_Amf_Value_MessageHeader(Zend_Amf_Constants::URL_APPEND_HEADER, false, $sessionValue);
  575. $response->addAmfHeader($sessionHeader);
  576. }
  577. // serialize the response and return serialized body.
  578. $response->finalize();
  579. }
  580. /**
  581. * Handle an AMF call from the gateway.
  582. *
  583. * @param null|Zend_Amf_Request $request Optional
  584. * @return Zend_Amf_Response
  585. */
  586. public function handle($request = null)
  587. {
  588. // Check if request was passed otherwise get it from the server
  589. if ($request === null || !$request instanceof Zend_Amf_Request) {
  590. $request = $this->getRequest();
  591. } else {
  592. $this->setRequest($request);
  593. }
  594. if ($this->isSession()) {
  595. // Check if a session is being sent from the amf call
  596. if (isset($_COOKIE[$this->_sessionName])) {
  597. session_id($_COOKIE[$this->_sessionName]);
  598. }
  599. }
  600. // Check for errors that may have happend in deserialization of Request.
  601. try {
  602. // Take converted PHP objects and handle service call.
  603. // Serialize to Zend_Amf_response for output stream
  604. $this->_handle($request);
  605. $response = $this->getResponse();
  606. } catch (Exception $e) {
  607. // Handle any errors in the serialization and service calls.
  608. require_once 'Zend/Amf/Server/Exception.php';
  609. throw new Zend_Amf_Server_Exception('Handle error: ' . $e->getMessage() . ' ' . $e->getLine(), 0, $e);
  610. }
  611. // Return the Amf serialized output string
  612. return $response;
  613. }
  614. /**
  615. * Set request object
  616. *
  617. * @param string|Zend_Amf_Request $request
  618. * @return Zend_Amf_Server
  619. */
  620. public function setRequest($request)
  621. {
  622. if (is_string($request) && class_exists($request)) {
  623. $request = new $request();
  624. if (!$request instanceof Zend_Amf_Request) {
  625. require_once 'Zend/Amf/Server/Exception.php';
  626. throw new Zend_Amf_Server_Exception('Invalid request class');
  627. }
  628. } elseif (!$request instanceof Zend_Amf_Request) {
  629. require_once 'Zend/Amf/Server/Exception.php';
  630. throw new Zend_Amf_Server_Exception('Invalid request object');
  631. }
  632. $this->_request = $request;
  633. return $this;
  634. }
  635. /**
  636. * Return currently registered request object
  637. *
  638. * @return null|Zend_Amf_Request
  639. */
  640. public function getRequest()
  641. {
  642. if (null === $this->_request) {
  643. require_once 'Zend/Amf/Request/Http.php';
  644. $this->setRequest(new Zend_Amf_Request_Http());
  645. }
  646. return $this->_request;
  647. }
  648. /**
  649. * Public access method to private Zend_Amf_Server_Response reference
  650. *
  651. * @param string|Zend_Amf_Server_Response $response
  652. * @return Zend_Amf_Server
  653. */
  654. public function setResponse($response)
  655. {
  656. if (is_string($response) && class_exists($response)) {
  657. $response = new $response();
  658. if (!$response instanceof Zend_Amf_Response) {
  659. require_once 'Zend/Amf/Server/Exception.php';
  660. throw new Zend_Amf_Server_Exception('Invalid response class');
  661. }
  662. } elseif (!$response instanceof Zend_Amf_Response) {
  663. require_once 'Zend/Amf/Server/Exception.php';
  664. throw new Zend_Amf_Server_Exception('Invalid response object');
  665. }
  666. $this->_response = $response;
  667. return $this;
  668. }
  669. /**
  670. * get a reference to the Zend_Amf_response instance
  671. *
  672. * @return Zend_Amf_Server_Response
  673. */
  674. public function getResponse()
  675. {
  676. if (null === ($response = $this->_response)) {
  677. require_once 'Zend/Amf/Response/Http.php';
  678. $this->setResponse(new Zend_Amf_Response_Http());
  679. }
  680. return $this->_response;
  681. }
  682. /**
  683. * Attach a class or object to the server
  684. *
  685. * Class may be either a class name or an instantiated object. Reflection
  686. * is done on the class or object to determine the available public
  687. * methods, and each is attached to the server as and available method. If
  688. * a $namespace has been provided, that namespace is used to prefix
  689. * AMF service call.
  690. *
  691. * @param string|object $class
  692. * @param string $namespace Optional
  693. * @param mixed $arg Optional arguments to pass to a method
  694. * @return Zend_Amf_Server
  695. * @throws Zend_Amf_Server_Exception on invalid input
  696. */
  697. public function setClass($class, $namespace = '', $argv = null)
  698. {
  699. if (is_string($class) && !class_exists($class)){
  700. require_once 'Zend/Amf/Server/Exception.php';
  701. throw new Zend_Amf_Server_Exception('Invalid method or class');
  702. } elseif (!is_string($class) && !is_object($class)) {
  703. require_once 'Zend/Amf/Server/Exception.php';
  704. throw new Zend_Amf_Server_Exception('Invalid method or class; must be a classname or object');
  705. }
  706. $argv = null;
  707. if (2 < func_num_args()) {
  708. $argv = array_slice(func_get_args(), 2);
  709. }
  710. // Use the class name as the name space by default.
  711. if ($namespace == '') {
  712. $namespace = is_object($class) ? get_class($class) : $class;
  713. }
  714. $this->_classAllowed[is_object($class) ? get_class($class) : $class] = true;
  715. $this->_methods[] = Zend_Server_Reflection::reflectClass($class, $argv, $namespace);
  716. $this->_buildDispatchTable();
  717. return $this;
  718. }
  719. /**
  720. * Attach a function to the server
  721. *
  722. * Additional arguments to pass to the function at dispatch may be passed;
  723. * any arguments following the namespace will be aggregated and passed at
  724. * dispatch time.
  725. *
  726. * @param string|array $function Valid callback
  727. * @param string $namespace Optional namespace prefix
  728. * @return Zend_Amf_Server
  729. * @throws Zend_Amf_Server_Exception
  730. */
  731. public function addFunction($function, $namespace = '')
  732. {
  733. if (!is_string($function) && !is_array($function)) {
  734. require_once 'Zend/Amf/Server/Exception.php';
  735. throw new Zend_Amf_Server_Exception('Unable to attach function');
  736. }
  737. $argv = null;
  738. if (2 < func_num_args()) {
  739. $argv = array_slice(func_get_args(), 2);
  740. }
  741. $function = (array) $function;
  742. foreach ($function as $func) {
  743. if (!is_string($func) || !function_exists($func)) {
  744. require_once 'Zend/Amf/Server/Exception.php';
  745. throw new Zend_Amf_Server_Exception('Unable to attach function');
  746. }
  747. $this->_methods[] = Zend_Server_Reflection::reflectFunction($func, $argv, $namespace);
  748. }
  749. $this->_buildDispatchTable();
  750. return $this;
  751. }
  752. /**
  753. * Creates an array of directories in which services can reside.
  754. * TODO: add support for prefixes?
  755. *
  756. * @param string $dir
  757. */
  758. public function addDirectory($dir)
  759. {
  760. $this->getLoader()->addPrefixPath("", $dir);
  761. }
  762. /**
  763. * Returns an array of directories that can hold services.
  764. *
  765. * @return array
  766. */
  767. public function getDirectory()
  768. {
  769. return $this->getLoader()->getPaths("");
  770. }
  771. /**
  772. * (Re)Build the dispatch table
  773. *
  774. * The dispatch table consists of a an array of method name =>
  775. * Zend_Server_Reflection_Function_Abstract pairs
  776. *
  777. * @return void
  778. */
  779. protected function _buildDispatchTable()
  780. {
  781. $table = array();
  782. foreach ($this->_methods as $key => $dispatchable) {
  783. if ($dispatchable instanceof Zend_Server_Reflection_Function_Abstract) {
  784. $ns = $dispatchable->getNamespace();
  785. $name = $dispatchable->getName();
  786. $name = empty($ns) ? $name : $ns . '.' . $name;
  787. if (isset($table[$name])) {
  788. require_once 'Zend/Amf/Server/Exception.php';
  789. throw new Zend_Amf_Server_Exception('Duplicate method registered: ' . $name);
  790. }
  791. $table[$name] = $dispatchable;
  792. continue;
  793. }
  794. if ($dispatchable instanceof Zend_Server_Reflection_Class) {
  795. foreach ($dispatchable->getMethods() as $method) {
  796. $ns = $method->getNamespace();
  797. $name = $method->getName();
  798. $name = empty($ns) ? $name : $ns . '.' . $name;
  799. if (isset($table[$name])) {
  800. require_once 'Zend/Amf/Server/Exception.php';
  801. throw new Zend_Amf_Server_Exception('Duplicate method registered: ' . $name);
  802. }
  803. $table[$name] = $method;
  804. continue;
  805. }
  806. }
  807. }
  808. $this->_table = $table;
  809. }
  810. /**
  811. * Raise a server fault
  812. *
  813. * Unimplemented
  814. *
  815. * @param string|Exception $fault
  816. * @return void
  817. */
  818. public function fault($fault = null, $code = 404)
  819. {
  820. }
  821. /**
  822. * Returns a list of registered methods
  823. *
  824. * Returns an array of dispatchables (Zend_Server_Reflection_Function,
  825. * _Method, and _Class items).
  826. *
  827. * @return array
  828. */
  829. public function getFunctions()
  830. {
  831. return $this->_table;
  832. }
  833. /**
  834. * Set server persistence
  835. *
  836. * Unimplemented
  837. *
  838. * @param mixed $mode
  839. * @return void
  840. */
  841. public function setPersistence($mode)
  842. {
  843. }
  844. /**
  845. * Load server definition
  846. *
  847. * Unimplemented
  848. *
  849. * @param array $definition
  850. * @return void
  851. */
  852. public function loadFunctions($definition)
  853. {
  854. }
  855. /**
  856. * Map ActionScript classes to PHP classes
  857. *
  858. * @param string $asClass
  859. * @param string $phpClass
  860. * @return Zend_Amf_Server
  861. */
  862. public function setClassMap($asClass, $phpClass)
  863. {
  864. require_once 'Zend/Amf/Parse/TypeLoader.php';
  865. Zend_Amf_Parse_TypeLoader::setMapping($asClass, $phpClass);
  866. return $this;
  867. }
  868. /**
  869. * List all available methods
  870. *
  871. * Returns an array of method names.
  872. *
  873. * @return array
  874. */
  875. public function listMethods()
  876. {
  877. return array_keys($this->_table);
  878. }
  879. }