_application;
}
/**
* Set the application
* @param $application PKPApplication
*/
function setApplication(&$application) {
$this->_application =& $application;
}
/**
* Get the router names
* @return array an array of Router names
*/
function &getRouterNames() {
return $this->_routerNames;
}
/**
* Add a router name.
*
* NB: Routers will be called in the order that they
* have been added to the dispatcher. The first router
* that supports the request will be called. The last
* router should always be a "catch-all" router that
* supports all types of requests.
*
* NB: Routers must be part of the core package
* to be accepted by this dispatcher implementation.
*
* @param $routerName string a class name of a router
* to be given the chance to route the request.
* NB: These are class names and not instantiated objects. We'll
* use lazy instantiation to reduce the performance/memory impact
* to a minimum.
* @param $shortcut string a shortcut name for the router
* to be used for quick router instance retrieval.
*/
function addRouterName($routerName, $shortcut) {
assert(is_array($this->_routerNames) && is_string($routerName));
$this->_routerNames[$shortcut] = $routerName;
}
/**
* Determine the correct router for this request. Then
* let the router dispatch the request to the appropriate
* handler method.
* @param $request PKPRequest
*/
function dispatch(&$request) {
// Make sure that we have at least one router configured
$routerNames = $this->getRouterNames();
assert(count($routerNames) > 0);
// Go through all configured routers by priority
// and find out whether one supports the incoming request
foreach($routerNames as $shortcut => $routerCandidateName) {
$routerCandidate =& $this->_instantiateRouter($routerCandidateName, $shortcut);
// Does this router support the current request?
if ($routerCandidate->supports($request)) {
// Inject router and dispatcher into request
$request->setRouter($routerCandidate);
$request->setDispatcher($this);
// We've found our router and can go on
// to handle the request.
$router =& $routerCandidate;
$this->_router =& $router;
break;
}
}
// None of the router handles this request? This is a development-time
// configuration error.
if (is_null($router)) fatalError('None of the configured routers supports this request.');
// Can we serve a cached response?
if ($router->isCacheable($request)) {
$this->_requestCallbackHack =& $request;
if (Config::getVar('cache', 'web_cache')) {
if ($this->_displayCached($router, $request)) exit(); // Success
ob_start(array(&$this, '_cacheContent'));
}
} else {
if (isset($_SERVER['HTTP_X_MOZ']) && $_SERVER['HTTP_X_MOZ'] == 'prefetch') {
header('HTTP/1.0 403 Forbidden');
echo '403: Forbidden
Pre-fetching not allowed.';
exit;
}
}
AppLocale::initialize();
PluginRegistry::loadCategory('generic', true);
$router->route($request);
}
/**
* Build a handler request URL into PKPApplication.
* @param $request PKPRequest the request to be routed
* @param $shortcut string the short name of the router that should be used to construct the URL
* @param $newContext mixed Optional contextual paths
* @param $handler string Optional name of the handler to invoke
* @param $op string Optional name of operation to invoke
* @param $path mixed Optional string or array of args to pass to handler
* @param $params array Optional set of name => value pairs to pass as user parameters
* @param $anchor string Optional name of anchor to add to URL
* @param $escape boolean Whether or not to escape ampersands for this URL; default false.
* @return string the URL
*/
function url(&$request, $shortcut, $newContext = null, $handler = null, $op = null, $path = null,
$params = null, $anchor = null, $escape = false) {
// Instantiate the requested router
assert(isset($this->_routerNames[$shortcut]));
$routerName = $this->_routerNames[$shortcut];
$router =& $this->_instantiateRouter($routerName, $shortcut);
return $router->url($request, $newContext, $handler, $op, $path, $params, $anchor, $escape);
}
//
// Private helper methods
//
/**
* Instantiate a router
* @param $routerName string
* @param $shortcut string
*/
function &_instantiateRouter($routerName, $shortcut) {
if (!isset($this->_routerInstances[$shortcut])) {
// Routers must belong to the classes.core or lib.pkp.classes.core package
// NB: This prevents code inclusion attacks.
$allowedRouterPackages = array(
'classes.core',
'lib.pkp.classes.core'
);
// Instantiate the router
$router =& instantiate($routerName, 'PKPRouter', $allowedRouterPackages);
if (!is_object($router)) {
fatalError('Cannot instantiate requested router. Routers must belong to the core package and be of type "PKPRouter".');
}
$router->setApplication($this->_application);
$router->setDispatcher($this);
// Save the router instance for later re-use
$this->_routerInstances[$shortcut] =& $router;
}
return $this->_routerInstances[$shortcut];
}
/**
* Display the request contents from cache.
* @param $router PKPRouter
*/
function _displayCached(&$router, &$request) {
$filename = $router->getCacheFilename($request);
if (!file_exists($filename)) return false;
// Allow a caching proxy to work its magic if possible
$ifModifiedSince = $request->getIfModifiedSince();
if ($ifModifiedSince !== null && $ifModifiedSince >= filemtime($filename)) {
header('HTTP/1.1 304 Not Modified');
exit();
}
$fp = fopen($filename, 'r');
$data = fread($fp, filesize($filename));
fclose($fp);
$i = strpos($data, ':');
$time = substr($data, 0, $i);
$contents = substr($data, $i+1);
if (mktime() > $time + Config::getVar('cache', 'web_cache_hours') * 60 * 60) return false;
header('Content-Type: text/html; charset=' . Config::getVar('i18n', 'client_charset'));
echo $contents;
return true;
}
/**
* Cache content as a local file.
* @param $contents string
* @return string
*/
function _cacheContent($contents) {
assert(is_a($this->_router, 'PKPRouter'));
if ($contents == '') return $contents; // Do not cache empties
$filename = $this->_router->getCacheFilename($this->_requestCallbackHack);
$fp = fopen($filename, 'w');
if ($fp) {
fwrite($fp, mktime() . ':' . $contents);
fclose($fp);
}
return $contents;
}
/**
* Handle a 404 error (page not found).
*/
function handle404() {
PKPRequest::_checkThis();
header('HTTP/1.0 404 Not Found');
fatalError('404 Not Found');
}
}
?>