PageRenderTime 46ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/classes/core/PKPRequest.inc.php

https://github.com/michaeljoyce/pkp-lib
PHP | 764 lines | 430 code | 102 blank | 232 comment | 82 complexity | e2c054c37074c8025b9d90583cd09538 MD5 | raw file
Possible License(s): LGPL-2.1, BSD-3-Clause
  1. <?php
  2. /**
  3. * @file classes/core/PKPRequest.inc.php
  4. *
  5. * Copyright (c) 2000-2010 John Willinsky
  6. * Distributed under the GNU GPL v2. For full terms see the file docs/COPYING.
  7. *
  8. * @class PKPRequest
  9. * @ingroup core
  10. *
  11. * @brief Class providing operations associated with HTTP requests.
  12. */
  13. // $Id$
  14. class PKPRequest {
  15. //
  16. // Internal state - please do not reference directly
  17. //
  18. /** @var PKPRouter router instance used to route this request */
  19. var $_router = null;
  20. /** @var array the request variables cache (GET/POST) */
  21. var $_requestVars = null;
  22. /** @var string request base path */
  23. var $_basePath;
  24. /** @var string request path */
  25. var $_requestPath;
  26. /** @var boolean true if restful URLs are enabled in the config */
  27. var $_isRestfulUrlsEnabled;
  28. /** @var boolean true if path info is enabled for this server */
  29. var $_isPathInfoEnabled;
  30. /** @var string server host */
  31. var $_serverHost;
  32. /** @var string base url */
  33. var $_baseUrl;
  34. /** @var string request protocol */
  35. var $_protocol;
  36. /** @var boolean true, if deprecation warning is switched on */
  37. var $_deprecationWarning = null;
  38. /**
  39. * get the router instance
  40. * @return PKPRouter
  41. */
  42. function &getRouter() {
  43. return $this->_router;
  44. }
  45. /**
  46. * set the router instance
  47. * @param $router instance PKPRouter
  48. */
  49. function setRouter(&$router) {
  50. $this->_router =& $router;
  51. }
  52. /**
  53. * Perform an HTTP redirect to an absolute or relative (to base system URL) URL.
  54. * @param $url string (exclude protocol for local redirects)
  55. */
  56. function redirectUrl($url) {
  57. PKPRequest::_checkThis();
  58. if (HookRegistry::call('Request::redirect', array(&$url))) {
  59. return;
  60. }
  61. header("Refresh: 0; url=$url");
  62. exit();
  63. }
  64. /**
  65. * Redirect to the current URL, forcing the HTTPS protocol to be used.
  66. */
  67. function redirectSSL() {
  68. $_this =& PKPRequest::_checkThis();
  69. $url = 'https://' . $_this->getServerHost() . $_this->getRequestPath();
  70. $queryString = $_this->getQueryString();
  71. if (!empty($queryString)) $url .= "?$queryString";
  72. $_this->redirectUrl($url);
  73. }
  74. /**
  75. * Redirect to the current URL, forcing the HTTP protocol to be used.
  76. */
  77. function redirectNonSSL() {
  78. $_this =& PKPRequest::_checkThis();
  79. $url = 'http://' . $_this->getServerHost() . $_this->getRequestPath();
  80. $queryString = $_this->getQueryString();
  81. if (!empty($queryString)) $url .= "?$queryString";
  82. $_this->redirectUrl($url);
  83. }
  84. /**
  85. * Handle a 404 error (page not found).
  86. */
  87. function handle404() {
  88. PKPRequest::_checkThis();
  89. header('HTTP/1.0 404 Not Found');
  90. fatalError('404 Not Found');
  91. }
  92. /**
  93. * Get the base URL of the request (excluding script).
  94. * @return string
  95. */
  96. function getBaseUrl() {
  97. $_this =& PKPRequest::_checkThis();
  98. if (!isset($_this->_baseUrl)) {
  99. $serverHost = $_this->getServerHost(null);
  100. if ($serverHost !== null) {
  101. // Auto-detection worked.
  102. $_this->_baseUrl = $_this->getProtocol() . '://' . $_this->getServerHost() . $_this->getBasePath();
  103. } else {
  104. // Auto-detection didn't work (e.g. this is a command-line call); use configuration param
  105. $_this->_baseUrl = Config::getVar('general', 'base_url');
  106. }
  107. HookRegistry::call('Request::getBaseUrl', array(&$_this->_baseUrl));
  108. }
  109. return $_this->_baseUrl;
  110. }
  111. /**
  112. * Get the base path of the request (excluding trailing slash).
  113. * @return string
  114. */
  115. function getBasePath() {
  116. $_this =& PKPRequest::_checkThis();
  117. if (!isset($_this->_basePath)) {
  118. $_this->_basePath = dirname($_SERVER['SCRIPT_NAME']);
  119. if ($_this->_basePath == '/' || $_this->_basePath == '\\') {
  120. $_this->_basePath = '';
  121. }
  122. HookRegistry::call('Request::getBasePath', array(&$_this->_basePath));
  123. }
  124. return $_this->_basePath;
  125. }
  126. /**
  127. * Deprecated
  128. * @see PKPPageRouter::getIndexUrl()
  129. */
  130. function getIndexUrl() {
  131. static $indexUrl;
  132. $_this =& PKPRequest::_checkThis();
  133. if (!isset($indexUrl)) {
  134. $indexUrl = $_this->_delegateToRouter('getIndexUrl');
  135. // Call legacy hook
  136. HookRegistry::call('Request::getIndexUrl', array(&$indexUrl));
  137. }
  138. return $indexUrl;
  139. }
  140. /**
  141. * Get the complete URL to this page, including parameters.
  142. * @return string
  143. */
  144. function getCompleteUrl() {
  145. $_this =& PKPRequest::_checkThis();
  146. static $completeUrl;
  147. if (!isset($completeUrl)) {
  148. $completeUrl = $_this->getRequestUrl();
  149. $queryString = $_this->getQueryString();
  150. if (!empty($queryString)) $completeUrl .= "?$queryString";
  151. HookRegistry::call('Request::getCompleteUrl', array(&$completeUrl));
  152. }
  153. return $completeUrl;
  154. }
  155. /**
  156. * Get the complete URL of the request.
  157. * @return string
  158. */
  159. function getRequestUrl() {
  160. $_this =& PKPRequest::_checkThis();
  161. static $requestUrl;
  162. if (!isset($requestUrl)) {
  163. $requestUrl = $_this->getProtocol() . '://' . $_this->getServerHost() . $_this->getRequestPath();
  164. HookRegistry::call('Request::getRequestUrl', array(&$requestUrl));
  165. }
  166. return $requestUrl;
  167. }
  168. /**
  169. * Get the complete set of URL parameters to the current request.
  170. * @return string
  171. */
  172. function getQueryString() {
  173. PKPRequest::_checkThis();
  174. static $queryString;
  175. if (!isset($queryString)) {
  176. $queryString = isset($_SERVER['QUERY_STRING'])?$_SERVER['QUERY_STRING']:'';
  177. HookRegistry::call('Request::getQueryString', array(&$queryString));
  178. }
  179. return $queryString;
  180. }
  181. /**
  182. * Get the complete set of URL parameters to the current request as an associative array.
  183. * @return array
  184. */
  185. function getQueryArray() {
  186. $_this =& PKPRequest::_checkThis();
  187. $queryString = $_this->getQueryString();
  188. $queryArray = array();
  189. if (isset($queryString)) {
  190. parse_str($queryString, $queryArray);
  191. }
  192. return $queryArray;
  193. }
  194. /**
  195. * Get the completed path of the request.
  196. * @return string
  197. */
  198. function getRequestPath() {
  199. $_this =& PKPRequest::_checkThis();
  200. if (!isset($_this->_requestPath)) {
  201. if ($_this->isRestfulUrlsEnabled()) {
  202. $_this->_requestPath = $_this->getBasePath();
  203. } else {
  204. $_this->_requestPath = $_SERVER['SCRIPT_NAME'];
  205. }
  206. if ($_this->isPathInfoEnabled()) {
  207. $_this->_requestPath .= isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : '';
  208. }
  209. HookRegistry::call('Request::getRequestPath', array(&$_this->_requestPath));
  210. }
  211. return $_this->_requestPath;
  212. }
  213. /**
  214. * Get the server hostname in the request. May optionally include the
  215. * port number if non-standard.
  216. * @return string
  217. */
  218. function getServerHost($default = 'localhost') {
  219. $_this =& PKPRequest::_checkThis();
  220. if (!isset($_this->_serverHost)) {
  221. $_this->_serverHost = isset($_SERVER['HTTP_X_FORWARDED_HOST']) ? $_SERVER['HTTP_X_FORWARDED_HOST']
  222. : (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST']
  223. : (isset($_SERVER['HOSTNAME']) ? $_SERVER['HOSTNAME']
  224. : $default));
  225. HookRegistry::call('Request::getServerHost', array(&$_this->_serverHost));
  226. }
  227. return $_this->_serverHost;
  228. }
  229. /**
  230. * Get the protocol used for the request (HTTP or HTTPS).
  231. * @return string
  232. */
  233. function getProtocol() {
  234. $_this =& PKPRequest::_checkThis();
  235. if (!isset($_this->_protocol)) {
  236. $_this->_protocol = (!isset($_SERVER['HTTPS']) || strtolower($_SERVER['HTTPS']) != 'on') ? 'http' : 'https';
  237. HookRegistry::call('Request::getProtocol', array(&$_this->_protocol));
  238. }
  239. return $_this->_protocol;
  240. }
  241. /**
  242. * Get the request method
  243. * @return string
  244. */
  245. function getRequestMethod() {
  246. PKPRequest::_checkThis();
  247. return $_SERVER['REQUEST_METHOD'];
  248. }
  249. /**
  250. * Determine whether the request is a POST request
  251. * @return boolean
  252. */
  253. function isPost() {
  254. $_this =& PKPRequest::_checkThis();
  255. return ($_this->getRequestMethod() == 'POST');
  256. }
  257. /**
  258. * Determine whether the request is a GET request
  259. * @return boolean
  260. */
  261. function isGet() {
  262. $_this =& PKPRequest::_checkThis();
  263. return ($_this->getRequestMethod() == 'GET');
  264. }
  265. /**
  266. * Get the remote IP address of the current request.
  267. * @return string
  268. */
  269. function getRemoteAddr() {
  270. PKPRequest::_checkThis();
  271. static $ipaddr;
  272. if (!isset($ipaddr)) {
  273. if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
  274. $ipaddr = $_SERVER['HTTP_X_FORWARDED_FOR'];
  275. } else if (isset($_SERVER['REMOTE_ADDR'])) {
  276. $ipaddr = $_SERVER['REMOTE_ADDR'];
  277. }
  278. if (!isset($ipaddr) || empty($ipaddr)) {
  279. $ipaddr = getenv('REMOTE_ADDR');
  280. }
  281. if (!isset($ipaddr) || $ipaddr == false) {
  282. $ipaddr = '';
  283. }
  284. // If multiple addresses are listed, take the last. (Supports ipv6.)
  285. if (preg_match_all('/([0-9.a-fA-F:]+)/', $ipaddr, $matches)) {
  286. $ipaddr = $matches[0][count($matches[0])-1];
  287. }
  288. HookRegistry::call('Request::getRemoteAddr', array(&$ipaddr));
  289. }
  290. return $ipaddr;
  291. }
  292. /**
  293. * Get the remote domain of the current request
  294. * @return string
  295. */
  296. function getRemoteDomain() {
  297. $_this =& PKPRequest::_checkThis();
  298. static $remoteDomain;
  299. if (!isset($remoteDomain)) {
  300. $remoteDomain = null;
  301. $remoteDomain = @getHostByAddr($_this->getRemoteAddr());
  302. HookRegistry::call('Request::getRemoteDomain', array(&$remoteDomain));
  303. }
  304. return $remoteDomain;
  305. }
  306. /**
  307. * Get the user agent of the current request.
  308. * @return string
  309. */
  310. function getUserAgent() {
  311. PKPRequest::_checkThis();
  312. static $userAgent;
  313. if (!isset($userAgent)) {
  314. if (isset($_SERVER['HTTP_USER_AGENT'])) {
  315. $userAgent = $_SERVER['HTTP_USER_AGENT'];
  316. }
  317. if (!isset($userAgent) || empty($userAgent)) {
  318. $userAgent = getenv('HTTP_USER_AGENT');
  319. }
  320. if (!isset($userAgent) || $userAgent == false) {
  321. $userAgent = '';
  322. }
  323. HookRegistry::call('Request::getUserAgent', array(&$userAgent));
  324. }
  325. return $userAgent;
  326. }
  327. /**
  328. * Determine whether a user agent is a bot or not using an external
  329. * list of regular expressions.
  330. */
  331. function isBot() {
  332. $_this =& PKPRequest::_checkThis();
  333. static $isBot;
  334. if (!isset($isBot)) {
  335. $userAgent = $_this->getUserAgent();
  336. $isBot = false;
  337. $userAgentsFile = Config::getVar('general', 'registry_dir') . DIRECTORY_SEPARATOR . 'botAgents.txt';
  338. $regexps = array_filter(file($userAgentsFile), create_function('&$a', 'return ($a = trim($a)) && !empty($a) && $a[0] != \'#\';'));
  339. foreach ($regexps as $regexp) {
  340. if (String::regexp_match($regexp, $userAgent)) {
  341. $isBot = true;
  342. return $isBot;
  343. }
  344. }
  345. }
  346. return $isBot;
  347. }
  348. /**
  349. * Return true if PATH_INFO is enabled.
  350. */
  351. function isPathInfoEnabled() {
  352. $_this =& PKPRequest::_checkThis();
  353. if (!isset($_this->_isPathInfoEnabled)) {
  354. $_this->_isPathInfoEnabled = Config::getVar('general', 'disable_path_info')?false:true;
  355. }
  356. return $_this->_isPathInfoEnabled;
  357. }
  358. /**
  359. * Return true if RESTFUL_URLS is enabled.
  360. */
  361. function isRestfulUrlsEnabled() {
  362. $_this =& PKPRequest::_checkThis();
  363. if (!isset($_this->_isRestfulUrlsEnabled)) {
  364. $_this->_isRestfulUrlsEnabled = Config::getVar('general', 'restful_urls')?true:false;
  365. }
  366. return $_this->_isRestfulUrlsEnabled;
  367. }
  368. /**
  369. * Get site data.
  370. * @return Site
  371. */
  372. function &getSite() {
  373. PKPRequest::_checkThis();
  374. $site =& Registry::get('site', true, null);
  375. if ($site === null) {
  376. $siteDao =& DAORegistry::getDAO('SiteDAO');
  377. $site =& $siteDao->getSite();
  378. }
  379. return $site;
  380. }
  381. /**
  382. * Get the user session associated with the current request.
  383. * @return Session
  384. */
  385. function &getSession() {
  386. PKPRequest::_checkThis();
  387. $session =& Registry::get('session', true, null);
  388. if ($session === null) {
  389. $sessionManager =& SessionManager::getManager();
  390. $session = $sessionManager->getUserSession();
  391. }
  392. return $session;
  393. }
  394. /**
  395. * Get the user associated with the current request.
  396. * @return User
  397. */
  398. function &getUser() {
  399. PKPRequest::_checkThis();
  400. $user =& Registry::get('user', true, null);
  401. if ($user === null) {
  402. $sessionManager =& SessionManager::getManager();
  403. $session =& $sessionManager->getUserSession();
  404. $user =& $session->getUser();
  405. }
  406. return $user;
  407. }
  408. /**
  409. * Get the value of a GET/POST variable.
  410. * @return mixed
  411. */
  412. function getUserVar($key) {
  413. $_this =& PKPRequest::_checkThis();
  414. // Get all vars (already cleaned)
  415. $vars =& $_this->getUserVars();
  416. if (isset($vars[$key])) {
  417. return $vars[$key];
  418. } else {
  419. return null;
  420. }
  421. }
  422. /**
  423. * Get all GET/POST variables as an array
  424. * @return array
  425. */
  426. function &getUserVars() {
  427. $_this =& PKPRequest::_checkThis();
  428. if (!isset($_this->_requestVars)) {
  429. $_this->_requestVars = array_merge($_GET, $_POST);
  430. $_this->cleanUserVar($_this->_requestVars);
  431. }
  432. return $_this->_requestVars;
  433. }
  434. /**
  435. * Get the value of a GET/POST variable generated using the Smarty
  436. * html_select_date and/or html_select_time function.
  437. * @param $prefix string
  438. * @param $defaultDay int
  439. * @param $defaultMonth int
  440. * @param $defaultYear int
  441. * @param $defaultHour int
  442. * @param $defaultMinute int
  443. * @param $defaultSecond int
  444. * @return Date
  445. */
  446. function getUserDateVar($prefix, $defaultDay = null, $defaultMonth = null, $defaultYear = null, $defaultHour = 0, $defaultMinute = 0, $defaultSecond = 0) {
  447. $_this =& PKPRequest::_checkThis();
  448. $monthPart = $_this->getUserVar($prefix . 'Month');
  449. $dayPart = $_this->getUserVar($prefix . 'Day');
  450. $yearPart = $_this->getUserVar($prefix . 'Year');
  451. $hourPart = $_this->getUserVar($prefix . 'Hour');
  452. $minutePart = $_this->getUserVar($prefix . 'Minute');
  453. $secondPart = $_this->getUserVar($prefix . 'Second');
  454. switch ($_this->getUserVar($prefix . 'Meridian')) {
  455. case 'pm':
  456. if (is_numeric($hourPart) && $hourPart != 12) $hourPart += 12;
  457. break;
  458. case 'am':
  459. default:
  460. // Do nothing.
  461. break;
  462. }
  463. if (empty($dayPart)) $dayPart = $defaultDay;
  464. if (empty($monthPart)) $monthPart = $defaultMonth;
  465. if (empty($yearPart)) $yearPart = $defaultYear;
  466. if (empty($hourPart)) $hourPart = $defaultHour;
  467. if (empty($minutePart)) $minutePart = $defaultMinute;
  468. if (empty($secondPart)) $secondPart = $defaultSecond;
  469. if (empty($monthPart) || empty($dayPart) || empty($yearPart)) return null;
  470. return mktime($hourPart, $minutePart, $secondPart, $monthPart, $dayPart, $yearPart);
  471. }
  472. /**
  473. * Sanitize a user-submitted variable (i.e., GET/POST/Cookie variable).
  474. * Strips slashes if necessary, then sanitizes variable as per Core::cleanVar().
  475. * @param $var mixed
  476. */
  477. function cleanUserVar(&$var, $stripHtml = false) {
  478. $_this =& PKPRequest::_checkThis();
  479. if (isset($var) && is_array($var)) {
  480. foreach ($var as $key => $value) {
  481. $_this->cleanUserVar($var[$key], $stripHtml);
  482. }
  483. } else if (isset($var)) {
  484. $var = Core::cleanVar(get_magic_quotes_gpc() ? stripslashes($var) : $var);
  485. } else {
  486. return null;
  487. }
  488. }
  489. /**
  490. * Get the value of a cookie variable.
  491. * @return mixed
  492. */
  493. function getCookieVar($key) {
  494. $_this =& PKPRequest::_checkThis();
  495. if (isset($_COOKIE[$key])) {
  496. $value = $_COOKIE[$key];
  497. $_this->cleanUserVar($value);
  498. return $value;
  499. } else {
  500. return null;
  501. }
  502. }
  503. /**
  504. * Set a cookie variable.
  505. * @param $key string
  506. * @param $value mixed
  507. */
  508. function setCookieVar($key, $value) {
  509. $_this =& PKPRequest::_checkThis();
  510. setcookie($key, $value, 0, $_this->getBasePath());
  511. $_COOKIE[$key] = $value;
  512. }
  513. /**
  514. * Redirect to the specified page within a PKP Application.
  515. * Shorthand for a common call to $request->redirect($router->url(...)).
  516. * @param $context Array The optional contextual paths
  517. * @param $page string The name of the op to redirect to.
  518. * @param $op string optional The name of the op to redirect to.
  519. * @param $path mixed string or array containing path info for redirect.
  520. * @param $params array Map of name => value pairs for additional parameters
  521. * @param $anchor string Name of desired anchor on the target page
  522. */
  523. function redirect($context = null, $page = null, $op = null, $path = null, $params = null, $anchor = null) {
  524. $_this =& PKPRequest::_checkThis();
  525. $router =& $_this->getRouter();
  526. $_this->redirectUrl($router->url($_this, $context, $page, $op, $path, $params, $anchor));
  527. }
  528. /**
  529. * Deprecated
  530. * @see PKPPageRouter::getContext()
  531. */
  532. function &getContext() {
  533. $_this =& PKPRequest::_checkThis();
  534. return $_this->_delegateToRouter('getContext');
  535. }
  536. /**
  537. * Deprecated
  538. * @see PKPPageRouter::getRequestedContextPath()
  539. */
  540. function getRequestedContextPath($contextLevel = null) {
  541. $_this =& PKPRequest::_checkThis();
  542. // Emulate the old behavior of getRequestedContextPath for
  543. // backwards compatibility.
  544. if (is_null($contextLevel)) {
  545. return $_this->_delegateToRouter('getRequestedContextPaths');
  546. } else {
  547. return array($_this->_delegateToRouter('getRequestedContextPath', $contextLevel));
  548. }
  549. }
  550. /**
  551. * Deprecated
  552. * @see PKPPageRouter::getRequestedPage()
  553. */
  554. function getRequestedPage() {
  555. $_this =& PKPRequest::_checkThis();
  556. return $_this->_delegateToRouter('getRequestedPage');
  557. }
  558. /**
  559. * Deprecated
  560. * @see PKPPageRouter::getRequestedOp()
  561. */
  562. function getRequestedOp() {
  563. $_this =& PKPRequest::_checkThis();
  564. return $_this->_delegateToRouter('getRequestedOp');
  565. }
  566. /**
  567. * Deprecated
  568. * @see PKPPageRouter::getRequestedArgs()
  569. */
  570. function getRequestedArgs() {
  571. $_this =& PKPRequest::_checkThis();
  572. return $_this->_delegateToRouter('getRequestedArgs');
  573. }
  574. /**
  575. * Deprecated
  576. * @see PKPPageRouter::url()
  577. */
  578. function url($context = null, $page = null, $op = null, $path = null,
  579. $params = null, $anchor = null, $escape = false) {
  580. $_this =& PKPRequest::_checkThis();
  581. return $_this->_delegateToRouter('url', $context, $page, $op, $path,
  582. $params, $anchor, $escape);
  583. }
  584. /**
  585. * This method exists to maintain backwards compatibility
  586. * with static calls to PKPRequest.
  587. *
  588. * If it is called non-statically then it will simply
  589. * return $this. Otherwise it will issue a deprecation
  590. * warning and expect a global singleton instance in the
  591. * registry that will be returned instead.
  592. *
  593. * NB: This method is protected and may not be used by
  594. * external classes. It should also only be used in legacy
  595. * methods.
  596. *
  597. * @return PKPRequest
  598. */
  599. function &_checkThis() {
  600. if (isset($this) && is_a($this, 'PKPRequest')) {
  601. return $this;
  602. } else {
  603. // We have to use a static variable here as
  604. // this deprecated call is static itself.
  605. static $deprecationWarning = null;
  606. if (is_null($deprecationWarning)) {
  607. $deprecationWarning = Config::getVar('debug', 'deprecation_warnings');
  608. if (is_null($deprecationWarning)) $deprecationWarning = false;
  609. }
  610. if ($deprecationWarning) trigger_error('Deprecated static function call');
  611. $instance =& Registry::get('request');
  612. assert(!is_null($instance));
  613. return $instance;
  614. }
  615. }
  616. /**
  617. * This method exists to maintain backwards compatibility
  618. * with calls to methods that have been factored into the
  619. * Router implementations.
  620. *
  621. * It delegates the call to the router and returns the result.
  622. *
  623. * NB: This method is protected and may not be used by
  624. * external classes. It should also only be used in legacy
  625. * methods.
  626. *
  627. * @return mixed depends on the called method
  628. */
  629. function &_delegateToRouter($method) {
  630. $_this =& PKPRequest::_checkThis();
  631. if (is_null($_this->_deprecationWarning)) {
  632. $_this->_deprecationWarning = Config::getVar('debug', 'deprecation_warnings');
  633. if (is_null($_this->_deprecationWarning)) $_this->_deprecationWarning = false;
  634. }
  635. if ($_this->_deprecationWarning) trigger_error('Deprecated function');
  636. $router =& $_this->getRouter();
  637. // Construct the method call
  638. $callable = array($router, $method);
  639. // Get additional parameters but replace
  640. // the first parameter (currently the
  641. // method to be called) with the request
  642. // as all router methods required the request
  643. // as their first parameter.
  644. $parameters = func_get_args();
  645. $parameters[0] =& $_this;
  646. $returner = call_user_func_array($callable, $parameters);
  647. return $returner;
  648. }
  649. }
  650. ?>