<?php
$module["session"]["name"]="Sessionmanagement Module";
$module["session"]["ver"]="0.9.1";
/**
 * Project:   astat - simple site engine
 * File:      /inc/sessions.class.php
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * @link http://www.astat.org SVN: $URL: http://svn.astat.org/astat/trunk/inc/sessions.class.php $
 * @copyright 2010 becast.at
 * @author Bernhard Jaud <bernhard at becast dot at>
 * @package astat core
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: sessions.class.php 129 2010-02-21 22:04:51Z genuineparts $
*/
class session {
	
	var $sid = 0;
	var $uid = 0;
	var $ip = '';
	var $packip = '';
	var $userdata = array();
	var $useragent = '';

	function page_begin($page = "UNDEFINED", $needlogin = TRUE){
	 global $config, $db, $log, $core, $lang, $plugin, $functions;
	 $plugin->run_hook('page_begin_start',array('page'=>$page,'needlogin'=>$needlogin));
	 if($this->userdata['uid']==0 || !$this->userdata['uid']){
		 $this->ip = $functions->get_ip();
		 $this->packip = $functions->my_inet_pton($this->ip);
		 $this->useragent = $_SERVER["HTTP_USER_AGENT"];

		//Check if the User has a Cookie
    	if (isset($_COOKIE[$config["cookiename"] . "_sid"])){
		//Retireve Data from Cookie
			$sid = $_COOKIE[$config["cookiename"] . "_sid"];
			$sid = $db->escape(base64_decode($sid));
			$data = $db->fetch_array($db->query("SELECT sid,uid FROM `" . $config["prefix"] . "sessions` WHERE `sid`='".$sid."' AND `ip`=".$db->escape_binary($this->packip)));
		
			if($data['sid']){
				$this->sid=$data['sid'];
				$this->uid=$data['uid'];
			}else{
				$this->sid=0;
				$this->uid=0;
			}
		}

		//Something's rotten. Still no SID.
		if(!$this->sid){
			//This is some strange behavior, log it with low priority.
			if($config["logging"])
				$log->write("SID not set.",5,__LINE__,__FILE__);
				
			$this->sid = 0;
			$this->uid = 0;
		}

		// If there is a Cookie log the user in (if he isn't already)
	   	if (isset($_COOKIE[$config["cookiename"] . "_base"])){
			$cookiedata = $_COOKIE[$config["cookiename"] . "_base"];
			$cookiedata = explode("_",base64_decode($cookiedata),2);	
			$this->load_data($cookiedata[0],$cookiedata[1]);
		}

		if($this->userdata['active']==2){
			$additional_message = '';
			if($this->userdata['bio']!=""){
				$additional_message = '<br />'.$lang->_('REASON').' '.$this->userdata['bio'];
			}
			//$this->destroy_session($session->sid);
			
			$this->userdata['uid']=0;
			
			$this->setcookie($config['cookiename'] . '_base', 0, time()-3600,  $config['path'],$config['domain']);
			$core->message($lang->_('BANNED'),$lang->_('YOUHAVEBEENBANNED').$additional_message);
		}

		// Still no Userdata, its a Guest
		if(!isset($this->userdata['uid'])){
			if(!empty($this->sid)){
				$this->update_session($this->sid);
				$this->userdata['uid']=0;
		 	}else{
				$this->create_session();
				$this->userdata['uid']=0;
			}
		}
		
		$this->setcookie($config["cookiename"] . "_sid",base64_encode($this->sid),0,"/",$config['domain'],true);
		}
		$plugin->run_hook('page_begin_end',array('data'=>$this));


		if($needlogin != FALSE && $this->userdata["uid"]==0){
			header("LOCATION://" . $_SERVER["HTTP_HOST"] . $config['path'] . "/index.php?fail=needlogin");
		}
	}

	        //Fetch userdata
        function load_data($uid, $loginkey){
			global $db,$config, $log, $plugin, $lang;
		   
			$plugin->run_hook('load_data_start',array('loginkey'=>$loginkey,'uid'=>$uid, 'data'=>$this));
			$result = $db->query("SELECT * FROM `" . $config["prefix"] . "users` u LEFT JOIN `" . $config["prefix"] . "role` r ON r.id=u.role WHERE u.`uid`='" . intval($uid) . "' and u.`loginkey`='" . $db->escape($loginkey) . "' LIMIT 1");
			$this->userdata=$db->fetch_array($result);
			$result = $db->query("SELECT * FROM `" . $config["prefix"] . "roleset` rs LEFT JOIN `" . $config["prefix"] . "role_values` rv ON rv.id=rs.role_value_id WHERE rs.role_id='".$this->userdata["role"]."'");
		   
			while($row=$db->fetch_array($result)){
				$this->userdata[$row["name"]]=$row["value"];
			}
			if(!$this->userdata['uid']){
		   
				if($config["logging"])
						$log->write("No User found. UID: " .$uid,4,__LINE__,__FILE__);
					   
				 unset($this->userdata);
				 $this->uid=0;
				 return false;
			}
	 
			if($uid!=$this->userdata['uid'] || $loginkey!=$this->userdata['loginkey']){
		   
				if($config["logging"]){
					$log->write("HACK ATTEMPT. Cookie Spoof. UID: " .$uid,1,__LINE__,__FILE__);
				}  
				unset($this->userdata);
				$this->uid=0;
				return false;
			}
			if($this->userdata['uid']!=0){
				if($this->userdata['lastip'] != $this->packip && array_key_exists('lastip', $this->userdata)){
					$lastip_add = ", lastip=".$db->escape_binary($this->packip);
				}
				else
				{
					$lastip_add = '';
				}
		
				$time = time();
				if($time - $this->userdata['lastactive'] > 900){
					$db->query("UPDATE `" . $config["prefix"] . "users` SET `lastvisit`='" . $this->userdata['lastactive']  . "', `lastactive`='" . $time . "'".$lastip_add." WHERE `uid`='" . $uid . "'");
					//$mybb->user['lastvisit'] = $mybb->user['lastactive'];
				}
				else
				{
					$timespent = $time - $this->userdata['lastactive'];
					$db->query("UPDATE `" . $config["prefix"] . "users` SET `lastactive`='" . $time . "'".$lastip_add." WHERE `uid`='" . $uid . "'");
				}
			}
			if(!empty($this->sid)){
				$this->update_session($this->sid, $this->userdata['uid']);
			}else{
				$this->create_session($this->userdata['uid']);
			}
			$lang->setlang($this->userdata['lang']);
			$plugin->run_hook('load_data_end',array('data'=>$this));
        }
       
        function setcookie($name,$data,$validto=0,$path=NULL,$domain=NULL,$httponly=false,$https=true)
        {
                if($domain!=''){
                        // Fix the domain to accept domains with and without 'www.'.
                        if (strtolower( substr($domain, 0, 4) ) == 'www.' ){
                                $domain = substr($domain, 4);
                        }else{
                                $domain = $domain;
                        }
                        // Add the dot prefix to ensure compatibility with subdomains
                        if ( substr($domain, 0, 1) != '.' ){
                                $domain = '.'.$domain;
                        }
                }
				if((isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS'])) || $https){
					$https = true;
				}
				$arr_cookie_options = array (
					'expires' => $validto,
					'path' => $path,
					'domain' => $domain, // leading dot for compatibility or use subdomain
					'secure' => $https,     // or false
					'httponly' => $httponly,    // or false
					'samesite' => 'Strict' // None || Lax  || Strict
				);
				setcookie($name, $data, $arr_cookie_options);
        }

        function update_session($sid, $uid=''){
         global $db,$config, $plugin, $lang;
                $plugin->run_hook('update_session_start', array('sid'=>$sid,'uid'=>$uid, 'data'=>$this));
                if($uid){
					$sessiondata['uid'] = $uid;
					$db->query("UPDATE `" . $config["prefix"] . "users` SET `lastvisit`='".time()."' WHERE `uid`='".$uid."'");
                }else{
					$sessiondata['uid'] = 0;
					$lang->setlang($config['lang']);
                }

                $sid = $db->escape($sid);
                $db->query("UPDATE `" . $config["prefix"] . "sessions` SET `uid`='".$sessiondata['uid']."',`time`='".time()."',`ip`=".$db->escape_binary($this->packip).", `useragent`='".$db->escape($this->useragent)."' WHERE `sid`='".$sid."'");
				$timeout=time()-1800;
				$db->query("DELETE FROM `" . $config["prefix"] . "sessions` WHERE `time`<='".$timeout."'");
                $plugin->run_hook('update_session_end');
        }

        function create_session($uid=0){
                global $db,$config, $plugin, $lang, $functions;
                $plugin->run_hook('create_session_start', array('uid'=>$uid, 'data'=>$this));
                if($uid > 0){
                        $db->query("DELETE FROM `" . $config["prefix"] . "sessions` WHERE `uid`='".intval($uid)."'");
                        $sessiondata['uid'] = $uid;
                }else{
                        $db->query("DELETE FROM `" . $config["prefix"] . "sessions` WHERE `ip`=".$db->escape_binary($this->packip));
                        $sessiondata['uid'] = 0;
						$lang->setlang($config['lang']);
                }
				
                $sessiondata['sid'] = md5($functions->random_str(50));
                $db->query("INSERT INTO `" . $config["prefix"] . "sessions` (`sid`,`uid`,`time`,`useragent`,`ip`) VALUES ('".$sessiondata['sid']."','".$sessiondata['uid']."','".time()."','".$db->escape($this->useragent)."',".$db->escape_binary($this->packip).")");
                $db->query("UPDATE `" . $config["prefix"] . "users` SET `lastvisit`='".time()."' WHERE `uid`='".$uid."'");
                $this->sid = $sessiondata['sid'];
                $this->uid = $sessiondata['uid'];
                $plugin->run_hook('create_session_end');
        }

        function destroy_session($sid)
        {
         global $db,$config, $plugin;
                $plugin->run_hook('destroy_session_start', array('data'=>$this));
                if($sid !=""){
                        $db->query("DELETE FROM `" . $config["prefix"] . "sessions` WHERE `sid`='".$db->escape($sid)."'");
                }else{
                        $db->query("DELETE FROM `" . $config["prefix"] . "sessions` WHERE `ip`=".$db->escape_binary($this->packip));
                }
                unset($this->userdata);
                $this->setcookie($config["cookiename"] . '_sid','',-3600,'/',true);
                $this->sid = 0;
                $this->uid = 0;
                $plugin->run_hook('destroy_session_end');
        }
       
        function check_login($username='',$password='',$openid='')
        {
         global $db,$config, $plugin, $lang, $core;
                $plugin->run_hook('check_login_start', array('data'=>$this));
                if($username!='' && $password!=''){
                        $username = $db->escape($username);
						$result = $db->query("SELECT `uid`,`salt` FROM `" . $config['prefix'] . "users` WHERE `username` LIKE '".$username."' AND `active`>'0' LIMIT 1");
                        if ($db->num_rows ($result) > 0){
                                // There is a user
                                $data=$db->fetch_array($result);
                        }else{
                                return false;
                        }
                        $pass = hash('sha256',$db->escape($data['salt'].$password));
                        $result = $db->query("SELECT `uid`,`loginkey`,`active`,`bio` FROM `" . $config['prefix'] . "users` WHERE `username` LIKE '".$username."' AND `password`='".$pass."' AND `active`>'0' LIMIT 1");
                        if ($db->num_rows ($result) > 0){
                                // There is a user
                                $data=$db->fetch_array($result);
                        }else{
                                return false;
                        }
						if($data['active']==2){
							$additional_message = '';
							if($data['bio']!=""){
								$additional_message = '<br />'.$lang->_('REASON').' '.$data['bio'];
							}
							unset($data);
					
							$this->setcookie($config['cookiename'] . '_base', 0, time()-3600,  $config['path'],$config['domain']);
							$core->message($lang->_('BANNED'),$lang->_('YOUHAVEBEENBANNED').$additional_message);
							return 'BANNED';
						}
						$uid = $data['uid'];
						$key = $data['loginkey'];
						$this->login($uid,$key);
						return $uid;
                }elseif($openid!=''){
                        $identity=$db->escape($openid);
                        $result = $db->query("SELECT `uid`,`loginkey` FROM `" . $config['prefix'] . "users` WHERE `openid_identity` = '".$identity."' AND `active`='1' LIMIT 1");
                        if ($db->num_rows ($result) > 0){
                           // There is a user
							$data=$db->fetch_array($result);
                        }else{
							return false;
                        }
                        $uid = $data['uid'];
                        $key = $data['loginkey'];
                        $this->login($uid,$key);
                        return $uid;
                }else{
                        return false;
                }      
        }
       
        function login($uid,$key)
        {
			global $db,$config, $plugin;
			$plugin->run_hook('logon_start', array('data'=>$this));
			$cookiedata['uid'] = $uid;
			$cookiedata['loginkey'] = $key;
			$cookiedata = base64_encode($cookiedata['uid'] .'_'. $cookiedata['loginkey']);
			if(isset($_POST['remember']) && $_POST['remember']){
					$this->setcookie($config['cookiename'] . '_base', $cookiedata, time() + 60 * 60 * 24 * 365, $config['path'],$config['domain'],true);
			}else{
					$this->setcookie($config['cookiename'] . '_base', $cookiedata, 0, $config['path'],$config['domain'],true);
			}
			$this->create_session($uid);
			$plugin->run_hook('logon_end');
        }
        
	function get_users_with_right($right, $value)
	{
		global $db,$config;
		$result = $db->query("SELECT u.* FROM `" . $config["prefix"] . "users` u LEFT JOIN `" . $config["prefix"] . "role` r ON u.`role`=r.`id` LEFT JOIN `" . $config["prefix"] . "roleset` rs ON rs.`role_id`=r.`id` LEFT JOIN `" . $config["prefix"] . "role_values` rv ON rv.`id`=rs.`role_value_id` WHERE rv.`name`='".$db->escape($right)."' AND rs.`value`='".$db->escape($value)."'");
		while($row=$db->fetch_array($result)){
			$return[]=$row;
		}
		return $return;
	}

	function generate_Key($length=8){
	 
	 $dummy = array_merge(range('0', '9'), range('a', 'z'), range('A', 'Z'));

	 mt_srand((double)microtime()*1000000);

		for ($i = 1; $i <= (count($dummy)*2); $i++){
		 $swap = mt_rand(0,count($dummy)-1);
		 $tmp = $dummy[$swap];
		 $dummy[$swap] = $dummy[0];
		 $dummy[0] = $tmp;
		}

	 return substr(implode('',$dummy),0,$length);
	 
	}

	function sanitize_username($username){
		global $config;
		$username = trim($username);
		$username = preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $username);
		$username = str_replace(array(chr(160), chr(173), chr(0xCA), chr(8238), chr(8237), chr(8203),"]","[","/","\\"), array("", "-", "", "", "", "","","","",""), $username);
		// Remove multiple spaces from the username
		$username = preg_replace("#\s{2,}#", "", $username);
		return $username;
	}

	function verify_username($username){
		global $config;

		// Check if the username is not empty.
		if($username == '')
		{
			return "Username empty.";
		}

		// Check if the username belongs to the list of banned usernames.
		$banned=explode("\n",$config['banned_usernames']);
		if(is_array($banned)){
			foreach($banned as $banned_username){
				$banned_username = str_replace('*', '(.*)', trim($banned_username));
				if(preg_match("#\b{$banned_username}\b#i", $username)){
					return "Forbidden Username:".$banned_username;
				}
			}
		}
		// Check for certain characters in username (<, >, &, commas and slashes)
		if(strpos($username, ".") !== false || strpos($username, ":") !== false || strpos($username, " ") !== false || strpos($username, "<") !== false || strpos($username, ">") !== false || strpos($username, "&") !== false || strpos($username, ")") !== false || strpos($username, "(") !== false || strpos($username, "\\") !== false || strpos($username, ";") !== false || strpos($username, ",") !== false || strpos($username, "~") !== false)
		{
			return "Forbidden Chars in Username";
		}

		// Check if the username is of the correct length.
		if(($config['maxnamelength'] != 0 && strlen($username) > $config['maxnamelength']) || ($config['minnamelength'] != 0 && strlen($username) < $config['minnamelength']))
		{
			return sprintf('The username must be %s Chars minimum and can be %s Chars long at max.',$config['minnamelength'],$config['maxnamelength']);
		}

		return true;
	}
}
?>
