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("&amp;", "&", $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