Source for file Server.class.php

Documentation is available at Server.class.php

  1. <?php
  2. /**
  3. * XOAD Server file.
  4. *
  5. * <p>This file defines the {@link XOAD_Server} Class.</p>
  6. * <p>Example:</p>
  7. * <code>
  8. * <?php
  9. *
  10. * require_once('xoad.php');
  11. *
  12. * class Calculator
  13. * {
  14. * var $result;
  15. *
  16. * function Calculator()
  17. * {
  18. * $this->result = 0;
  19. * }
  20. *
  21. * function Add($arg)
  22. * {
  23. * $this->result += $arg;
  24. * }
  25. * }
  26. *
  27. * XOAD_Server::runServer();
  28. *
  29. * ?>
  30. * </code>
  31. *
  32. * @author Stanimir Angeloff
  33. *
  34. * @package XOAD
  35. *
  36. * @version 0.6.0.0
  37. *
  38. */
  39.  
  40. /**
  41. * XOAD Server Class.
  42. *
  43. * <p>This class is used to handle client callbacks.</p>
  44. * <p>Example:</p>
  45. * <code>
  46. * <?php
  47. *
  48. * require_once('xoad.php');
  49. *
  50. * class Calculator
  51. * {
  52. * var $result;
  53. *
  54. * function Calculator()
  55. * {
  56. * $this->result = 0;
  57. * }
  58. *
  59. * function Add($arg)
  60. * {
  61. * $this->result += $arg;
  62. * }
  63. * }
  64. *
  65. * XOAD_Server::runServer();
  66. *
  67. * ?>
  68. * </code>
  69. *
  70. * @author Stanimir Angeloff
  71. *
  72. * @package XOAD
  73. *
  74. * @version 0.6.0.0
  75. *
  76. */
  77. class XOAD_Server extends XOAD_Observable
  78. {
  79. /**
  80. * Checks if the request is a client callback
  81. * to the server and handles it.
  82. *
  83. * @access public
  84. *
  85. * @return bool true if the request is a valid client callback,
  86. * false otherwise.
  87. *
  88. * @static
  89. *
  90. */
  91. function runServer()
  92. {
  93. if ( ! XOAD_Server::notifyObservers('runServerEnter')) {
  94.  
  95. return false;
  96. }
  97.  
  98. if (XOAD_Server::initializeCallback()) {
  99.  
  100. XOAD_Server::dispatch();
  101.  
  102. /**
  103. * Defines whether the request is a client callback.
  104. */
  105. define('XOAD_CALLBACK', true);
  106. }
  107.  
  108. if ( ! defined('XOAD_CALLBACK')) {
  109.  
  110. /**
  111. * Defines whether the request is a client callback.
  112. */
  113. define('XOAD_CALLBACK', false);
  114. }
  115.  
  116. if (XOAD_Server::notifyObservers('runServerLeave', array('isCallback' => XOAD_CALLBACK))) {
  117.  
  118. return XOAD_CALLBACK;
  119.  
  120. } else {
  121.  
  122. return false;
  123. }
  124. }
  125.  
  126. /**
  127. * Checks if the request is a client callback to the
  128. * server and initializes callback parameters.
  129. *
  130. * @access public
  131. *
  132. * @return bool true if the request is a valid client callback,
  133. * false otherwise.
  134. *
  135. * @static
  136. *
  137. */
  138. function initializeCallback()
  139. {
  140. if ( ! XOAD_Server::notifyObservers('initializeCallbackEnter')) {
  141.  
  142. return false;
  143. }
  144.  
  145. if (isset($_GET['xoadCall'])) {
  146.  
  147. if (strcasecmp($_GET['xoadCall'], 'true') == 0) {
  148.  
  149. if ( ! isset($GLOBALS['HTTP_RAW_POST_DATA'])) {
  150.  
  151. return false;
  152. }
  153.  
  154. $requestBody = @unserialize($GLOBALS['HTTP_RAW_POST_DATA']);
  155.  
  156. if ($requestBody == null) {
  157.  
  158. return false;
  159. }
  160.  
  161. if (
  162. isset($requestBody['eventPost']) &&
  163. isset($requestBody['className']) &&
  164. isset($requestBody['sender']) &&
  165. isset($requestBody['event']) &&
  166. array_key_exists('data', $requestBody) &&
  167. array_key_exists('filter', $requestBody)) {
  168.  
  169. if (
  170. (XOAD_Utilities::getType($requestBody['eventPost']) != 'bool') ||
  171. (XOAD_Utilities::getType($requestBody['className']) != 'string') ||
  172. (XOAD_Utilities::getType($requestBody['sender']) != 'string') ||
  173. (XOAD_Utilities::getType($requestBody['event']) != 'string')) {
  174.  
  175. return false;
  176. }
  177.  
  178. if ( ! empty($requestBody['className'])) {
  179.  
  180. XOAD_Server::loadClass($requestBody['className']);
  181.  
  182. } else {
  183.  
  184. return false;
  185. }
  186.  
  187. if ( ! XOAD_Server::isClassAllowed($requestBody['className'])) {
  188.  
  189. return false;
  190. }
  191.  
  192. $requestBody['sender'] = @unserialize($requestBody['sender']);
  193.  
  194. if ($requestBody['sender'] === null) {
  195.  
  196. return false;
  197. }
  198.  
  199. if (strcasecmp(get_class($requestBody['sender']), $requestBody['className']) != 0) {
  200.  
  201. return false;
  202. }
  203.  
  204. if ( ! XOAD_Server::notifyObservers('initializeCallbackSuccess', array('request' => &$requestBody))) {
  205.  
  206. return false;
  207. }
  208.  
  209. $GLOBALS['_XOAD_SERVER_REQUEST_BODY'] =& $requestBody;
  210.  
  211. if (XOAD_Server::notifyObservers('initializeCallbackLeave', array('request' => &$requestBody))) {
  212.  
  213. return true;
  214. }
  215.  
  216. } else if (
  217. isset($requestBody['eventsCallback']) &&
  218. isset($requestBody['time']) &&
  219. isset($requestBody['data'])) {
  220.  
  221. if (
  222. (XOAD_Utilities::getType($requestBody['eventsCallback']) != 'bool') ||
  223. (XOAD_Utilities::getType($requestBody['time']) != 'float') ||
  224. (XOAD_Utilities::getType($requestBody['data']) != 's_array')) {
  225.  
  226. return false;
  227. }
  228.  
  229. foreach ($requestBody['data'] as $eventData) {
  230.  
  231. if ( ! empty($eventData['className'])) {
  232.  
  233. XOAD_Server::loadClass($eventData['className']);
  234.  
  235. } else {
  236.  
  237. return false;
  238. }
  239.  
  240. if ( ! XOAD_Server::isClassAllowed($eventData['className'])) {
  241.  
  242. return false;
  243. }
  244. }
  245.  
  246. if ( ! XOAD_Server::notifyObservers('initializeCallbackSuccess', array('request' => &$requestBody))) {
  247.  
  248. return false;
  249. }
  250.  
  251. $GLOBALS['_XOAD_SERVER_REQUEST_BODY'] =& $requestBody;
  252.  
  253. if (XOAD_Server::notifyObservers('initializeCallbackLeave', array('request' => &$requestBody))) {
  254.  
  255. return true;
  256. }
  257.  
  258. } else {
  259.  
  260. if (
  261. ( ! isset($requestBody['source'])) ||
  262. ( ! isset($requestBody['className'])) ||
  263. ( ! isset($requestBody['method'])) ||
  264. ( ! isset($requestBody['arguments']))) {
  265.  
  266. return false;
  267. }
  268.  
  269. if ( ! empty($requestBody['className'])) {
  270.  
  271. XOAD_Server::loadClass($requestBody['className']);
  272. }
  273.  
  274. $requestBody['source'] = @unserialize($requestBody['source']);
  275.  
  276. $requestBody['arguments'] = @unserialize($requestBody['arguments']);
  277.  
  278. if (
  279. ($requestBody['source'] === null) ||
  280. ($requestBody['className'] === null) ||
  281. ($requestBody['arguments'] === null)) {
  282.  
  283. return false;
  284. }
  285.  
  286. if (
  287. (XOAD_Utilities::getType($requestBody['source']) != 'object') ||
  288. (XOAD_Utilities::getType($requestBody['className']) != 'string') ||
  289. (XOAD_Utilities::getType($requestBody['method']) != 'string') ||
  290. (XOAD_Utilities::getType($requestBody['arguments']) != 's_array')) {
  291.  
  292. return false;
  293. }
  294.  
  295. if (strcasecmp($requestBody['className'], get_class($requestBody['source'])) != 0) {
  296.  
  297. return false;
  298. }
  299.  
  300. if ( ! XOAD_Server::isClassAllowed($requestBody['className'])) {
  301.  
  302. return false;
  303. }
  304.  
  305. if (method_exists($requestBody['source'], XOAD_CLIENT_METADATA_METHOD_NAME)) {
  306.  
  307. call_user_func_array(array(&$requestBody['source'], XOAD_CLIENT_METADATA_METHOD_NAME), null);
  308.  
  309. if (isset($requestBody['source']->xoadMeta)) {
  310.  
  311. if (XOAD_Utilities::getType($requestBody['source']->xoadMeta) == 'object') {
  312.  
  313. if (strcasecmp(get_class($requestBody['source']->xoadMeta), 'XOAD_Meta') == 0) {
  314.  
  315. if ( ! $requestBody['source']->xoadMeta->isPublicMethod($requestBody['method'])) {
  316.  
  317. return false;
  318. }
  319. }
  320. }
  321. }
  322. }
  323.  
  324. if ( ! XOAD_Server::notifyObservers('initializeCallbackSuccess', array('request' => &$requestBody))) {
  325.  
  326. return false;
  327. }
  328.  
  329. $GLOBALS['_XOAD_SERVER_REQUEST_BODY'] =& $requestBody;
  330.  
  331. if (XOAD_Server::notifyObservers('initializeCallbackLeave', array('request' => &$requestBody))) {
  332.  
  333. return true;
  334. }
  335. }
  336. }
  337. }
  338.  
  339. XOAD_Server::notifyObservers('initializeCallbackLeave');
  340.  
  341. return false;
  342. }
  343.  
  344. /**
  345. * Dispatches a client callback to the server.
  346. *
  347. * @access public
  348. *
  349. * @return string Outputs JavaString code that contains the result
  350. * and the output of the callback.
  351. *
  352. * @static
  353. *
  354. */
  355. function dispatch()
  356. {
  357. if (empty($GLOBALS['_XOAD_SERVER_REQUEST_BODY'])) {
  358.  
  359. return false;
  360. }
  361.  
  362. $requestBody =& $GLOBALS['_XOAD_SERVER_REQUEST_BODY'];
  363.  
  364. if ( ! XOAD_Server::notifyObservers('dispatchEnter', array('request' => &$requestBody))) {
  365.  
  366. return false;
  367. }
  368.  
  369. if (isset($requestBody['eventPost'])) {
  370.  
  371. $callbackResponse = array();
  372.  
  373. $storage =& XOAD_Events_Storage::getStorage();
  374.  
  375. $callbackResponse['status'] = $storage->postEvent($requestBody['event'], $requestBody['className'], $requestBody['sender'], $requestBody['data'], $requestBody['filter']);
  376.  
  377. if (XOAD_Server::notifyObservers('dispatchLeave', array('request' => &$requestBody, 'response' => &$callbackResponse))) {
  378.  
  379. if ( ! empty($callbackResponse['status'])) {
  380.  
  381. print XOAD_Client::register($callbackResponse);
  382. }
  383. }
  384.  
  385. } else if (isset($requestBody['eventsCallback'])) {
  386.  
  387. $eventsQuery = array();
  388.  
  389. foreach ($requestBody['data'] as $event) {
  390.  
  391. $eventsQuery[] = array(
  392. 'event' => $event['event'],
  393. 'className' => $event['className'],
  394. 'filter' => $event['filter'],
  395. 'time' => $requestBody['time']
  396. );
  397. }
  398.  
  399. $callbackResponse = array();
  400.  
  401. $storage =& XOAD_Events_Storage::getStorage();
  402.  
  403. $storage->cleanEvents();
  404.  
  405. $callbackResponse['result'] = $storage->filterMultipleEvents($eventsQuery);
  406.  
  407. if (XOAD_Server::notifyObservers('dispatchLeave', array('request' => &$requestBody, 'response' => &$callbackResponse))) {
  408.  
  409. if ( ! empty($callbackResponse['result'])) {
  410.  
  411. print XOAD_Client::register($callbackResponse);
  412. }
  413. }
  414.  
  415. } else {
  416.  
  417. $callbackResponse = array();
  418.  
  419. $outputBuffering = @ob_start();
  420.  
  421. set_error_handler(array('XOAD_Server', 'handleError'));
  422.  
  423. $callbackResponse['returnValue'] = call_user_func_array(array(&$requestBody['source'], $requestBody['method']), $requestBody['arguments']);
  424.  
  425. if (defined('XOAD_SERVER_EXCEPTION')) {
  426.  
  427. if (XOAD_Server::notifyObservers('dispatchFailed', array('request' => &$requestBody, 'message' => XOAD_SERVER_EXCEPTION))) {
  428.  
  429. XOAD_Server::throwException(XOAD_SERVER_EXCEPTION);
  430.  
  431. return false;
  432. }
  433. }
  434.  
  435. $callbackResponse['returnObject'] =& $requestBody['source'];
  436.  
  437. if ($outputBuffering) {
  438.  
  439. $output = @ob_get_contents();
  440.  
  441. if ( ! empty($output)) {
  442.  
  443. $callbackResponse['output'] = $output;
  444. }
  445.  
  446. @ob_end_clean();
  447. }
  448.  
  449. restore_error_handler();
  450.  
  451. if (XOAD_Server::notifyObservers('dispatchLeave', array('request' => &$requestBody, 'response' => &$callbackResponse))) {
  452.  
  453. print XOAD_Client::register($callbackResponse);
  454. }
  455. }
  456. }
  457.  
  458. /**
  459. * Handles all errors that occur during the callback.
  460. *
  461. * <p>Only E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR and E_USER_ERROR
  462. * will halt the callback and throw an exception.</p>
  463. *
  464. * @access protected
  465. *
  466. * @param int $type Error type (compile, core, user...).
  467. *
  468. * @param string $message Error message.
  469. *
  470. * @return void
  471. *
  472. * @static
  473. *
  474. */
  475. function handleError($type, $message)
  476. {
  477. if (error_reporting()) {
  478.  
  479. if ( ! XOAD_Server::notifyObservers('handleErrorEnter', array('type' => &$type, 'message' => &$message))) {
  480.  
  481. return false;
  482. }
  483.  
  484. $breakLevel = E_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR;
  485.  
  486. if (($type & $breakLevel) > 0) {
  487.  
  488. if ( ! defined('XOAD_SERVER_EXCEPTION')) {
  489.  
  490. /**
  491. * Defines the error message that caused the callback to halt.
  492. */
  493. define('XOAD_SERVER_EXCEPTION', $message);
  494. }
  495. }
  496. }
  497.  
  498. XOAD_Server::notifyObservers('handleErrorLeave', array('type' => &$type, 'message' => &$message));
  499. }
  500.  
  501. /**
  502. * Throws a XOAD callback exception.
  503. *
  504. * @access protected
  505. *
  506. * @param string $message Exception message.
  507. *
  508. * @return string Outputs JavaString code that contains the
  509. * exception message.
  510. *
  511. * @static
  512. *
  513. */
  514. function throwException($message)
  515. {
  516. if ( ! XOAD_Server::notifyObservers('throwExceptionEnter', array('message' => &$message))) {
  517.  
  518. return false;
  519. }
  520.  
  521. restore_error_handler();
  522.  
  523. $callbackException = array();
  524.  
  525. $callbackException['exception'] = $message;
  526.  
  527. if (XOAD_Server::notifyObservers('throwExceptionLeave', array('message' => &$message))) {
  528.  
  529. print XOAD_Client::register($callbackException);
  530. }
  531. }
  532.  
  533. /**
  534. * Adds a specified class to the classes map.
  535. *
  536. * <p>Example:</p>
  537. * <code>
  538. * <?php
  539. *
  540. * require_once('xoad.php');
  541. *
  542. * XOAD_Server::mapClass('Calculator', 'Calculator.class.php');
  543. *
  544. * XOAD_Server::mapClass('EnglishDictionary', array('BaseDictionary.class.php', 'EnglishDictionary.class.php'));
  545. *
  546. * XOAD_Server::runServer();
  547. *
  548. * ?>
  549. * </code>
  550. *
  551. * @access public
  552. *
  553. * @param string $className The class name to add.
  554. *
  555. * @param mixed $files The files that are required
  556. * to load the class.
  557. *
  558. * @return void
  559. *
  560. * @static
  561. *
  562. */
  563. function mapClass($className, $files)
  564. {
  565. if ( ! isset($GLOBALS['_XOAD_SERVER_CLASSES_MAP'])) {
  566.  
  567. $GLOBALS['_XOAD_SERVER_CLASSES_MAP'] = array();
  568. }
  569.  
  570. $GLOBALS['_XOAD_SERVER_CLASSES_MAP'][strtolower($className)] = $files;
  571. }
  572.  
  573. /**
  574. * Loads a specified class from the classes map.
  575. *
  576. * @access public
  577. *
  578. * @param string $className The class name to load. Note that all files
  579. * that are included in the class map will be
  580. * loaded.
  581. *
  582. * @return void
  583. *
  584. * @static
  585. *
  586. */
  587. function loadClass($className)
  588. {
  589. $className = strtolower($className);
  590.  
  591. if ( ! empty($GLOBALS['_XOAD_SERVER_CLASSES_MAP'])) {
  592.  
  593. if (isset($GLOBALS['_XOAD_SERVER_CLASSES_MAP'][$className])) {
  594.  
  595. $files = $GLOBALS['_XOAD_SERVER_CLASSES_MAP'][$className];
  596.  
  597. $filesType = XOAD_Utilities::getType($files);
  598.  
  599. if ($filesType == 'string') {
  600.  
  601. require_once($files);
  602.  
  603. } else if (
  604. ($filesType == 's_array') ||
  605. ($filesType == 'a_array')) {
  606.  
  607. foreach ($files as $fileName) {
  608.  
  609. require_once($fileName);
  610. }
  611. }
  612. }
  613. }
  614. }
  615.  
  616. /**
  617. * Adds specified classes to the allowed classes map.
  618. *
  619. * <p>Example:</p>
  620. * <code>
  621. * <?php
  622. *
  623. * class AllowedClass
  624. * {
  625. * function call() { return 'AllowedClass->call()'; }
  626. * }
  627. *
  628. * class DeniedClass
  629. * {
  630. * function call() { return 'DeniedClass->call()'; }
  631. * }
  632. *
  633. * require_once('xoad.php');
  634. *
  635. * XOAD_Server::allowClasses('AllowedClass');
  636. *
  637. * if (XOAD_Server::runServer()) {
  638. *
  639. * exit;
  640. * }
  641. *
  642. * ?>
  643. * <?= XOAD_Utilities::header() ?>
  644. *
  645. * <script type="text/javascript">
  646. *
  647. * var allowedClass = <?= XOAD_Client::register(new AllowedClass()) ?>;
  648. *
  649. * var deniedClass = <?= XOAD_Client::register(new DeniedClass()) ?>;
  650. *
  651. * alert(allowedClass.call());
  652. *
  653. * // This line will throw an exception.
  654. * // DeniedClass is not in the allowed classes list.
  655. * alert(deniedClass.call());
  656. *
  657. * </script>
  658. * </code>
  659. *
  660. * @access public
  661. *
  662. * @param mixed $classes The classes that can be accessed within
  663. * a callback request.
  664. *
  665. * @return void
  666. *
  667. * @static
  668. *
  669. */
  670. function allowClasses($classes)
  671. {
  672. $classesType = XOAD_Utilities::getType($classes);
  673.  
  674. if ( ! isset($GLOBALS['_XOAD_SERVER_ALLOWED_CLASSES'])) {
  675.  
  676. $GLOBALS['_XOAD_SERVER_ALLOWED_CLASSES'] = array();
  677. }
  678.  
  679. $allowedClasses =& $GLOBALS['_XOAD_SERVER_ALLOWED_CLASSES'];
  680.  
  681. if ($classesType == 'string') {
  682.  
  683. $allowedClasses[] = strtolower($classes);
  684.  
  685. } else if (($classesType == 's_array') || ($classesType == 'a_array')) {
  686.  
  687. foreach ($classes as $class) {
  688.  
  689. $allowedClasses[] = strtolower($class);
  690. }
  691. }
  692. }
  693.  
  694. /**
  695. * Adds specified classes to the denied classes map.
  696. *
  697. * <p>Example:</p>
  698. * <code>
  699. * <?php
  700. *
  701. * class AllowedClass
  702. * {
  703. * function call() { return 'AllowedClass->call()'; }
  704. * }
  705. *
  706. * class DeniedClass
  707. * {
  708. * function call() { return 'DeniedClass->call()'; }
  709. * }
  710. *
  711. * require_once('xoad.php');
  712. *
  713. * XOAD_Server::denyClasses('DeniedClass');
  714. *
  715. * if (XOAD_Server::runServer()) {
  716. *
  717. * exit;
  718. * }
  719. *
  720. * ?>
  721. * <?= XOAD_Utilities::header() ?>
  722. *
  723. * <script type="text/javascript">
  724. *
  725. * var allowedClass = <?= XOAD_Client::register(new AllowedClass()) ?>;
  726. *
  727. * var deniedClass = <?= XOAD_Client::register(new DeniedClass()) ?>;
  728. *
  729. * alert(allowedClass.call());
  730. *
  731. * // This line will throw an exception.
  732. * // DeniedClass is in the denied classes list.
  733. * alert(deniedClass.call());
  734. *
  735. * </script>
  736. * </code>
  737. *
  738. * @access public
  739. *
  740. * @param mixed $classes The classes that can NOT be accessed
  741. * within a callback request.
  742. *
  743. * @return void
  744. *
  745. * @static
  746. *
  747. */
  748. function denyClasses($classes)
  749. {
  750. $classesType = XOAD_Utilities::getType($classes);
  751.  
  752. if ( ! isset($GLOBALS['_XOAD_SERVER_DENIED_CLASSES'])) {
  753.  
  754. $GLOBALS['_XOAD_SERVER_DENIED_CLASSES'] = array();
  755. }
  756.  
  757. $deniedClasses =& $GLOBALS['_XOAD_SERVER_DENIED_CLASSES'];
  758.  
  759. if ($classesType == 'string') {
  760.  
  761. $deniedClasses[] = strtolower($classes);
  762.  
  763. } else if (($classesType == 's_array') || ($classesType == 'a_array')) {
  764.  
  765. foreach ($classes as $class) {
  766.  
  767. $deniedClasses[] = strtolower($class);
  768. }
  769. }
  770. }
  771.  
  772. /**
  773. * Checks if a class can be accessed within a callback request.
  774. *
  775. * @access public
  776. *
  777. * @param string $class The class name to check.
  778. *
  779. * @return bool true if the class can be accessed, false if
  780. * the class is denied and can NOT be accessed.
  781. *
  782. * @static
  783. *
  784. */
  785. function isClassAllowed($class)
  786. {
  787. $allowedClasses = null;
  788.  
  789. $deniedClasses = null;
  790.  
  791. if (isset($GLOBALS['_XOAD_SERVER_ALLOWED_CLASSES'])) {
  792.  
  793. $allowedClasses =& $GLOBALS['_XOAD_SERVER_ALLOWED_CLASSES'];
  794. }
  795.  
  796. if (isset($GLOBALS['_XOAD_SERVER_DENIED_CLASSES'])) {
  797.  
  798. $deniedClasses =& $GLOBALS['_XOAD_SERVER_DENIED_CLASSES'];
  799. }
  800.  
  801. if ( ! empty($deniedClasses)) {
  802.  
  803. if (in_array(strtolower($class), $deniedClasses)) {
  804.  
  805. return false;
  806. }
  807. }
  808.  
  809. if ( ! empty($allowedClasses)) {
  810.  
  811. if ( ! in_array(strtolower($class), $allowedClasses)) {
  812.  
  813. return false;
  814. }
  815. }
  816.  
  817. return true;
  818. }
  819.  
  820. /**
  821. * Adds a {@link XOAD_Server} events observer.
  822. *
  823. * @access public
  824. *
  825. * @param mixed $observer The observer object to add (must extend {@link XOAD_Observer}).
  826. *
  827. * @return string true on success, false otherwise.
  828. *
  829. * @static
  830. *
  831. */
  832. function addObserver(&$observer)
  833. {
  834. return parent::addObserver($observer, 'XOAD_Server');
  835. }
  836.  
  837. /**
  838. *
  839. * @access public
  840. *
  841. * @return bool
  842. *
  843. */
  844. function notifyObservers($event = 'default', $arg = null)
  845. {
  846. return parent::notifyObservers($event, $arg, 'XOAD_Server');
  847. }
  848. }
  849. ?>

Documentation generated on Sat, 12 Nov 2005 20:24:42 +0200 by phpDocumentor 1.3.0RC3