4 * @file classes/core/PKPRequest.inc.php
6 * Copyright (c) 2000-2009 John Willinsky
7 * Distributed under the GNU GPL v2. For full terms see the file docs/COPYING.
12 * @brief Class providing operations associated with HTTP requests.
15 // $Id: PKPRequest.inc.php,v 1.18 2009/07/17 20:26:07 asmecher Exp $
20 * Perform an HTTP redirect to an absolute or relative (to base system URL) URL.
21 * @param $url string (exclude protocol for local redirects)
23 function redirectUrl($url) {
24 if (HookRegistry
::call('Request::redirect', array(&$url))) {
28 header("Refresh: 0; url=$url");
33 * Redirect to the current URL, forcing the HTTPS protocol to be used.
35 function redirectSSL() {
36 $url = 'https://' . PKPRequest
::getServerHost() . PKPRequest
::getRequestPath();
37 $queryString = PKPRequest
::getQueryString();
38 if (!empty($queryString)) $url .= "?$queryString";
39 PKPRequest
::redirectUrl($url);
43 * Redirect to the current URL, forcing the HTTP protocol to be used.
45 function redirectNonSSL() {
46 $url = 'http://' . PKPRequest
::getServerHost() . PKPRequest
::getRequestPath();
47 $queryString = PKPRequest
::getQueryString();
48 if (!empty($queryString)) $url .= "?$queryString";
49 PKPRequest
::redirectUrl($url);
53 * Handle a 404 error (page not found).
55 function handle404() {
56 header('HTTP/1.0 404 Not Found');
57 fatalError('404 Not Found');
61 * Get the base URL of the request (excluding script).
64 function getBaseUrl() {
67 if (!isset($baseUrl)) {
68 $serverHost = PKPRequest
::getServerHost(null);
69 if ($serverHost !== null) {
70 // Auto-detection worked.
71 $baseUrl = PKPRequest
::getProtocol() . '://' . PKPRequest
::getServerHost() . PKPRequest
::getBasePath();
73 // Auto-detection didn't work (e.g. this is a command-line call); use configuration param
74 $baseUrl = Config
::getVar('general', 'base_url');
76 HookRegistry
::call('Request::getBaseUrl', array(&$baseUrl));
83 * Get the base path of the request (excluding trailing slash).
86 function getBasePath() {
89 if (!isset($basePath)) {
90 $basePath = dirname($_SERVER['SCRIPT_NAME']);
91 if ($basePath == '/' ||
$basePath == '\\') {
94 HookRegistry
::call('Request::getBasePath', array(&$basePath));
101 * Get the URL to the index script.
104 function getIndexUrl() {
107 if (!isset($indexUrl)) {
108 if (PKPRequest
::isRestfulUrlsEnabled()) {
109 $indexUrl = PKPRequest
::getBaseUrl();
111 $indexUrl = PKPRequest
::getBaseUrl() . '/' . basename($_SERVER['SCRIPT_NAME']);
113 HookRegistry
::call('Request::getIndexUrl', array(&$indexUrl));
120 * Get the complete URL to this page, including parameters.
123 function getCompleteUrl() {
126 if (!isset($completeUrl)) {
127 $completeUrl = PKPRequest
::getRequestUrl();
128 $queryString = PKPRequest
::getQueryString();
129 if (!empty($queryString)) $completeUrl .= "?$queryString";
130 HookRegistry
::call('Request::getCompleteUrl', array(&$completeUrl));
137 * Get the complete URL of the request.
140 function getRequestUrl() {
143 if (!isset($requestUrl)) {
144 $requestUrl = PKPRequest
::getProtocol() . '://' . PKPRequest
::getServerHost() . PKPRequest
::getRequestPath();
145 HookRegistry
::call('Request::getRequestUrl', array(&$requestUrl));
152 * Get the complete set of URL parameters to the current request.
155 function getQueryString() {
158 if (!isset($queryString)) {
159 $queryString = isset($_SERVER['QUERY_STRING'])?
$_SERVER['QUERY_STRING']:'';
160 HookRegistry
::call('Request::getQueryString', array(&$queryString));
167 * Get the complete set of URL parameters to the current request as an associative array.
170 function getQueryArray() {
171 $queryString = PKPRequest
::getQueryString();
172 $queryArray = array();
174 if (isset($queryString)) {
175 parse_str($queryString, $queryArray);
182 * Get the completed path of the request.
185 function getRequestPath() {
187 if (!isset($requestPath)) {
188 if (PKPRequest
::isRestfulUrlsEnabled()) {
189 $requestPath = PKPRequest
::getBasePath();
191 $requestPath = $_SERVER['SCRIPT_NAME'];
194 if (PKPRequest
::isPathInfoEnabled()) {
195 $requestPath .= isset($_SERVER['PATH_INFO']) ?
$_SERVER['PATH_INFO'] : '';
197 HookRegistry
::call('Request::getRequestPath', array(&$requestPath));
203 * Get the server hostname in the request. May optionally include the
204 * port number if non-standard.
207 function getServerHost($default = 'localhost') {
209 if (!isset($serverHost)) {
210 $serverHost = isset($_SERVER['HTTP_X_FORWARDED_HOST']) ?
$_SERVER['HTTP_X_FORWARDED_HOST']
211 : (isset($_SERVER['HTTP_HOST']) ?
$_SERVER['HTTP_HOST']
212 : (isset($_SERVER['HOSTNAME']) ?
$_SERVER['HOSTNAME']
214 HookRegistry
::call('Request::getServerHost', array(&$serverHost));
220 * Get the protocol used for the request (HTTP or HTTPS).
223 function getProtocol() {
225 if (!isset($protocol)) {
226 $protocol = (!isset($_SERVER['HTTPS']) ||
strtolower($_SERVER['HTTPS']) != 'on') ?
'http' : 'https';
227 HookRegistry
::call('Request::getProtocol', array(&$protocol));
233 * Get the request method
236 function getRequestMethod() {
237 return $_SERVER['REQUEST_METHOD'];
241 * Determine whether the request is a POST request
245 return (PKPRequest
::getRequestMethod() == 'POST');
249 * Determine whether the request is a GET request
253 return (PKPRequest
::getRequestMethod() == 'GET');
257 * Get the remote IP address of the current request.
260 function getRemoteAddr() {
262 if (!isset($ipaddr)) {
263 if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
264 $ipaddr = $_SERVER['HTTP_X_FORWARDED_FOR'];
265 } else if (isset($_SERVER['REMOTE_ADDR'])) {
266 $ipaddr = $_SERVER['REMOTE_ADDR'];
268 if (!isset($ipaddr) ||
empty($ipaddr)) {
269 $ipaddr = getenv('REMOTE_ADDR');
271 if (!isset($ipaddr) ||
$ipaddr == false) {
275 // If multiple addresses are listed, take the first. (Supports ipv6.)
276 if (preg_match('/^([0-9.a-fA-F:]+)/', $ipaddr, $matches)) {
277 $ipaddr = $matches[1];
279 HookRegistry
::call('Request::getRemoteAddr', array(&$ipaddr));
285 * Get the remote domain of the current request
288 function getRemoteDomain() {
289 static $remoteDomain;
290 if (!isset($remoteDomain)) {
291 $remoteDomain = null;
292 $remoteDomain = @getHostByAddr
(PKPRequest
::getRemoteAddr());
293 HookRegistry
::call('Request::getRemoteDomain', array(&$remoteDomain));
295 return $remoteDomain;
299 * Get the user agent of the current request.
302 function getUserAgent() {
304 if (!isset($userAgent)) {
305 if (isset($_SERVER['HTTP_USER_AGENT'])) {
306 $userAgent = $_SERVER['HTTP_USER_AGENT'];
308 if (!isset($userAgent) ||
empty($userAgent)) {
309 $userAgent = getenv('HTTP_USER_AGENT');
311 if (!isset($userAgent) ||
$userAgent == false) {
314 HookRegistry
::call('Request::getUserAgent', array(&$userAgent));
320 * Determine whether a user agent is a bot or not using an external
321 * list of regular expressions.
325 if (!isset($isBot)) {
326 $userAgent = PKPRequest
::getUserAgent();
328 $userAgentsFile = Config
::getVar('general', 'registry_dir') . DIRECTORY_SEPARATOR
. 'botAgents.txt';
329 $regexps = array_filter(file($userAgentsFile), create_function('&$a', 'return ($a = trim($a)) && !empty($a) && $a[0] != \'#\';'));
330 foreach ($regexps as $regexp) {
331 if (String::regexp_match($regexp, $userAgent)) {
341 * Return true if PATH_INFO is enabled.
343 function isPathInfoEnabled() {
344 static $isPathInfoEnabled;
345 if (!isset($isPathInfoEnabled)) {
346 $isPathInfoEnabled = Config
::getVar('general', 'disable_path_info')?
false:true;
348 return $isPathInfoEnabled;
352 * Return true if RESTFUL_URLS is enabled.
354 function isRestfulUrlsEnabled() {
355 static $isRestfulUrlsEnabled;
356 if (!isset($isRestfulUrlsEnabled)) {
357 $isRestfulUrlsEnabled = Config
::getVar('general', 'restful_urls')?
true:false;
359 return $isRestfulUrlsEnabled;
366 function &getSite() {
367 $site =& Registry
::get('site', true, null);
368 if ($site === null) {
369 $siteDao =& DAORegistry
::getDAO('SiteDAO');
370 $site =& $siteDao->getSite();
377 * Get the user session associated with the current request.
380 function &getSession() {
381 $session =& Registry
::get('session', true, null);
383 if ($session === null) {
384 $sessionManager =& SessionManager
::getManager();
385 $session = $sessionManager->getUserSession();
392 * Get the user associated with the current request.
395 function &getUser() {
396 $user =& Registry
::get('user', true, null);
397 if ($user === null) {
398 $sessionManager =& SessionManager
::getManager();
399 $session =& $sessionManager->getUserSession();
400 $user =& $session->getUser();
407 * A Generic call to a context defining object (e.g. a Journal, a Conference, or a SchedConf)
408 * This class must be implemented by all PKPApplications
410 function &getContext() {
411 // Child classes will override this method.
417 * A Generic call to a context-defined path (e.g. a Journal or a Conference's path)
418 * @param $contextLevel int (optional) the number of levels of context to return in the path
419 * @return array of String (each element the path to one context element)
421 function getRequestedContextPath($contextLevel = null) {
422 // Child classes will override this method.
427 * Get the page requested in the URL.
428 * @return String the page path (under the "pages" directory)
430 function getRequestedPage() {
434 if (PKPRequest
::isPathInfoEnabled()) {
435 $application = PKPApplication
::getApplication();
436 $contextDepth = $application->getContextDepth();
438 if (isset($_SERVER['PATH_INFO'])) {
439 $vars = explode('/', $_SERVER['PATH_INFO']);
440 if (count($vars) > $contextDepth+
1) {
441 $page = Core
::cleanFileVar($vars[$contextDepth+
1]);
445 $page = PKPRequest
::getUserVar('page');
453 * Get the operation requested in the URL (assumed to exist in the requested page handler).
456 function getRequestedOp() {
460 if (PKPRequest
::isPathInfoEnabled()) {
461 $application = PKPApplication
::getApplication();
462 $contextDepth = $application->getContextDepth();
464 if (isset($_SERVER['PATH_INFO'])) {
465 $vars = explode('/', $_SERVER['PATH_INFO']);
466 if (count($vars) > $contextDepth+
2) {
467 $op = Core
::cleanFileVar($vars[$contextDepth+
2]);
471 return PKPRequest
::getUserVar('op');
473 $op = empty($op) ?
'index' : $op;
480 * Get the arguments requested in the URL (not GET/POST arguments, only arguments appended to the URL separated by "/").
483 function getRequestedArgs() {
484 if (PKPRequest
::isPathInfoEnabled()) {
486 if (isset($_SERVER['PATH_INFO'])) {
487 $application = PKPApplication
::getApplication();
488 $contextDepth = $application->getContextDepth();
489 $vars = explode('/', $_SERVER['PATH_INFO']);
490 if (count($vars) > $contextDepth+
3) {
491 $args = array_slice($vars, $contextDepth+
3);
492 for ($i=0, $count=count($args); $i<$count; $i++
) {
493 $args[$i] = Core
::cleanVar(get_magic_quotes_gpc() ?
stripslashes($args[$i]) : $args[$i]);
498 $args = PKPRequest
::getUserVar('path');
499 if (empty($args)) $args = array();
500 elseif (!is_array($args)) $args = array($args);
506 * Get the value of a GET/POST variable.
509 function getUserVar($key) {
513 $vars = array_merge($_GET, $_POST);
516 if (isset($vars[$key])) {
517 // FIXME Do not clean vars again if function is called more than once?
518 PKPRequest
::cleanUserVar($vars[$key]);
526 * Get the value of a GET/POST variable generated using the Smarty
527 * html_select_date and/or html_select_time function.
528 * @param $prefix string
529 * @param $defaultDay int
530 * @param $defaultMonth int
531 * @param $defaultYear int
532 * @param $defaultHour int
533 * @param $defaultMinute int
534 * @param $defaultSecond int
537 function getUserDateVar($prefix, $defaultDay = null, $defaultMonth = null, $defaultYear = null, $defaultHour = 0, $defaultMinute = 0, $defaultSecond = 0) {
538 $monthPart = PKPRequest
::getUserVar($prefix . 'Month');
539 $dayPart = PKPRequest
::getUserVar($prefix . 'Day');
540 $yearPart = PKPRequest
::getUserVar($prefix . 'Year');
541 $hourPart = PKPRequest
::getUserVar($prefix . 'Hour');
542 $minutePart = PKPRequest
::getUserVar($prefix . 'Minute');
543 $secondPart = PKPRequest
::getUserVar($prefix . 'Second');
545 switch (PKPRequest
::getUserVar($prefix . 'Meridian')) {
547 if (is_numeric($hourPart) && $hourPart != 12) $hourPart +
= 12;
555 if (empty($dayPart)) $dayPart = $defaultDay;
556 if (empty($monthPart)) $monthPart = $defaultMonth;
557 if (empty($yearPart)) $yearPart = $defaultYear;
558 if (empty($hourPart)) $hourPart = $defaultHour;
559 if (empty($minutePart)) $minutePart = $defaultMinute;
560 if (empty($secondPart)) $secondPart = $defaultSecond;
562 if (empty($monthPart) ||
empty($dayPart) ||
empty($yearPart)) return null;
563 return mktime($hourPart, $minutePart, $secondPart, $monthPart, $dayPart, $yearPart);
567 * Sanitize a user-submitted variable (i.e., GET/POST/Cookie variable).
568 * Strips slashes if necessary, then sanitizes variable as per Core::cleanVar().
571 function cleanUserVar(&$var, $stripHtml = false) {
572 if (isset($var) && is_array($var)) {
573 foreach ($var as $key => $value) {
574 PKPRequest
::cleanUserVar($var[$key], $stripHtml);
576 } else if (isset($var)) {
577 $var = Core
::cleanVar(get_magic_quotes_gpc() ?
stripslashes($var) : $var);
585 * Get the value of a cookie variable.
588 function getCookieVar($key) {
589 if (isset($_COOKIE[$key])) {
590 $value = $_COOKIE[$key];
591 PKPRequest
::cleanUserVar($value);
599 * Set a cookie variable.
601 * @param $value mixed
603 function setCookieVar($key, $value) {
604 setcookie($key, $value, 0, PKPRequest
::getBasePath());
605 $_COOKIE[$key] = $value;
609 * Redirect to the specified page within a PKP Application. Shorthand for a common call to Request::redirect(Request::url(...)).
610 * @param $context Array The optional contextual paths
611 * @param $page string The name of the op to redirect to.
612 * @param $op string optional The name of the op to redirect to.
613 * @param $path mixed string or array containing path info for redirect.
614 * @param $params array Map of name => value pairs for additional parameters
615 * @param $anchor string Name of desired anchor on the target page
617 function redirect($context = null, $page = null, $op = null, $path = null, $params = null, $anchor = null) {
618 PKPRequest
::redirectUrl(PKPRequest
::url($context, $page, $op, $path, $params, $anchor));
622 * Build a URL into PKPApplication.
623 * @param $context Array Optional contextual paths
624 * @param $page string Optional name of page to invoke
625 * @param $op string Optional name of operation to invoke
626 * @param $path mixed Optional string or array of args to pass to handler
627 * @param $params array Optional set of name => value pairs to pass as user parameters
628 * @param $anchor string Optional name of anchor to add to URL
629 * @param $escape boolean Whether or not to escape ampersands for this URL; default false.
631 function url($context = null, $page = null, $op = null, $path = null,
632 $params = null, $anchor = null, $escape = false) {
634 $application =& PKPApplication
::getApplication();
635 $contextList = $application->getContextList();
636 $contextDepth = $application->getContextDepth();
638 // set an empty array in case that $context was null
639 if ( !isset($context) ) {
641 for ($i = 0; $i < $contextDepth; $i++
) {
646 $pathInfoDisabled = !PKPRequest
::isPathInfoEnabled();
648 $amp = $escape?
'&':'&';
649 $prefix = $pathInfoDisabled?
$amp:'?';
651 // Establish defaults for page and op
652 $defaultPage = PKPRequest
::getRequestedPage();
653 $defaultOp = PKPRequest
::getRequestedOp();
655 // Declare some empty variables
656 $contextPathProvided = false;
657 $contextPath = array();
659 foreach ($contextList as $contextName) {
660 $contextValue = array_shift($context);
661 if (isset($contextValue)) {
662 $contextPath[] = rawurlencode($contextValue);
663 $contextPathProvided = true;
665 $contextObject =& Request
::getContextByName($contextName);
666 if ($contextObject) $contextPath[] = $contextObject->getPath();
667 else $contextPath[] = 'index';
671 // If a context has been specified, don't supply default page or op.
672 if($contextPathProvided) {
677 // Get overridden base URLs (if available).
678 if ( isset($contextPath[0])) {
679 $overriddenBaseUrl = Config
::getVar('general', "base_url[$contextPath[0]]");
682 // If a page has been specified, don't supply a default op.
684 $page = rawurlencode($page);
687 $page = $defaultPage;
691 if ($op) $op = rawurlencode($op);
692 else $op = $defaultOp;
694 // Process additional parameters
695 $additionalParams = '';
696 if (!empty($params)) foreach ($params as $key => $value) {
697 if (is_array($value)) foreach($value as $element) {
698 $additionalParams .= $prefix . $key . '%5B%5D=' . rawurlencode($element);
701 $additionalParams .= $prefix . $key . '=' . rawurlencode($value);
707 if (!empty($anchor)) $anchor = '#' . rawurlencode($anchor);
711 if (is_array($path)) $path = array_map('rawurlencode', $path);
712 else $path = array(rawurlencode($path));
713 if (!$page) $page = 'index';
714 if (!$op) $op = 'index';
718 if ($pathInfoDisabled) {
719 $joiner = $amp . 'path%5B%5D=';
720 if (!empty($path)) $pathString = $joiner . implode($joiner, $path);
721 if (empty($overriddenBaseUrl) && count($contextPath)) {
723 foreach ($contextList as $contextName) {
724 $contextValue = array_shift($contextPath);
725 if (!empty($contextValue)) {
726 $baseParams .= $contextName.'='.$contextValue;
727 $baseParams .= count($contextPath)?
$amp:'';
732 else $baseParams = '';
734 if (!empty($page) ||
!empty($overriddenBaseUrl)) {
735 $baseParams .= empty($baseParams)?
'?':$amp;
736 $baseParams .= "page=$page";
738 $baseParams .= $amp . "op=$op";
742 if (!empty($path)) $pathString = '/' . implode('/', $path);
743 if (empty($overriddenBaseUrl) && count($contextPath)) $baseParams = "/". implode("/", $contextPath);
745 array_shift($contextPath); // Throw away first
746 $baseParams = implode('/', $contextPath);
750 $baseParams .= "/$page";
752 $baseParams .= "/$op";
757 return ((empty($overriddenBaseUrl)?PKPRequest
::getIndexUrl():$overriddenBaseUrl) . $baseParams . $pathString . $additionalParams . $anchor);