<?php
// namespace core;
// use helpers\session as Session;
// use core\cookie as Cookie;
// use helpers\database as Database

/**
* Class Auth - Authentication
* Simply checks if user is logged in. Several controllers use Auth::handleLogin() to check if user if user is logged in, useful to show controllers/methods only to logged-in users.
* Like part of registration may be used as dependency injection for constructing
*/
class Auth{

	/**
	* This check should be placed on every page that shouldn't be accessed no matter what!
	*/
	public static function handleLogin(){
		/* Collect this information on every request, not sending errors upon SERVER */
		$adressip = "";//@$_SERVER['REMOTE_ADDR'];//
		/* Comment warning outs because of server configuration */
		$browserip = @$_SERVER['HTTP_X_FORWARDED_FOR'];//HTTP_X_FORWARDED_FOR 
		$agent = @$_SERVER['HTTP_USER_AGENT'];//
		/* initialize the session, may be omitted due to routing configurations ??? */
		Session::init();
		$user_ident = hash("sha1", USER_TOKEN.$adressip.$agent.$browserip);
		// error_log('current geka : ra - '.$_SERVER['REMOTE_ADDR'].' htp-for'.$_SERVER['HTTP_X_FORWARDED_FOR'].' user-agent '.$_SERVER['HTTP_USER_AGENT'].' user ident : '.$user_ident);
		/* if user is still not logged in, then destroy session, handle user as "not logged in" and redirect user to main page for login */
		if (!Session::get("user_logged_in") OR Session::get('user_ident') != $user_ident) {
			Session::destroy();
			header('Location: '.DIR.'');
			/* to prevent fetching views via cURL (which "ignores" the header-redirect above) we leave the application the hard way, via exit() */
			exit();
		}
	}

	/**
	* Checks if user is already login under session and if not check if remember me set in cookie
	* @return bool true for logged in user else false
	*/
	public static function handleCookedLogin(){
		/* Collect this information on every request */
		$adressip = "";//$_SERVER['REMOTE_ADDR'];
		$browserip = @$_SERVER['HTTP_X_FORWARDED_FOR'];
		$agent = @$_SERVER['HTTP_USER_AGENT'];
		/* initialize the session, may be omitted due to routing configurations ??? */
		Session::init();
		/* Do this each time the user successfully logs in. */
		/* And do this every time the client makes a request to the server, after authenticating */
		$user_ident = hash("sha1", USER_TOKEN.$adressip.$agent.$browserip);
		/* Check if already checked for triplet cookie combination, if not start checking and set appropriate flags */
		// error_log(print_r(Session::display(),true));
		// error_log('Session id : '.Session::id());
		// error_log('current geka : ra - '.$_SERVER['REMOTE_ADDR'].' htp-for'.$_SERVER['HTTP_X_FORWARDED_FOR'].' user-agent '.$_SERVER['HTTP_USER_AGENT'].' user ident : '.$user_ident);
		/* This is the first check for each page that should be use modular login */
		if (!Session::get("user_logged_in_cooked")){
			/* Set in session that the cookie is checked, to prevent unnecessary server requests */
			Session::set("user_logged_in_cooked", true);
			/* get cookie triplet */
			/* rmbm[xcst]=>token is the actual browser combination + simple defined salt to change time to time */
			/* rmbm[xcsi]=>id user's hashed number + four first digits for limit of 10,000 rows in SQL, its same for individual user */
			/* may be from first creation time + user id + salt user */
			/* rmbm[xcsc]=>counter from first remember me and be first deleted from database for more newer remember me */
			$cookieTriplet = Cookie::get_multi_cookie('rmbm');
			/* check if user has and existing cookie triplet */
			if(count($cookieTriplet) != 3){
				return false;
			}
			/* connect to DB and get all database for user xcsi => i for id */
			$_temp_db = new Database();
			$query = $_temp_db->selectOne("SELECT * 
											FROM ".PREFIX."usr 
											WHERE user_cookie_id = :user_cookie_id",
											array(':user_cookie_id' => $cookieTriplet['xcsi']));
			/* fake user hijack attempt */
			if(!$query)
				return false;
			/* get users actual and real browser + current salt */
			$current_xcst = hash('sha1',SALT_TOKEN.$_SERVER['HTTP_USER_AGENT']);
			/* get all user combinations for tokens and their creation time */
			$runner = explode(',',$query['user_remember']);
			/* updated triplet for DB to clean from string the COOKIE_EXPIRES */
			$new_user_remembers = '';
			/* current time for deletion of expired cookies */
			$cookie_time = time() + COOKIE_EXPIRES;
			/* run on array of xcst and xcsc */
			foreach($runner as $combinations){
				/* get at comb[0]->xcst and at comb[1]->xcsc */
				$comb = explode('|',$combinations);
				/*  check if cookie is still relevant if not delete it we don't need to hold expired cookies */
				/*  will not handle users browser cookies because they should dispatched automatically probably it's brute force attack over rainbow tables... just ignore it! */
				if($comb[0] >= time()){
					/* bingo for time (priority on time because the token run combination more difficult) */
					if($comb[0] == $cookieTriplet['xcsc'] AND $comb[1] == $current_xcst){
						/* get the real user info from users table */
						$query_b = $_temp_db->selectOne("SELECT user_email,
														user_gender,
														user_account_type,
														user_provider_type
													FROM ".PREFIX."usr 
													WHERE user_id = :user_id",
													array(':user_id' => $query['user_id']));
						/* update this basic information for session */
						Session::set('user_id', $query['user_id']);
						// Session::set('user_name', $query_b['user_name']);
						Session::set('user_gender', $query_b['user_gender']);
						Session::set('user_email', $query_b['user_email']);
						Session::set('user_account_type', $query_b['user_account_type']);
						Session::set('user_provider_type', 'DEFAULT');
						/* set user login to true to prevent Auth resubmitting */
						Session::set("user_logged_in",true);
						/* set user identification on current session : this is important for every cycle check */
						Session::set("user_ident",$user_ident);
						/* extend another two weeks for cookie (not checking for successful cookie update) */
						Cookie::set_cookie('rmbm[xcsc]',$cookie_time);
						/* update extended time in DB */
						$new_user_remembers .= $cookie_time.'|'.$comb[1].',';
						$_temp_db->update(PREFIX."usr"
											,array('user_last_login_timestamp' => time())
											,array('user_id' => $query['user_id']));
					/* This one is also cleans from an duplicated xcst in DB */
					}else{
						/* check if time is smuggled -> break */
						if($comb[1] == $current_xcst){
							return false;
						/* otherwise OK, for new user remember reconstruct */
						}else{
							$new_user_remembers .= $comb[0].'|'.$comb[1].',';}
					}
				}
			}
			/* check for string allowed size before pushing to DB for max of 8 remember me so chop the string */
			/* Browsers allowed | xcsc xcst * 8 and , * 7 = total of 463 :) */
			$final_remembers = strlen($new_user_remembers);
			/* chop ',' at the end of string */
			if($final_remembers >= 10)
				substr($new_user_remembers,0,$final_remembers-1);
			/* COMMENTED because we can update the string or remove part of it no need for more checks */
			// if(strlen($new_user_remembers) >= 464)
			// substr($new_user_remembers,0,463);
			/* update DB with new remember me string, we not interesting in success or failure??? */
			$_temp_db->update(PREFIX."usr",
								array('user_remember' => $new_user_remembers),
								array('user_cookie_id' => $cookieTriplet['xcsi']));
		}
		/* simple check if user is login in regular or cookie way */
		if($user_ident != Session::get('user_ident')){
			return false;
		}
		return true;
	}
}