Open Journal Systems  3.3.0
Dispatcher.inc.php
1 <?php
2 
17 class Dispatcher {
19  var $_application;
20 
22  var $_routerNames = array();
23 
25  var $_routerInstances = array();
26 
28  var $_router;
29 
32 
37  function &getApplication() {
38  return $this->_application;
39  }
40 
45  function setApplication($application) {
46  $this->_application = $application;
47  }
48 
53  function &getRouterNames() {
54  return $this->_routerNames;
55  }
56 
77  function addRouterName($routerName, $shortcut) {
78  assert(is_array($this->_routerNames) && is_string($routerName));
79  $this->_routerNames[$shortcut] = $routerName;
80  }
81 
88  function dispatch($request) {
89  // Make sure that we have at least one router configured
90  $routerNames = $this->getRouterNames();
91  assert(count($routerNames) > 0);
92 
93  // Go through all configured routers by priority
94  // and find out whether one supports the incoming request
95  foreach($routerNames as $shortcut => $routerCandidateName) {
96  $routerCandidate =& $this->_instantiateRouter($routerCandidateName, $shortcut);
97 
98  // Does this router support the current request?
99  if ($routerCandidate->supports($request)) {
100  // Inject router and dispatcher into request
101  $request->setRouter($routerCandidate);
102  $request->setDispatcher($this);
103 
104  // We've found our router and can go on
105  // to handle the request.
106  $router =& $routerCandidate;
107  $this->_router =& $router;
108  break;
109  }
110  }
111 
112  // None of the router handles this request? This is a development-time
113  // configuration error.
114  if (is_null($router)) fatalError('None of the configured routers supports this request.');
115 
116  // Can we serve a cached response?
117  if ($router->isCacheable($request)) {
118  $this->_requestCallbackHack =& $request;
119  if (Config::getVar('cache', 'web_cache')) {
120  if ($this->_displayCached($router, $request)) exit(); // Success
121  ob_start(array($this, '_cacheContent'));
122  }
123  } else {
124  if (isset($_SERVER['HTTP_X_MOZ']) && $_SERVER['HTTP_X_MOZ'] == 'prefetch') {
125  header('HTTP/1.0 403 Forbidden');
126  echo '403: Forbidden<br><br>Pre-fetching not allowed.';
127  exit;
128  }
129  }
130 
131  AppLocale::initialize($request);
132  PluginRegistry::loadCategory('generic', true);
133  PluginRegistry::loadCategory('pubIds', true);
134 
135  HookRegistry::call('Dispatcher::dispatch', $request);
136 
137  // Reload the context after generic plugins have loaded so that changes to
138  // the context schema can take place
139  import('classes.core.Services');
140  $contextSchema = \Services::get('schema')->get(SCHEMA_CONTEXT, true);
141  $request->getRouter()->getContext($request, 1, true);
142 
143  $router->route($request);
144  }
145 
159  function url($request, $shortcut, $newContext = null, $handler = null, $op = null, $path = null,
160  $params = null, $anchor = null, $escape = false) {
161  // Instantiate the requested router
162  assert(isset($this->_routerNames[$shortcut]));
163  $routerName = $this->_routerNames[$shortcut];
164  $router =& $this->_instantiateRouter($routerName, $shortcut);
165 
166  return $router->url($request, $newContext, $handler, $op, $path, $params, $anchor, $escape);
167  }
168 
169  //
170  // Private helper methods
171  //
172 
178  function &_instantiateRouter($routerName, $shortcut) {
179  if (!isset($this->_routerInstances[$shortcut])) {
180  // Routers must belong to the classes.core or lib.pkp.classes.core package
181  // NB: This prevents code inclusion attacks.
182  $allowedRouterPackages = array(
183  'classes.core',
184  'lib.pkp.classes.core'
185  );
186 
187  // Instantiate the router
188  $router =& instantiate($routerName, 'PKPRouter', $allowedRouterPackages);
189  if (!is_object($router)) {
190  fatalError('Cannot instantiate requested router. Routers must belong to the core package and be of type "PKPRouter".');
191  }
192  $router->setApplication($this->_application);
193  $router->setDispatcher($this);
194 
195  // Save the router instance for later re-use
196  $this->_routerInstances[$shortcut] =& $router;
197  }
198 
199  return $this->_routerInstances[$shortcut];
200  }
201 
206  function _displayCached($router, $request) {
207  $filename = $router->getCacheFilename($request);
208  if (!file_exists($filename)) return false;
209 
210  // Allow a caching proxy to work its magic if possible
211  $ifModifiedSince = $request->getIfModifiedSince();
212  if ($ifModifiedSince !== null && $ifModifiedSince >= filemtime($filename)) {
213  header('HTTP/1.1 304 Not Modified');
214  exit();
215  }
216 
217  $fp = fopen($filename, 'r');
218  $data = fread($fp, filesize($filename));
219  fclose($fp);
220 
221  $i = strpos($data, ':');
222  $time = substr($data, 0, $i);
223  $contents = substr($data, $i+1);
224 
225  if (mktime() > $time + Config::getVar('cache', 'web_cache_hours') * 60 * 60) return false;
226 
227  header('Content-Type: text/html; charset=' . Config::getVar('i18n', 'client_charset'));
228 
229  echo $contents;
230  return true;
231  }
232 
238  function _cacheContent($contents) {
239  assert(is_a($this->_router, 'PKPRouter'));
240  if ($contents == '') return $contents; // Do not cache empties
241  $filename = $this->_router->getCacheFilename($this->_requestCallbackHack);
242  $fp = fopen($filename, 'w');
243  if ($fp) {
244  fwrite($fp, mktime() . ':' . $contents);
245  fclose($fp);
246  }
247  return $contents;
248  }
249 
253  function handle404() {
254  header('HTTP/1.0 404 Not Found');
255  fatalError('404 Not Found');
256  }
257 }
258 
259 
$op
$op
Definition: lib/pkp/pages/help/index.php:18
AppLocale\initialize
static initialize($request)
Definition: env1/MockAppLocale.inc.php:31
instantiate
& instantiate($fullyQualifiedClassName, $expectedTypes=null, $expectedPackages=null, $expectedMethods=null, $constructorArg=null)
Definition: functions.inc.php:165
Dispatcher\getRouterNames
& getRouterNames()
Definition: Dispatcher.inc.php:68
$application
$application
Definition: index.php:65
Dispatcher\setApplication
setApplication($application)
Definition: Dispatcher.inc.php:60
Dispatcher\addRouterName
addRouterName($routerName, $shortcut)
Definition: Dispatcher.inc.php:92
PluginRegistry\loadCategory
static loadCategory($category, $enabledOnly=false, $mainContextId=null)
Definition: PluginRegistry.inc.php:103
Dispatcher\url
url($request, $shortcut, $newContext=null, $handler=null, $op=null, $path=null, $params=null, $anchor=null, $escape=false)
Definition: Dispatcher.inc.php:174
Config\getVar
static getVar($section, $key, $default=null)
Definition: Config.inc.php:35
Dispatcher\dispatch
dispatch($request)
Definition: Dispatcher.inc.php:103
Dispatcher\$_routerInstances
$_routerInstances
Definition: Dispatcher.inc.php:34
Seboettg\Collection\count
count()
Definition: ArrayListTrait.php:253
Dispatcher\_instantiateRouter
& _instantiateRouter($routerName, $shortcut)
Definition: Dispatcher.inc.php:193
Dispatcher\getApplication
& getApplication()
Definition: Dispatcher.inc.php:52
Dispatcher\$_application
$_application
Definition: Dispatcher.inc.php:22
Dispatcher\_cacheContent
_cacheContent($contents)
Definition: Dispatcher.inc.php:253
Dispatcher\$_routerNames
$_routerNames
Definition: Dispatcher.inc.php:28
fatalError
if(!function_exists('import')) fatalError($reason)
Definition: functions.inc.php:32
Dispatcher\_displayCached
_displayCached($router, $request)
Definition: Dispatcher.inc.php:221
HookRegistry\call
static call($hookName, $args=null)
Definition: HookRegistry.inc.php:86
Dispatcher
Class dispatching HTTP requests to handlers.
Definition: Dispatcher.inc.php:17
Dispatcher\$_router
$_router
Definition: Dispatcher.inc.php:40
Dispatcher\$_requestCallbackHack
$_requestCallbackHack
Definition: Dispatcher.inc.php:46
PKPServices\get
static get($service)
Definition: PKPServices.inc.php:49
Dispatcher\handle404
handle404()
Definition: Dispatcher.inc.php:268