1<?php 2/* 3 * e107 website system 4 * 5 * Copyright (C) 2008-2010 e107 Inc (e107.org) 6 * Released under the terms and conditions of the 7 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) 8 * 9 * Redirection handler 10 * 11 * $URL$ 12 * $Id$ 13 */ 14 15/** 16 * Redirection class 17 * 18 * @package e107 19 * @category e107_handlers 20 * @version 1.0 21 * @author Cameron 22 * @copyright Copyright (C) 2008-2010 e107 Inc. 23 */ 24class redirection 25{ 26 /** 27 * List of pages to not check against e_SELF 28 * 29 * @var array 30 */ 31 protected $self_exceptions = array(); 32 33 /** 34 * List of pages to not check against e_PAGE 35 * 36 * @var array 37 */ 38 protected $page_exceptions = array(); 39 40 /** 41 * List of queries to not check against e_QUERY 42 * @var array 43 */ 44 protected $query_exceptions = array(); 45 46 /** 47 * Manage Member-Only Mode. 48 * 49 * @return void 50 */ 51 function __construct() 52 { 53 $this->self_exceptions = array(e_SIGNUP, SITEURL.'fpw.php', e_LOGIN, SITEURL.'membersonly.php'); 54 $this->page_exceptions = array('e_ajax.php', 'e_js.php', 'e_jslib.php', 'sitedown.php',e_LOGIN, 'secimg.php'); 55 $this->query_exceptions = array('logout'); 56 57 // Remove from self_exceptions: SITEURL, SITEURL.'index.php', // allows a custom frontpage to be viewed while logged out and membersonly active. 58 } 59 60 61 62 function getSelfExceptions() 63 { 64 return $this->self_exceptions; 65 } 66 67 /** 68 * FIXME - build self_exceptions dynamically - use URL assembling to match the proper URLs later 69 * Store the current URL in a cookie for 5 minutes so we can return to it after being logged out. 70 * @param string $url if empty self url will be used 71 * @param boolean $forceNoSef if false REQUEST_URI will be used (mod_rewrite support) 72 * @return redirection 73 */ 74 function setPreviousUrl($url = null, $forceNoSef = false, $forceCookie = false) 75 { 76 if(!$url) 77 { 78 // e_SELF, e_PAGE and e_QUERY not set early enough when in e_SINGLE_ENTRY mod 79 if(defset('e_SELF') && in_array(e_SELF, $this->self_exceptions)) 80 { 81 return; 82 } 83 elseif(in_array(e_REQUEST_URI, $this->self_exceptions)) 84 { 85 return; 86 } 87 88 if(defset('e_PAGE') && in_array(e_PAGE, $this->page_exceptions)) 89 { 90 return; 91 } 92 if(in_array($_SERVER['QUERY_STRING'], $this->query_exceptions)) 93 { 94 return; 95 } 96 $url = $this->getSelf($forceNoSef); 97 } 98 99 $this->setCookie('_previousUrl', $url, 300, $forceCookie); 100 //session_set(e_COOKIE.'_previousUrl',$self ,(time()+300)); 101 102 return $this; 103 } 104 105 public function getSelf($full = false) 106 { 107 if($full) 108 { 109 $url = e_REQUEST_URL;//(e_QUERY) ? e_SELF."?".e_QUERY : e_SELF; 110 } 111 else 112 { 113 // TODO - e107::requestUri() - sanitize, add support for various HTTP servers 114 $url = e_REQUEST_URI; 115 } 116 return $url; 117 } 118 119 /** 120 * Return the URL the admin was on, prior to being logged-out. 121 * @return string 122 */ 123 public function getPreviousUrl() 124 { 125 return $this->getCookie('_previousUrl'); 126 } 127 128 /** 129 * Get value stored with self::setCookie() 130 * @param string $name 131 * @return mixed 132 */ 133 public function getCookie($name) //TODO move to e107_class or a new user l class. 134 { 135 $cookiename = e_COOKIE."_".$name; 136 $session = e107::getSession(); 137 138 if($session->has($name)) 139 { 140 // expired - cookie like session implementation 141 if((integer) $session->get($name.'_expire') < time()) 142 { 143 $session->clear($name.'_expire') 144 ->clear($name); 145 return false; 146 } 147 return $session->get($name); 148 } 149 // fix - prevent null values 150 elseif(isset($_COOKIE[$cookiename]) && $_COOKIE[$cookiename]) 151 { 152 return $_COOKIE[$cookiename]; 153 } 154 155 return false; 156 } 157 158 /** 159 * Register url in current session 160 * @param string $name 161 * @param string $value 162 * @param integer $expire expire after value in seconds, null (default) - ignore 163 * @return redirection 164 */ 165 public function setCookie($name, $value, $expire = null, $forceCookie = false) 166 { 167 $cookiename = e_COOKIE."_".$name; 168 $session = e107::getSession(); 169 170 if(!$forceCookie && e107::getPref('cookie_name') != 'cookie') 171 { 172 // expired - cookie like session implementation 173 if(null !== $expire) $session->set($name.'_expire', time() + (integer) $expire); 174 $session->set($name, $value); 175 } 176 else 177 { 178 cookie($cookiename, $value, time() + (integer) $expire, e_HTTP, e107::getLanguage()->getCookieDomain()); 179 } 180 181 return $this; 182 } 183 184 /** 185 * Clear data set via self::setCookie() 186 * @param string $name 187 * @return redirection 188 */ 189 public function clearCookie($name) 190 { 191 $cookiename = e_COOKIE."_".$name; 192 $session = e107::getSession(); 193 $session->clear($name) 194 ->clear($name.'_expire'); 195 cookie($cookiename, null, null, e_HTTP, e107::getLanguage()->getCookieDomain()); 196 return $this; 197 } 198 199 200 /** 201 * Perform re-direction when Maintenance Mode is active. 202 * 203 * @return void 204 */ 205 public function checkMaintenance() 206 { 207 // prevent looping. 208 if(strpos(defset('e_SELF'), 'admin.php') !== FALSE || strpos(defset('e_SELF'), 'sitedown.php') !== FALSE) 209 { 210 return; 211 } 212 213 if(deftrue('NO_MAINTENANCE')) // per-page disable option. 214 { 215 return; 216 } 217 218 if(e107::getPref('maintainance_flag') && defset('e_PAGE') != 'secure_img_render.php') 219 { 220 // if not admin 221 222 $allowed = e107::getPref('maintainance_flag'); 223 224 // if(!ADMIN 225 // or if not mainadmin - ie e_UC_MAINADMIN 226 // || (e_UC_MAINADMIN == e107::getPref('maintainance_flag') && !getperms('0'))) 227 228 if(!check_class($allowed) && !getperms('0')) 229 { 230 // 307 Temporary Redirect 231 $this->redirect(SITEURL.'sitedown.php', TRUE, 307); 232 } 233 } 234 else 235 { 236 return; 237 } 238 } 239 240 241 /** 242 * Check if user is logged in. 243 * 244 * @return void 245 */ 246 public function checkMembersOnly() 247 { 248 249 if(!e107::getPref('membersonly_enabled')) 250 { 251 return; 252 } 253 254 if(USER && !e_AJAX_REQUEST) 255 { 256 $this->restoreMembersOnlyUrl(); 257 return; 258 } 259 if(e_AJAX_REQUEST) 260 { 261 return; 262 } 263 if(strpos(e_PAGE, 'admin') !== FALSE) 264 { 265 return; 266 } 267 if(in_array(e_SELF, $this->self_exceptions)) 268 { 269 return; 270 } 271 if(in_array(e_PAGE, $this->page_exceptions)) 272 { 273 return; 274 } 275 foreach (e107::getPref('membersonly_exceptions') as $val) 276 { 277 $srch = trim($val); 278 if(strpos(e_SELF, $srch) !== FALSE) 279 { 280 return; 281 } 282 } 283 284 /* 285 echo "e_SELF=".e_SELF; 286 echo "<br />e_PAGE=".e_PAGE; 287 print_a( $this->self_exceptions); 288 print_a($this->page_exceptions); 289 */ 290 291 $this->saveMembersOnlyUrl(); 292 293 $redirectType = e107::getPref('membersonly_redirect'); 294 295 $redirectURL = ($redirectType == 'splash') ? 'membersonly.php' : 'login.php'; 296 297 $this->redirect(e_HTTP.$redirectURL); 298 } 299 300 301 /** 302 * Store the current URL so that it can retrieved after login. 303 * 304 * @return void 305 */ 306 private function saveMembersOnlyUrl($forceNoSef = false) 307 { 308 // remember the url for after-login. 309 //$afterlogin = e_COOKIE.'_afterlogin'; 310 $this->setCookie('_afterlogin', $this->getSelf($forceNoSef), 300); 311 //session_set($afterlogin, $url, time() + 300); 312 } 313 314 315 /** 316 * Restore the previously saved URL, and redirect the User to it after login. 317 * 318 * @return void 319 */ 320 private function restoreMembersOnlyUrl() 321 { 322 $url = $this->getCookie('_afterlogin'); 323 if(USER && $url) 324 { 325 //session_set(e_COOKIE.'_afterlogin', FALSE, -1000); 326 $this->clearCookie('_afterlogin'); 327 $this->redirect($url); 328 } 329 } 330 331 public function redirectPrevious() 332 { 333 if($this->getPreviousUrl()) 334 { 335 $this->redirect($this->getPreviousUrl()); 336 } 337 } 338 339 340 public function redirect($url, $replace = TRUE, $http_response_code = NULL, $preventCache = true) 341 { 342 $this->go($url, $replace, $http_response_code, $preventCache); 343 exit; 344 } 345 346 347 /** 348 * Redirect to the given URI 349 * 350 * @param string $url or error code number. eg. 404 = Not Found. If left empty SITEURL will be used. 351 * @param boolean $replace - default TRUE 352 * @param integer|null $http_response_code - default NULL 353 * @param boolean $preventCache 354 * @return void 355 */ 356 public function go($url='', $replace = TRUE, $http_response_code = NULL, $preventCache = true) 357 { 358 $url = str_replace("&", "&", $url); // cleanup when using e_QUERY in $url; 359 360 if(empty($url)) 361 { 362 $url = SITEURL; 363 } 364 365 if($url == 'admin') 366 { 367 $url = SITEURLBASE. e_ADMIN_ABS; 368 } 369 370 371 372 if(defset('e_DEBUG') === 'redirect') 373 { 374 $error = debug_backtrace(); 375 376 $message = "URL: ".$url."\nFile: ".$error[1]['file']."\nLine: ".$error[1]['line']."\nClass: ".$error[1]['class']."\nFunction: ".$error[1]['function']."\n\n"; 377 e107::getLog()->addDebug($message, true); 378 echo "Debug active"; 379 print_a($message); 380 echo "Go to : <a href='".$url."'>".$url."</a>"; 381 e107::getLog()->toFile('redirect.log',"Redirect Log", true); 382 return; 383 } 384 385 if(session_id()) 386 { 387 e107::getSession()->end(); 388 } 389 if($preventCache) 390 { 391 header('Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0', true); 392 header('Expires: Sat, 26 Jul 1997 05:00:00 GMT', true); 393 } 394 // issue #3179 redirect with response code >= 400 doesn't work. Only response codes below 400. 395 if(null === $http_response_code || $http_response_code >= 400) 396 { 397 header('Location: '.$url, $replace); 398 } 399 else 400 { 401 header('Location: '.$url, $replace, $http_response_code); 402 } 403 404 // Safari endless loop fix. 405 header('Content-Length: 0'); 406 407 // write session if needed 408 //if(session_id()) session_write_close(); 409 410 exit(); 411 } 412} 413