396 lines
16 KiB
PHP
396 lines
16 KiB
PHP
<?php
|
|
$module["session"]["name"]="Sessionmanagement Module";
|
|
$module["session"]["ver"]="0.9.2";
|
|
/**
|
|
* Project: BeCast WebEngine - 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.becast.at
|
|
* @copyright 2009-2025 becast.at
|
|
* @author Bernhard Jaud <bernhard at becast dot at>
|
|
* @package BcWe core
|
|
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
|
|
* @version $Id$
|
|
*/
|
|
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;
|
|
}
|
|
}
|
|
?>
|