<?php
###############################################################################
# GenericIDP.php
#
# @author Anil Kumar <akumar@codepunch.com>
# @link   https://codepunch.com
#
############################################################################### 

namespace 	CodePunch\Config\SAML;

use 		CodePunch\Base\Util as UTIL;
use			CodePunch\Base\Text as TEXT;
use			CodePunch\DB\Audit as AUDIT;
use 		Exception;

###############################################################################

class GenericIDP Extends SAML {
	
	###########################################################################
	
	public function logout()
	{
		$returnTo = null;
		$parameters = array();
		$nameId = null;
		$sessionIndex = null;
		$nameIdFormat = null;
		
		parent::logout();

		if (isset($_SESSION['samlNameId'])) {
			$nameId = $_SESSION['samlNameId'];
		}
		if (isset($_SESSION['samlSessionIndex'])) {
			$sessionIndex = $_SESSION['samlSessionIndex'];
		}
		if (isset($_SESSION['samlNameIdFormat'])) {
			$nameIdFormat = $_SESSION['samlNameIdFormat'];
		}

		if($this->getSAMLAuth()) 
			$this->getSAMLAuth()->logout($returnTo, $parameters, $nameId, $sessionIndex, false, $nameIdFormat);

		# If LogoutRequest ID need to be saved in order to later validate it, do instead
		# $sloBuiltUrl = $this->getSAMLAuth()->logout(null, $paramters, $nameId, $sessionIndex, true);
		# $_SESSION['LogoutRequestID'] = $this->getSAMLAuth()->getLastRequestID();
		# header('Pragma: no-cache');
		# header('Cache-Control: no-cache, must-revalidate');
		# header('Location: ' . $sloBuiltUrl);
		# exit();
	}
	
	###########################################################################
	
	public function ACS()
	{
		if (isset($_SESSION) && isset($_SESSION['AuthNRequestID'])) 
			$requestID = $_SESSION['AuthNRequestID'];
		else 
			$requestID = null;

		try {
			$this->getSAMLAuth()->processResponse($requestID);
			$errors = $this->getSAMLAuth()->getErrors();
			if (!$this->getSAMLAuth()->isAuthenticated()) {
				$errmsg = "";
				if(!empty($errors)) 
					$errmsg = implode(', ', $errors);
				throw new Exception(sprintf(TEXT::get("format_saml_auth_error_S"), $errmsg));
			}
			$_SESSION['samlUserdata'] = $this->getSAMLAuth()->getAttributes();
			$_SESSION['samlNameId'] = $this->getSAMLAuth()->getNameId();
			$_SESSION['samlNameIdFormat'] = $this->getSAMLAuth()->getNameIdFormat();
			$_SESSION['samlSessionIndex'] = $this->getSAMLAuth()->getSessionIndex();
			unset($_SESSION['AuthNRequestID']);
			if (isset($_POST['RelayState']) && \OneLogin_Saml2_Utils::getSelfURL() != $_POST['RelayState']) {
				$this->getSAMLAuth()->redirectTo($_POST['RelayState']);
			}
		}
		catch (Exception $e) {
			throw $e;
		}
	}
	
	###########################################################################
	
	public function SLS()
	{
		if (isset($_SESSION) && isset($_SESSION['LogoutRequestID'])) 
			$requestID = $_SESSION['LogoutRequestID'];
		else 
			$requestID = null;

		$this->getSAMLAuth()->processSLO(false, $requestID);
		$errors = $this->getSAMLAuth()->getErrors();
		if (empty($errors)) {
			echo '<p>Sucessfully logged out</p>';
		} 
		else {
			echo '<p>', implode(', ', $errors), '</p>';
		}
	}
	
	###########################################################################
	
	public function hasSettings()
	{
		$settings = $this->getSettings();
		if(isset($settings['sp']) && isset($settings['idp'])) {
			if(count($settings['sp']) && count($settings['idp']))
				return true;
		}
		return false;
	}
	
	###########################################################################
	
	public function isLoggedIn()
	{
		if (isset($_SESSION['samlUserdata'])) {
			if (!empty($_SESSION['samlUserdata'])) {
				return true;
			}
		}
		return false;
	}
	
	###########################################################################
	
	public function process()
	{
		if (isset($_SESSION['samlUserdata'])) {
			if (!empty($_SESSION['samlUserdata'])) {
				$setup = new \CodePunch\Config\Settings($this->getAuth());
				$idpname = $setup->getEncryptedOption("genericidp_idp_name", "GenericIDP");
				$attributes = $_SESSION['samlUserdata'];
				$genericidpuser = "";
				if(isset($_SESSION['samlNameId']))
					$genericidpuser = $_SESSION['samlNameId'];
				$genericidpname = "";
				$samldata = array('idp'=>$idpname, 'name'=>$genericidpname, 'user'=>$genericidpuser);
				$mappeduser = $this->get_valid_user_name($genericidpuser, $genericidpname);
				$this->processUser($mappeduser, $samldata);
			} 
			else {
				// Error
			}
		} 
		else {
			$url = UTIL::get_root_url() . "saml.php?sso";
			header("Location: $url");
			exit;
		}

	}
	
	###########################################################################
	
	public function getOptions()
	{
		return array (
			'idp-name' => array('string', 'ID Provider name', 'Provider Name (eg. Google, SSOCircle)'),
			'idp-entityId' => array('string', 'ID Provider', 'Entity ID (Issuer URL)'),
			'idp-singleSignOnService' => array('string', 'ID Provider', 'SignOn URL (SAML 2.0 Endpoint)'),
			'idp-singleLogoutService' => array('string', 'ID Provider', 'Logout URL (SLO Endpoint)'),
			'idp-x509cert' => array('text', 'ID Provider', 'x509 Certificate'),
			'idp-requestedAuthnContext' => array('text', 'Security', 'RequestedAuthnContext [Leave empty or type-in "default" (without the quotes) to ignore this entry. Type-in "standard" for the standard settings. Otherwise type-in the required data as specified by the identity provider (one entry per line)]'),
			'idp-strictMode' => array('boolean', 'Strict Mode', 'SAML Strict Mode')
		);
	}
	
	###########################################################################
	
	public function getName()
	{
		$setup = new \CodePunch\Config\Settings($this->getAuth());
		return $setup->getEncryptedOption("genericidp_idp_name", "GenericIDP");
	}
	
	###########################################################################
	
	public function getSettings()
	{
		$setup = new \CodePunch\Config\Settings($this->getAuth());
		
		$settingsInfo = array('sp'=>array(), 'idp'=>array());
		$settingsInfo['sp']['entityId'] = UTIL::get_root_url() . "metadata.php";
		$settingsInfo['sp']['assertionConsumerService'] = array('url'=>UTIL::get_root_url() . "saml.php?acs");
		$settingsInfo['sp']['singleLogoutService'] = array('url'=>UTIL::get_root_url() . "saml.php?sls");
		$settingsInfo['sp']['NameIDFormat'] = 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress';

		$settingsInfo['idp']['entityId'] = $setup->getEncryptedOption("genericidp_idp_entityid", "");
		$settingsInfo['idp']['singleSignOnService'] = array('url' => $setup->getEncryptedOption("genericidp_idp_singlesignonservice", ""));
		$settingsInfo['idp']['singleLogoutService'] = array('url' => $setup->getEncryptedOption("genericidp_idp_singlelogoutservice", ""));
		$cert = $setup->getText("genericidp_idp_x509cert", "");
		$settingsInfo['idp']['x509cert'] = $this->getAuth()->decrypt($cert);
		
		$settingsInfo['strict'] = UTIL::str_to_bool($setup->getEncryptedOption("genericidp_idp_strictmode", "yes"), true);
		$settingsInfo['security'] = array();
		$settingsInfo['security']['signatureAlgorithm'] = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256';
		$settingsInfo['security']['digestAlgorithm'] = 'http://www.w3.org/2001/04/xmlenc#sha256';
		$reqauthncontext = $setup->getEncryptedOption("genericidp_idp_requestedauthncontext", "0");
		if($reqauthncontext == "0" || $reqauthncontext == "false" || trim(strtolower($reqauthncontext), " \"\n\r\t\v\0") == "default" || $reqauthncontext === false)
			$reqauthncontext = false;
		else if($reqauthncontext == "1" || $reqauthncontext == "true" || trim(strtolower($reqauthncontext), " \"\n\r\t\v\0") == "standard" || $reqauthncontext === true)
			$reqauthncontext = true;
		else if($reqauthncontext != "" && strpos($reqauthncontext, ":") !== false) {
			$reqauthncontext = str_replace("\r", "\n", $reqauthncontext);
			$reqauthncontext = str_replace("||", "\n", $reqauthncontext);
			$reqauthncontext = explode("\n", $reqauthncontext);
			$reqauthncontext = array_filter($reqauthncontext, 'strlen');
		}
		else
			$reqauthncontext = true;
		$settingsInfo['security']['requestedAuthnContext'] = $reqauthncontext;

		return $settingsInfo;
	}
	
}

###############################################################################
