e107_handlers/redirection_class.php
<?php
/*
* e107 website system
*
* Copyright (C) 2008-2010 e107 Inc (e107.org)
* Released under the terms and conditions of the
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt)
*
* Redirection handler
*
* $URL$
* $Id$
*/
/**
* Redirection class
*
* @package e107
* @category e107_handlers
* @version 1.0
* @author Cameron
* @copyright Copyright (C) 2008-2010 e107 Inc.
*/
class redirection
{
/**
* List of pages to not check against e_SELF
*
* @var array
*/
protected $self_exceptions = array();
/**
* List of pages to not check against defset('e_PAGE')
*
* @var array
*/
protected $page_exceptions = array();
/**
* List of queries to not check against e_QUERY
* @var array
*/
protected $query_exceptions = array();
public $staticDomains;
public $domain;
public $subdomain;
public $self;
public $siteurl;
/**
* Manage Member-Only Mode.
*
* @return void
*/
function __construct()
{
$this->self_exceptions = array(e_SIGNUP, SITEURL.'fpw.php', e_LOGIN, SITEURL.'membersonly.php');
$this->page_exceptions = array('e_ajax.php', 'e_js.php', 'e_jslib.php', 'sitedown.php',e_LOGIN, 'secimg.php');
$this->query_exceptions = array('logout');
$this->staticDomains = defset('e_HTTP_STATIC');
$this->domain = defset('e_DOMAIN');
$this->subdomain = defset('e_SUBDOMAIN');
$this->self = $this->getSelf(true);
// Remove from self_exceptions: SITEURL, SITEURL.'index.php', // allows a custom frontpage to be viewed while logged out and membersonly active.
}
/**
* @return array
*/
function getSelfExceptions()
{
return $this->self_exceptions;
}
/**
* FIXME - build self_exceptions dynamically - use URL assembling to match the proper URLs later
* Store the current URL in a cookie for 5 minutes so we can return to it after being logged out.
* @param string $url if empty self url will be used
* @param boolean $forceNoSef if false REQUEST_URI will be used (mod_rewrite support)
* @return redirection
*/
function setPreviousUrl($url = null, $forceNoSef = false, $forceCookie = false)
{
if(!$url)
{
// e_SELF, defset('e_PAGE') and e_QUERY not set early enough when in e_SINGLE_ENTRY mod
if(defset('e_SELF') && in_array(e_SELF, $this->self_exceptions))
{
return;
}
elseif(in_array(e_REQUEST_URI, $this->self_exceptions))
{
return;
}
if(defset('e_PAGE') && in_array(e_PAGE, $this->page_exceptions))
{
return;
}
if(in_array($_SERVER['QUERY_STRING'], $this->query_exceptions))
{
return;
}
$url = $this->getSelf($forceNoSef);
}
$this->setCookie('_previousUrl', $url, 300, $forceCookie);
//session_set(e_COOKIE.'_previousUrl',$self ,(time()+300));
return $this;
}
/**
* @param $full
* @return array|mixed|string|string[]
*/
public function getSelf($full = false)
{
if($full)
{
$url = e_REQUEST_URL;//(e_QUERY) ? e_SELF."?".e_QUERY : e_SELF;
}
else
{
// TODO - e107::requestUri() - sanitize, add support for various HTTP servers
$url = e_REQUEST_URI;
}
return $url;
}
/**
* Return the URL the admin was on, prior to being logged-out.
* @return string
*/
public function getPreviousUrl()
{
return $this->getCookie('_previousUrl');
}
/**
* Get value stored with self::setCookie()
* @param string $name
* @return mixed
*/
public function getCookie($name) //TODO move to e107_class or a new user l class.
{
$cookiename = e_COOKIE."_".$name;
$session = e107::getSession();
if($session->has($name))
{
// expired - cookie like session implementation
if((integer) $session->get($name.'_expire') < time())
{
$session->clear($name.'_expire')
->clear($name);
return false;
}
return $session->get($name);
}
// fix - prevent null values
elseif(isset($_COOKIE[$cookiename]) && $_COOKIE[$cookiename])
{
return $_COOKIE[$cookiename];
}
return false;
}
/**
* Register url in current session
* @param string $name
* @param string $value
* @param integer $expire expire after value in seconds, null (default) - ignore
* @return redirection
*/
public function setCookie($name, $value, $expire = null, $forceCookie = false)
{
$cookiename = e_COOKIE."_".$name;
$session = e107::getSession();
if(!$forceCookie && e107::getPref('cookie_name') != 'cookie')
{
// expired - cookie like session implementation
if(null !== $expire) $session->set($name.'_expire', time() + (integer) $expire);
$session->set($name, $value);
}
else
{
cookie($cookiename, $value, time() + (integer) $expire, e_HTTP, e107::getLanguage()->getCookieDomain());
}
return $this;
}
/**
* Clear data set via self::setCookie()
* @param string $name
* @return redirection
*/
public function clearCookie($name)
{
$cookiename = e_COOKIE."_".$name;
$session = e107::getSession();
$session->clear($name)
->clear($name.'_expire');
cookie($cookiename, null, null, e_HTTP, e107::getLanguage()->getCookieDomain());
return $this;
}
/**
* Perform re-direction when Maintenance Mode is active.
*
* @return void
*/
public function checkMaintenance()
{
// prevent looping.
if(strpos(defset('e_SELF'), 'admin.php') !== FALSE || strpos(defset('e_SELF'), 'sitedown.php') !== FALSE)
{
return;
}
if(deftrue('NO_MAINTENANCE')) // per-page disable option.
{
return;
}
if(e107::getPref('maintainance_flag') && defset('e_PAGE') !== 'secure_img_render.php')
{
// if not admin
$allowed = e107::getPref('maintainance_flag');
if(defset('e_PAGE') === 'login.php' && empty($_POST)) // allow admins/members to login.
{
return null;
}
// if(!ADMIN
// or if not mainadmin - ie e_UC_MAINADMIN
// || (e_UC_MAINADMIN == e107::getPref('maintainance_flag') && !getperms('0')))
if(!check_class($allowed) && !getperms('0'))
{
// 307 Temporary Redirect
$this->redirect(SITEURL.'sitedown.php', TRUE, 307);
}
}
}
/**
* Check if user is logged in.
*
* @return void
*/
public function checkMembersOnly()
{
if(!e107::getPref('membersonly_enabled'))
{
return;
}
if(USER && !e_AJAX_REQUEST)
{
$this->restoreMembersOnlyUrl();
return;
}
if(e_AJAX_REQUEST)
{
return;
}
if(strpos(defset('e_PAGE'), 'admin') !== false)
{
return;
}
if(in_array(e_SELF, $this->self_exceptions))
{
return;
}
if(in_array(defset('e_PAGE'), $this->page_exceptions))
{
return;
}
foreach (e107::getPref('membersonly_exceptions') as $val)
{
$srch = trim($val);
if(!empty($srch) && strpos(e_SELF, $srch) !== false)
{
return;
}
}
/*
echo "e_SELF=".e_SELF;
echo "<br />defset('e_PAGE')=".defset('e_PAGE');
print_a( $this->self_exceptions);
print_a($this->page_exceptions);
*/
$this->saveMembersOnlyUrl();
$redirectType = e107::getPref('membersonly_redirect');
$redirectURL = ($redirectType == 'splash') ? 'membersonly.php' : 'login.php';
$this->redirect(e_HTTP.$redirectURL);
}
/**
* Store the current URL so that it can retrieved after login.
*
* @return void
*/
private function saveMembersOnlyUrl($forceNoSef = false)
{
// remember the url for after-login.
//$afterlogin = e_COOKIE.'_afterlogin';
$this->setCookie('_afterlogin', $this->getSelf($forceNoSef), 300);
//session_set($afterlogin, $url, time() + 300);
}
/**
* Restore the previously saved URL, and redirect the User to it after login.
*
* @return void
*/
private function restoreMembersOnlyUrl()
{
$url = $this->getCookie('_afterlogin');
if(USER && $url)
{
//session_set(e_COOKIE.'_afterlogin', FALSE, -1000);
$this->clearCookie('_afterlogin');
$this->redirect($url);
}
}
/**
* @return void
*/
public function redirectPrevious()
{
if($this->getPreviousUrl())
{
$this->redirect($this->getPreviousUrl());
}
}
/**
* @param $url
* @param $replace
* @param $http_response_code
* @param $preventCache
* @return void
*/
public function redirect($url, $replace = TRUE, $http_response_code = NULL, $preventCache = true)
{
$this->go($url, $replace, $http_response_code, $preventCache);
exit;
}
/**
* Redirect to the given URI
*
* @param string $url or error code number. eg. 404 = Not Found. If left empty SITEURL will be used.
* @param boolean $replace - default TRUE
* @param integer|null $http_response_code - default NULL
* @param boolean $preventCache
* @return void
*/
public function go($url='', $replace = TRUE, $http_response_code = NULL, $preventCache = true)
{
if(e107::isCli())
{
return null;
}
$url = str_replace("&", "&", $url); // cleanup when using e_QUERY in $url;
if(empty($url))
{
$url = SITEURL;
}
if($url == 'admin')
{
$url = SITEURLBASE. e_ADMIN_ABS;
}
if(deftrue('e_DEBUG_REDIRECT') && strpos($url, 'sitedown.php') === false)
{
$error = debug_backtrace();
$sent = headers_list();
$message = "Headers previously sent: ".print_r($sent,true);
e107::getLog()->addDebug($message);
print_a($message);
$message = "URL: ".$url."\nFile: ".$error[1]['file']."\nLine: ".$error[1]['line']."\nClass: ".$error[1]['class']."\nFunction: ".$error[1]['function']."\n\n";
e107::getLog()->addDebug($message);
echo "Debug active";
print_a($message);
echo "Go to : <a href='".$url."'>".$url."</a>";
e107::getLog()->toFile('redirect.log',"Redirect Log", true);
return;
}
if(session_id())
{
e107::getSession()->end();
}
if($preventCache)
{
header('Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0');
header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
}
// issue #3179 redirect with response code >= 400 doesn't work. Only response codes below 400.
if(null === $http_response_code || $http_response_code >= 400)
{
header('Location: '.$url, $replace);
}
else
{
header('Location: '.$url, $replace, $http_response_code);
}
// Safari endless loop fix.
header('Content-Length: 0');
// write session if needed
//if(session_id()) session_write_close();
exit();
}
/**
* If a static subdomain is detected, returns the equivalent non-static domain.
* @return string|false
*/
public function redirectStaticDomain()
{
if(empty($this->staticDomains))
{
return false;
}
$tmp = explode('.',$this->domain);
if(!empty($tmp[0]) && strpos($tmp[0], 'static') !== false)
{
unset($tmp[0]);
return str_replace($this->domain.'/', implode('.',$tmp).'/', $this->self);
}
return false;
}
}