<?php

//--------------------------------------------------------------//
function sendy_passkeys_supported()
//--------------------------------------------------------------//
{
	return version_compare(PHP_VERSION, '7.1.0', '>=') &&
		extension_loaded('openssl') &&
		extension_loaded('json') &&
		file_exists(dirname(dirname(__DIR__)).'/vendor/autoload.php');
}

//--------------------------------------------------------------//
function sendy_passkeys_load_library()
//--------------------------------------------------------------//
{
	if(!sendy_passkeys_supported()) return false;
	require_once dirname(dirname(__DIR__)).'/vendor/autoload.php';
	return class_exists('\lbuchs\WebAuthn\WebAuthn');
}

//--------------------------------------------------------------//
function sendy_passkeys_json($data, $status=200)
//--------------------------------------------------------------//
{
	if(!headers_sent())
	{
		if(function_exists('http_response_code')) http_response_code($status);
		header('Content-Type: application/json');
	}
	echo json_encode($data);
	exit;
}

//--------------------------------------------------------------//
function sendy_passkeys_resume_session()
//--------------------------------------------------------------//
{
	if(version_compare(PHP_VERSION, '5.4') >= 0)
	{
		if(session_status() !== PHP_SESSION_ACTIVE) session_start();
	}
	else if(session_id()=='') session_start();
}

//--------------------------------------------------------------//
function sendy_passkeys_error($msg, $status=400)
//--------------------------------------------------------------//
{
	sendy_passkeys_json(array('success'=>false, 'msg'=>$msg), $status);
}

//--------------------------------------------------------------//
function sendy_passkeys_read_json()
//--------------------------------------------------------------//
{
	$raw = trim(file_get_contents('php://input'));
	if($raw=='') return array();
	$data = json_decode($raw, true);
	if(!is_array($data)) sendy_passkeys_error('Invalid request.');
	return $data;
}

//--------------------------------------------------------------//
function sendy_passkeys_ensure_table()
//--------------------------------------------------------------//
{
	global $mysqli;

	$q = 'CREATE TABLE IF NOT EXISTS `passkeys` (
		  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
		  `userID` int(11) unsigned NOT NULL,
		  `credential_id` varchar(1000) NOT NULL,
		  `credential_id_hash` char(64) NOT NULL,
		  `credential_public_key` text NOT NULL,
		  `signature_counter` int(11) DEFAULT NULL,
		  `name` varchar(100) DEFAULT NULL,
		  `transports` varchar(255) DEFAULT NULL,
		  `attestation_format` varchar(100) DEFAULT NULL,
		  `created` int(11) NOT NULL,
		  `last_used` int(11) DEFAULT NULL,
		  PRIMARY KEY (`id`),
		  KEY `passkeys_userID` (`userID`),
		  UNIQUE KEY `passkeys_credential_id_hash` (`credential_id_hash`)
		) DEFAULT CHARSET=utf8mb4';
	mysqli_query($mysqli, $q);

	$q = "SHOW COLUMNS FROM passkeys WHERE Field = 'credential_id_hash'";
	$r = mysqli_query($mysqli, $q);
	if(!$r || mysqli_num_rows($r)==0)
	{
		mysqli_query($mysqli, 'ALTER TABLE passkeys ADD credential_id_hash char(64) NOT NULL AFTER credential_id');
		$r2 = mysqli_query($mysqli, 'SELECT id, credential_id FROM passkeys');
		if($r2)
		{
			while($row = mysqli_fetch_array($r2))
			{
				$hash = mysqli_real_escape_string($mysqli, hash('sha256', base64_decode($row['credential_id'])));
				mysqli_query($mysqli, 'UPDATE passkeys SET credential_id_hash = "'.$hash.'" WHERE id = '.(int)$row['id']);
			}
		}
		mysqli_query($mysqli, 'ALTER TABLE passkeys ADD UNIQUE KEY passkeys_credential_id_hash (credential_id_hash)');
	}
}

//--------------------------------------------------------------//
function sendy_passkeys_rp_id()
//--------------------------------------------------------------//
{
	$host = CURRENT_DOMAIN;
	if(strpos($host, ':') !== false)
	{
		$parsed = parse_url((strpos($host, '://') === false ? 'https://' : '').$host);
		if(isset($parsed['host'])) $host = $parsed['host'];
	}
	return trim(strtolower($host), '.');
}

//--------------------------------------------------------------//
function sendy_passkeys_rp_name()
//--------------------------------------------------------------//
{
	global $mysqli;

	$name = 'Sendy';
	$r = mysqli_query($mysqli, 'SELECT company FROM login WHERE id = 1 LIMIT 1');
	if($r && mysqli_num_rows($r) > 0)
	{
		$row = mysqli_fetch_array($r);
		if(trim($row['company'])!='') $name = stripslashes($row['company']);
	}
	return $name;
}

//--------------------------------------------------------------//
function sendy_passkeys_webauthn()
//--------------------------------------------------------------//
{
	if(!sendy_passkeys_load_library()) sendy_passkeys_error('Passkeys require PHP 7.1+ with OpenSSL and the WebAuthn library installed.', 501);
	return new \lbuchs\WebAuthn\WebAuthn(sendy_passkeys_rp_name(), sendy_passkeys_rp_id(), array('none'));
}

//--------------------------------------------------------------//
function sendy_passkeys_b64decode($value)
//--------------------------------------------------------------//
{
	$decoded = base64_decode((string)$value, true);
	if($decoded===false) sendy_passkeys_error('Invalid passkey data.');
	return $decoded;
}

//--------------------------------------------------------------//
function sendy_passkeys_session_challenge($key)
//--------------------------------------------------------------//
{
	if(!isset($_SESSION[$key])) return null;
	if(is_string($_SESSION[$key])) return $_SESSION[$key];
	if(is_object($_SESSION[$key]) && method_exists($_SESSION[$key], 'getBinaryString')) return $_SESSION[$key]->getBinaryString();
	unset($_SESSION[$key]);
	return null;
}

//--------------------------------------------------------------//
function sendy_passkeys_redirect($redirect_to, $tied_to, $restricted_to_app)
//--------------------------------------------------------------//
{
	if($tied_to=='')
	{
		if($redirect_to=='') return get_app_info('path');
		return get_app_info('path').'/'.$redirect_to;
	}
	else
	{
		if($redirect_to=='') return get_app_info('path').'/app?i='.$restricted_to_app;
		return get_app_info('path').'/'.$redirect_to;
	}
}

//--------------------------------------------------------------//
function sendy_passkeys_set_login_cookie($userID, $email, $password_hash, $auth_salt)
//--------------------------------------------------------------//
{
	return setcookie('logged_in', hash('sha512', $userID.$email.$password_hash.$auth_salt), time()+31556926, '/', get_app_info('cookie_domain'));
}

//--------------------------------------------------------------//
function sendy_passkeys_json_safe_redirect($redirect_to)
//--------------------------------------------------------------//
{
	$redirect_to = trim((string)$redirect_to);
	if($redirect_to=='' || preg_match('/^[a-zA-Z0-9_\-\/?=&.%]+$/', $redirect_to)) return $redirect_to;
	return '';
}
