<?php
// +---------------------------------------------------------------------------------------+
// | TenderSystem                                                                          |
// +---------------------------------------------------------------------------------------+
// | The contents of this file are subject to the TenderSystem Public License Version 1.1  |
// | ("License"); you may not use this file except in compliance with the License. You may |
// | obtain a copy of the License at http://www.tendersystem.com/tpl/                      |
// |                                                                                       |
// | Software distributed under the License is distributed on an "AS IS" basis, WITHOUT    |
// | WARRANTY OF ANY KIND, either express or implied. See the License for the specific     |
// | language governing rights and limitations under the License.                          |
// |                                                                                       |
// | All copies of the Covered Code must include the "Powered by TenderSystem" logo and    |
// | ValueCard copyright notice on every user interface screen and in every outgoing       |
// | email in the same form as they appear in the distribution.                            |
// |                                                                                       |
// | The Original Code is: TenderSystem                                                    |
// | The Initial Developer of the Original Code is ValueCard (Pty) Limited.                |
// | Portions created by ValueCard are Copyright (C) 2002 ValueCard (Pty) Limited.         |
// | All Rights Reserved.                                                                  |
// | Contributor(s): __________________.                                                   |
// +---------------------------------------------------------------------------------------+

/**
* Session class
* @package TenderSystem
* @subpackage session
* @copyright Copyright &copy; 2002, ValueCard (Pty) Ltd
* @license http://www.tendersystem.com/tpl/ TenderSystem Public License
* @version 
*/

// Security - ensure that file never called directly
// not required if global variables are off or API is hosted on a non-public server
if (eregi(basename(__FILE__),$_SERVER['PHP_SELF'])) {
    die ("You can't access this file directly...");
}

Class session {
	// user paramaters
	var $user;
	// class paramaters
	var $error;
	
	function session() {
		// allow php5 to work
		$this->error = array();	
	}
	
	/**
	 * Logins in the user
	 * 
	 * @param array user user login information
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param mixed array of tender items or FALSE on error  
	 */
	function login($user,$cfg,$conn) {
		// set the paramaters
		$this->user = $user;
		// if no session present return error message
		if (!$this->user['username']) {
			// 1062 - Missing username
			$this->error[] = "1062";
		}
		if (!$this->user['password']) {
			// 1063 - Missing password
			$this->error[] = "1063";
		}
		if (!$this->user['ip']) {
			// e6 - no incoming ip address present
			$this->error[] = "e6";
		}
		if (!$this->user['server_ip']) {
			// if no server ip present incoming set to remote address
			$this->user['server_ip'] = $_SERVER['REMOTE_ADDR'];
		}
		// error response
		if (!empty($this->error)) {
			// return false
			return FALSE;
		}
		$new_user = new user;
		// get user id
		$userid = $new_user->get_id_by_username($this->user['username'],$cfg,$conn);
		if(!empty($new_user->error)) {
			$this->error = array_merge($this->error,$new_user->error);
			// response
			return FALSE;
		} elseif (!$userid) {
			// instantiate the error class and log
			require($cfg['file']."modules/session/language/".$cfg['language']."/session_error.php");
			$new_error = new error;
			$error_text = $lang['invalidattempt']." ".$this->user['username']." (".$lang['usingpassword'].")";
			$new_error->log("Login","serious",$error_text,$cfg);
			// e7 - Invalid login attempt. Please try again...
			$this->error[] = "e7";
			// response
			return FALSE;
       	}
       	$new_password = new password;
       	// check the password
       	$result = $new_password->validate_hashed_password($userid,$this->user['password'],$cfg,$conn);
       	if(!empty($new_password->error)) {
			$this->error = array_merge($this->error,$new_password->error);
			// error in session class
			$this->error[] = "205";
		} elseif(!$result) {
			// instantiate the error class and log
			require($cfg['file']."modules/session/language/".$cfg['language']."/session_error.php");
			$new_error = new error;
			$error_text = $lang['invalidattempt']." ".$this->user['username']." (".$lang['usingpassword'].")";
			$new_error->log("Login","serious",$error_text,$cfg);
			// e8 - Invalid login attempt. Please try again...
			$this->error[] = "e8";
			// response
			return FALSE;
       	}
       	// get session info
       	$user_info = $new_user->get_info($userid,$cfg,$conn);
       	if(is_array($user_info)) {
       		$this->user = array_merge($this->user,$user_info);
       	} elseif(!empty($new_user->error)) {
			$this->error = array_merge($this->error,$new_user->error);
			// response
			return FALSE;
		}
		// usuall md5
		$hash = $cfg['session']['hash'];	
		// create the session string
		$this->user['session'] = $hash(uniqid(rand(),$cfg['session']['more']['entropy']));
        // create 6 character authentication string for additional security
		$auth_string = $hash(uniqid(rand()));
		$auth_string = strtolower($auth_string);
		// remove any o and 0 as it can be confusing
		$replace_array = array("o","0");
		$auth_string = str_replace($replace_array, "", $auth_string);
		// make the auth string 6 characters long starting at postion 2
		$auth_string = substr($auth_string, 2, 6);
		// determine expiry period
		if ($this->user['classification'] == "1") {
			// supplier
			$expiry_period = $cfg['login']['agent'];
		} elseif ($this->user['classification'] == "2") {
			// user
			$expiry_period = $cfg['login']['subscriber'];
		} elseif ($this->user['classification'] == "3") {
			// administrator
			$expiry_period = min($cfg['login']['admin'],60);
		} else {
			// e9 - Unknown Classification for User
			$this->error[] = "e9";
			// response
			return FALSE;
		}
		// set exiry time
		$time_now = ts_time($cfg);
		$time_expire = $time_now + $expiry_period;
		// set table
		$table_name = "~session";
		// create insert array
		$insert = array (
			'id'				=>	$this->user['session'],
			'user_id'			=>	$this->user['id'],
			'ip_address'		=>	$this->user['ip'],
			'ip_server'			=>	$this->user['server_ip'],
			'ip_api'			=>	$_SERVER['SERVER_ADDR'],
			'authentication'	=>	$auth_string,
			'browser'			=>	$this->user['browser'],
			'status'			=>	"1"
		);
		$new_database = new database;
		$new_database->setTime("created",$insert,"",$cfg);
		$new_database->setTime("expire",$insert,$time_expire,$cfg);
		$new_database->parse_sql($table_name,$cfg);
		 // execute the sql string
        $conn->AutoExecute($table_name,$insert,"INSERT");
		// error handling
		if ($conn->ErrorMsg()) {
			// instantiate the error class and log
			$new_error = new error;
			$error_text = "SQL error in file ".__file__." on line ".__line__." Error:".$conn->ErrorMsg();
			$new_error->log("SQL","critical",$error_text,$cfg);
			// 1064 - Error occurred while inserting into Database
			$this->error[] = "1064";
			// response
			return FALSE;
        }
		// response
		return TRUE;	
	}
	
	/**
	 * Validates a session
	 * 
	 * @param array params search information
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param mixed array of tender items or FALSE on error  
	 */
	function validate($user,$cfg,$conn) {
		// set the paramaters
		$this->user = $user;
		// if no session present return error message
		if (!$this->user['session']) {
			// e10 - No session present
			$this->error[] = "e10";
		}
		if (!$this->user['ip']) {
			// e6 - no incoming ip address present
			$this->error[] = "e6";
		}
		if (!empty($this->error)) {
			// response
			return FALSE;
		}
		// determine if the server ip is present
		if (!$this->user['server_ip']) {
			// no server ip present - set to remote address
			$this->user['server_ip'] = $_SERVER['REMOTE_ADDR'];
		}
		// determine if valid session
		$sqlstr = "SELECT ~session.id, ~session.user_id, ~session.ip_address AS ip, ";
		$sqlstr.= "~session.ip_address, ~session.expire_date, ~session.expire_time, ";
		$sqlstr.= "~session.authentication, ~session.browser, ~session.status, ";
		$sqlstr.= "~users.id AS usersid, ~users.organisation, ~users.branch ";
		$sqlstr.= "FROM ~session, ~users, ~organisation, ~organisation_branch ";
		$sqlstr.= "WHERE ~session.id = '".$this->user['session']."' ";
		$sqlstr.= "AND ~session.status = '1' ";
		$sqlstr.= "AND ~session.user_id = ~users.id ";
		if ($cfg['security']['ip_track']) {
			$sqlstr.= "AND ~session.ip_server = '".$this->user['server_ip']."' ";
		}
		$sqlstr.= "AND ~users.status > '0' ";
		$sqlstr.= "AND ~users.organisation = ~organisation.id ";
		$sqlstr.= "AND ~organisation.status = '1' ";
		$sqlstr.= "AND ~users.branch = ~organisation_branch.id ";
		$sqlstr.= "AND ~organisation_branch.status = '1' ";
		$new_database = new database;
		$new_database->parse_sql($sqlstr,$cfg);
		// execute the query
 		//$recordSet = $conn->Execute($sqlstr);
 		$all = $conn->GetAll($sqlstr);
 		if ($conn->ErrorMsg()) {
			// instantiate the error class and log
			$new_error = new error;
			$error_text = "SQL error in file ".__file__." on line ".__line__." Error:".$conn->ErrorMsg();
			$new_error->log("SQL","critical",$error_text,$cfg);
			// 1065 - An error occurred while querying the Database
			$this->error[] = "1065";
			// response
			return FALSE;
       	}  elseif (count($all) == 0) {
       		require($cfg['file']."modules/session/language/".$cfg['language']."/session_error.php");
       		// instantiate the error class and log
			$new_error = new error;
			$error_text = $lang['sessionfailed']." ".$this->user['session']." ".$lang['fromip']." ".$this->user['ip'];
			$new_error->log("Session","mild",$error_text,$cfg);
			// e11 - session has expired. please log in again...
			$this->error[] = "e11";
			// response
			return FALSE;
       	} elseif (count($all) > 1) {
       		require($cfg['file']."modules/session/language/".$cfg['language']."/session_error.php");
       		// instantiate the error class and log
			$new_error = new error;
			$error_text = $lang['duplicatesession']." ".$this->user['session'];
			$new_error->log("Session","mild",$error_text,$cfg);
			// duplicate sessions - improbable but might occur
			// e11 - session has expired. please log in again...
			$this->error[] = "e11";
			// response
			return FALSE;
		}
		// determine if ip tracking active
		if ($cfg['security']['ip_track']) {
			// determine if correct incoming ip address
			if ($all[0]['ip'] != $this->user['ip']) {
				require($cfg['file']."modules/session/language/".$cfg['language']."/session_error.php");
	       		// instantiate the error class and log
				$new_error = new error;
				$error_text = $lang['sessiontheft']." ".$this->user['session']." ".$lang['fromip']." ".$this->user['ip']." ".$lang['correctip']." ".$all[0]['ip'];
				// instantiate the error class and log
				$new_error->log("Session","mild",$error_text,$cfg);
				// e12 - Invalid incoming IP address. Please log in again..
				$this->error[] = "e12";
				// response
				return FALSE;
			}
		}
		$row = $all[0];
		// determine if session has expired - NOTE: no error logging
		$expire_date = $row['expire_date'];
		$expire_date = str_replace("-","",$expire_date);
		$expire_time = $row['expire_time'];
		$expire_time = str_replace(":","",$expire_time);
		$time_now = ts_time($cfg);
		$date = date("Ymd",$time_now);
		$time = date("His",$time_now);
		if ($expire_date < $date || ($expire_date == $date && $expire_time < $time)) {
			// e11 - session has expired. please log in again...
			$this->error[] = "e11";
			// response
			return FALSE;
		}
		// set paramaters
		$new_user = new user;
		// get session info
		$this->user['browser'] = $row['browser'];
       	$userinfo = $new_user->get_info($row['usersid'],$cfg,$conn);
		if(!empty($new_user->error)) {
			$this->error = array_merge($this->error,$new_user->error);
			// response
			return FALSE;
		}
		// set user info
		$this->user['id'] = $userinfo['id'];
		$this->user['name'] = $userinfo['name'];
		$this->user['surname'] = $userinfo['surname'];
		$this->user['organisation'] = $userinfo['organisation'];
		$this->user['branch'] = $userinfo['branch'];
		$this->user['preference'] = $userinfo['preference'];
		$this->user['classification'] = $userinfo['classification'];
		$this->user['language'] = $userinfo['language'];
		$this->user['theme'] = $userinfo['theme'];
		$this->user['administrator'] = $userinfo['administrator'];
		$this->user['email'] = $userinfo['email'];
		$this->user['phone_mobile'] = $userinfo['phone_mobile'];
		$this->user['phone_prefix'] = $userinfo['phone_prefix'];
		$this->user['phone_fax'] = $userinfo['phone_fax'];
		$this->user['phone_work'] = $userinfo['phone_work'];
		$this->user['status'] = $userinfo['status'];
		$this->user['username'] = $userinfo['username'];
		$this->user['permission'] = $userinfo['permission'];
		// determine expiry period
		if ($this->user['classification'] == "1") {
			// supplier
			$expiry_period = $cfg['login']['agent'];
		} elseif ($this->user['classification'] == "2") {
			// user
			$expiry_period = $cfg['login']['subscriber'];
		} elseif ($this->user['classification'] == "3") {
			// administrator
			$expiry_period = $cfg['login']['admin'];
		} else {
			// e9 - Unknown Classification for User
			$this->error[] = "e9";
			// response
			return FALSE;
		}
		// set the table name
		$table_name = "~session";
		// set new exiry time
		$time_expire = ts_time($cfg) + $expiry_period;
		// set update string
		$update = array ();
		$new_database->setTime("expire",$update,$time_expire,$cfg);
		// set the where clause
		$where = "id = '".$this->user['session']."' ";
		$where.= "AND user_id = '".$this->user['id']."' ";
		$new_database = new database;
		$new_database->parse_sql($table_name,$cfg);
		// execute the query
 		$conn->AutoExecute($table_name,$update,"UPDATE",$where);
		// error handling
       	if ($conn->ErrorMsg()) {
			// instantiate the error class and log
			$new_error = new error;
			$error_text = "SQL error in file ".__file__." on line ".__line__." Error:".$conn->ErrorMsg();
			$new_error->log("SQL","critical",$error_text,$cfg);
			// 1066 - Error occurred while updating the Database
			$this->error[] = "1066";
			// response
			return FALSE;
       	}
		// response - no error handling on purpose
		return $this->user;
	}
	
	/**
	 * log user out
	 * 
	 * @param array user user logout information
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param mixed array of tender items or FALSE on error  
	 */
	function logout($user,$cfg,$conn) {
		// set the paramaters
		$this->user = $user;
		if (!$this->user['session']) {
			// e10 - No session present
			$this->error[] = "e10";
		}
		if (!$this->user['ip']) {
			// e6 - no incoming ip address present
			$this->error[] = "e6";
		}
		if (!empty($this->error)) {
			// response
			return FALSE;
		}
		$timestamp = ts_time($cfg);
		// check if already expired
		$sqlstr = "SELECT * ";
		$sqlstr.= "FROM ~session ";
		$sqlstr.= "WHERE ~session.id = '".$this->user['session']."' ";
		$sqlstr.= "AND (~session.expire_date > '".date("Y-m-d",$timestamp)."' ";
		$sqlstr.= "OR (~session.expire_date = '".date("Y-m-d",$timestamp)."' ";
		$sqlstr.= "AND ~session.expire_time > '".date("H:i:s",$timestamp)."')) ";
		$sqlstr.= "AND ~session.status = '1' ";
		$new_database = new database;
		$new_database->parse_sql($sqlstr,$cfg);
		// execute the query
 		$all = $conn->GetAll($sqlstr,"",TRUE);
		if($conn->ErrorMsg()) {
			// instantiate the error class and log
			$new_error = new error;
			$error_text = "SQL error in file ".__file__." on line ".__line__." Error:".$conn->ErrorMsg()." SQL:".$sqlstr;
			$new_error->log("SQL","critical",$error_text,$cfg);
			// error occurred while querying into database 
			$this->error[] = "1065";
			// response
			return FALSE;
		} elseif (!$all) {
			// e13 - Session already expired
			$this->error[] = "e13";
			// response
			return FALSE;
       	}
		// set the table name
		$table_name = "~session";
		// set update string
		$update = array (
			// update this 
			'status'	=> "0"
		);
		$new_database = new database;
		$new_database->setTime("expire",$update,"",$cfg);
		$new_database->parse_sql($table_name,$cfg);
		// set the wehere clause
		$where.= " id = '".$this->user['session']."' ";
		// execute the sql string
		$conn->AutoExecute($table_name,$update,"UPDATE",$where);
		// error handling
       	if ($conn->ErrorMsg()) {
			// instantiate the error class and log
			$new_error = new error;
			$error_text = "SQL error in file ".__file__." on line ".__line__." Error:".$conn->ErrorMsg();
			$new_error->log("SQL","critical",$error_text,$cfg);
			// set the response error
			$this->error[] = "1066";
			// response
			return FALSE;
       	} 
		// response - no error handling on purpose
		return TRUE;
	}
	
	/**
	 * session logs
	 * 
	 * @param array params search information
	 * @param mixed cfg The Config settings of tendersystem
	 * @param [ADOConnection] conn The connection to the database
	 *
	 * @param mixed array of tender items or FALSE on error  
	 */
	function get_list_session($page,$cfg,$conn) {
		if(!$page) {
			$page = "0";	
		}
		$sqlstr = "SELECT ~session.id, ~session.created_date, ~session.created_time,";
		$sqlstr.= "~session.browser, ~session.ip_address, ~session.status, ";
		$sqlstr.= "~session.expire_time AS expiretime, ~session.expire_date AS expiredate,";
		$sqlstr.= "~session.ip_server, ~session.ip_api, ";
		$sqlstr.= "~users.classification, ~users.permission, ~users.id as usersid  ";
		$sqlstr.= "FROM ~session, ~users ";
		$sqlstr.= "WHERE ~session.user_id = ~users.id ";
		$sqlstr.= "ORDER BY ~session.created_date DESC, ~session.created_time DESC, ~session.id DESC ";
		$new_database = new database;
		$new_database->parse_sql($sqlstr,$cfg);
		$result = $conn->SelectLimit($sqlstr,$cfg['display']['login'],$cfg['display']['login']*$page);
		if($result) {
			$all = $result->GetRows();
		}
		if(!$result || $conn->ErrorMsg()) {
			// instantiate the error class and log
			$new_error = new error;
			$error_text = "SQL error in file ".__file__." on line ".__line__." Error:".$conn->ErrorMsg()." sql:".$sqlstr;
			$new_error->log("SQL","critical",$error_text,$cfg);
			// error occurred while querying into database 
			$this->error[] = "1065";
			// response
			return FALSE;
		}
		// put time in proper format
		$new_database->convertTime($all,$cfg);
		// get user info
		$new_users = new user;
		$timestamp = ts_time($cfg);
		foreach($all as $key => $value) {
			$users_info = $new_users->get_info($value['usersid'],$cfg,$conn);
			$value['name'] = $users_info['name'];
			$value['surname'] = $users_info['surname'];
			$expire = str_replace("-","",$value['expiredate']).str_replace(":","",$value['expiretime']);
			list($year,$month,$day,$hour,$minute,$second) = sscanf(str_replace(" ","",$expire),'%4s%2s%2s%2s%2s%2s');
			$expirestamp =  mktime($hour,$minute,$second,$month,$day,$year);
			// check if expired
			if($timestamp > $expirestamp) {
				$value['expired'] = "1";
				$value['idle'] = "--";
			} else {
				$value['expired'] = "0";
				if($value['classification'] == "3") {
					$value['idle'] = $cfg['login']['admin'] - $expirestamp + $timestamp;
				} elseif($value['classification'] == "2") {
					$value['idle'] = $cfg['login']['agent'] - $expirestamp + $timestamp;
				} else {
					$value['idle'] = $cfg['login']['subscriber'] - $expirestamp + $timestamp;
				}
				if($value['idle'] < 0) {
					$value['idle'] = "--";
				}
				
			}
			// check create time
			if($value['created_date'] == date($cfg['date']['format'],$timestamp)) {
				$value['created_on'] = $value['created_time'];
			} else {
				$value['created_on'] = $value['created_date']." " .$value['created_time'];
			}
			// checks the browser type
			$browser = strtolower($value['browser']);
			// browser types
			$browser_array = array(
				'msie' 		=> "Internet Explorer",
				'firefox' 	=> "Firefox",
				'netscape'	=> "Netscape",
				'opera'		=> "Opera",
				'konqueror'	=> "Konqueror",
				'epiphany'	=> "Epiphany",
				'galeon'	=> "Galeon",
				// This must be last
				'mozilla'	=> "Mozilla"
			);
			// assume the browser type in unknown
			$value['browser'] = "--";
			// determine browser type
			foreach($browser_array as $key1 => $value1) {
				$start_position = strpos($browser,$key1);
				if($start_position !== FALSE) {
					$version = substr($browser, $start_position + strlen($key1),6);
					$value['browser'] = $value1." ".preg_replace('/[^0-9,.]/','',$version);
					break;
				}
			}
			$all[$key] = $value;
		}
		return $all;
	}
}
?>