<?php
/**
 *ProxyPanel安装程序
 *
 * 安装完成后建议删除此文件
 *
 * @author Heron
 */

// error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);
// ini_set('display_errors', '1');
define('DS', DIRECTORY_SEPARATOR); // 定义目录分隔符
define('ROOT_PATH', __DIR__.DS.'..'.DS); // 定义根目录
define('DB_PATH', ROOT_PATH.'sql'.DS.'db.sql');// 数据库

// 判断文件或目录是否有写的权限
function is_really_writable($file) {
	if(DIRECTORY_SEPARATOR == '/' and @ ini_get("safe_mode") == false){
		return is_writable($file);
	}

	if(!is_file($file) or ($fp = @fopen($file, "r+")) === false){
		return false;
	}

	fclose($fp);

	return true;
}

$name = "ProxyPanel";

// 检测依赖组件目录是否存在
$checkDirs = [
	'vendor',
];

// 错误信息
$errInfo = '';

// 数据库配置文件
$ConfigFile = ROOT_PATH.'.env';

// 数据库标准配置文件
$exampleConfigFile = ROOT_PATH.'.env.example';

// 锁定的文件
$lockFile = ROOT_PATH.'.env';
if(is_file($lockFile)){
	$errInfo = "如果需要重新安装,请备份数据库后手动移除 .env 文件";
}elseif(version_compare(PHP_VERSION, '7.3.0', '<')){
	$errInfo = "当前PHP版本(".PHP_VERSION.")过低,请使用PHP7.3.0及以上版本";
}elseif(strtoupper(substr(PHP_OS, 0, 3)) === 'WIN'){
	$errInfo = "当前系统环境为Windows,无法进行安装";
}elseif(!is_file($exampleConfigFile)){
	$errInfo = "缺失标准配置文件 .env.example";
}elseif(!extension_loaded("PDO")){
	$errInfo = "当前PHP环境未启用PDO组件,无法进行安装";
}elseif(!is_really_writable(ROOT_PATH)){
	$open_basedir = ini_get('open_basedir');
	if($open_basedir){
		$dirArr = explode(PATH_SEPARATOR, $open_basedir);
		if($dirArr && in_array(__DIR__, $dirArr)){
			$errInfo = '当前服务器因配置了open_basedir,导致无法读取应用根目录';
		}
	}

	if(!$errInfo){
		$errInfo = '权限不足,无法写入配置文件.env';
	}
}else{
	$dirArr = [];
	foreach($checkDirs as $k => $v){
		if(!is_dir(ROOT_PATH.$v)){
			$errInfo = '请先在'.$name."根目录下执行<b>php composer.phar install</b> 安装依赖";
			break;
		}
	}
}

// 当前是POST请求
if(isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST'){
	if($errInfo){
		echo $errInfo;
		exit;
	}

	$err = '';
	$APP_KEY = md5(time().mt_rand(1, 1000000));
	$DB_HOST = isset($_POST['mysqlHost'])? trim($_POST['mysqlHost']) : '127.0.0.1';
	$DB_PORT = isset($_POST['mysqlPort'])? trim($_POST['mysqlPort']) : 3306;
	$hostArr = explode(':', $DB_HOST);
	if(count($hostArr) > 1){
		$DB_HOST = $hostArr[0];
		$DB_PORT = $hostArr[1];
	}
	$DB_USERNAME = isset($_POST['mysqlUsername'])? trim($_POST['mysqlUsername']) : 'proxypanel';
	$DB_PASSWORD = isset($_POST['mysqlPassword'])? trim($_POST['mysqlPassword']) : 'proxypanel';
	$DB_DATABASE = isset($_POST['mysqlDatabase'])? trim($_POST['mysqlDatabase']) : 'proxypanel';

	try{
		// 检测能否读取数据库文件
		$sql = @file_get_contents(DB_PATH);
		if(!$sql){
			throw new Exception("无法读取所需的".DB_PATH.",请检查是否有读权限");
		}

		$config = @file_get_contents($exampleConfigFile);
		if(!$config){
			throw new Exception("无法读取配置.env.example文件,请检查是否有读权限");
		}

		$pdo = new PDO("mysql:host={$DB_HOST};port={$DB_PORT}", $DB_USERNAME, $DB_PASSWORD, [
			PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
			PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"
		]);

		// 检测是否支持innodb存储引擎
		$pdoStatement = $pdo->query("SHOW VARIABLES LIKE 'innodb_version'");
		$result = $pdoStatement->fetch();
		if(!$result){
			throw new Exception("当前数据库不支持innodb存储引擎,请开启后再重新尝试安装");
		}

		$pdo->query("CREATE DATABASE IF NOT EXISTS `{$DB_DATABASE}` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;");
		$pdo->query("USE `{$DB_DATABASE}`");
		$pdo->exec($sql);

		// 写入数据库配置到.env文件
		$callback = function($matches) use ($APP_KEY, $DB_HOST, $DB_PORT, $DB_USERNAME, $DB_PASSWORD, $DB_DATABASE) {
			$field = $matches[1];
			$replace = ${"{$field}"};
			return "{$matches[1]}={$replace}".PHP_EOL;
		};
		$config = preg_replace_callback("/(APP_KEY|DB_HOST|DB_DATABASE|DB_USERNAME|DB_PASSWORD|DB_PORT)=(.*)(\s+)/",
			$callback, $config);
		$result = @file_put_contents($ConfigFile, $config);
		if(!$result){
			throw new Exception("无法写入数据库信息到.env文件,请检查是否有写权限");
		}

		echo "success";
	}catch(PDOException $e){
		$err = $e->getMessage();
	}catch(Exception $e){
		$err = $e->getMessage();
	}

	echo $err;
	exit;
}
?>
<!doctype html>
<html>
<head>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<title>安装<?php
		echo $name; ?></title>
	<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
	<meta name="renderer" content="webkit">

	<style>
		body {
			background: #5c97bd;
			margin: 0;
			padding: 0;
			line-height: 1.5;
		}

		body, input, button {
			font-family: 'Open Sans', sans-serif;
			font-size: 16px;
			color: #fff;
		}

		.container {
			max-width: 515px;
			margin: 0 auto;
			padding: 20px;
			text-align: center;
		}

		a {
			color: #fff7d0;
			text-decoration: none;
		}

		a:hover {
			text-decoration: underline;
		}

		h1 {
			margin-top: 0;
			margin-bottom: 10px;
		}

		h2 {
			font-size: 28px;
			font-weight: normal;
			color: #fff;
			margin-bottom: 0;
		}

		form {
			margin-top: 40px;
		}

		.form-group {
			margin-bottom: 20px;
		}

		.form-group .form-field:first-child input {
			border-top-left-radius: 4px;
			border-top-right-radius: 4px;
		}

		.form-group .form-field:last-child input {
			border-bottom-left-radius: 4px;
			border-bottom-right-radius: 4px;
		}

		.form-field input {
			background: #6ba3c8;
			margin: 0 0 1px;
			border: 2px solid transparent;
			transition: background 0.2s, border-color 0.2s, color 0.2s;
			width: 100%;
			padding: 15px 15px 15px 180px;
			box-sizing: border-box;
		}

		.form-field input:focus {
			border-color: #e8f6ff;
			outline: none;
		}

		.form-field label {
			float: left;
			width: 160px;
			text-align: right;
			margin-right: -160px;
			position: relative;
			margin-top: 18px;
			font-size: 14px;
			pointer-events: none;
			opacity: 0.7;
		}

		button, .btn {
			background: #fff;
			color: #6ba3ca;
			border: 0;
			font-weight: bold;
			border-radius: 4px;
			cursor: pointer;
			padding: 15px 30px;
			-webkit-appearance: none;
		}

		button[disabled] {
			opacity: 0.5;
		}

		#error, .error, #success, .success {
			background: #d66c6c;
			color: #fff;
			padding: 15px 20px;
			border-radius: 4px;
			margin-bottom: 20px;
		}

		#success {
			background: #3C5675;
		}

		#error a, .error a {
			color: white;
			text-decoration: underline;
		}
	</style>
</head>

<body>
<div class="container">
	<h2>安装 <?php
		echo $name; ?></h2>
	<div>
		<form method="post">
			<?php
			if($errInfo): ?>
				<div class="error">
					<?php
					echo $errInfo; ?>
				</div>
			<?php
			endif; ?>
			<div id="error" style="display:none"></div>
			<div id="success" style="display:none"></div>

			<div class="form-group">
				<div class="form-field">
					<label>MySQL 数据库地址</label>
					<input type="text" name="mysqlHost" value="127.0.0.1" required="">
				</div>

				<div class="form-field">
					<label>MySQL 数据库名</label>
					<input type="text" name="mysqlDatabase" value="proxypanel" required="">
				</div>

				<div class="form-field">
					<label>MySQL 用户名</label>
					<input type="text" name="mysqlUsername" value="proxypanel" required="">
				</div>

				<div class="form-field">
					<label>MySQL 密码</label>
					<input type="password" name="mysqlPassword">
				</div>

				<div class="form-field">
					<label>MySQL 端口号</label>
					<input type="number" name="mysqlPort" value="3306">
				</div>
			</div>

			<div class="form-buttons">
				<button type="submit" <?php
				echo $errInfo? 'disabled' : '' ?>>安装
				</button>
			</div>
		</form>

		<script src="//cdn.staticfile.org/jquery/2.1.4/jquery.min.js" type="text/javascript"></script>
		<script>
			$(function () {

				$('form').on('submit', function (e) {
					e.preventDefault();

					var $button = $(this).find('button').text('安装中...').prop('disabled', true);

					$.post('', $(this).serialize())
						.done(function (ret) {
							if (ret === 'success') {
								$('#error').hide();
								$("#success").text("安装成功,请使用[用户名:test@test.com、密码:123456]登录").show();
								$('<a class="btn" href="./admin/login">登录后台</a>').insertAfter($button);
								$button.remove();
								localStorage.setItem("fastep", "installed");
							} else {
								$('#error').show().text(ret);
								$button.prop('disabled', false).text('点击安装');
								$("html,body").animate({
									scrollTop: 0
								}, 500);
							}
						})
						.fail(function (data) {
							$('#error').show().text('发生错误:\n\n' + data.responseText);
							$button.prop('disabled', false).text('点击安装');
							$("html,body").animate({
								scrollTop: 0
							}, 500);
						});

					return false;
				});
			});
		</script>
	</div>
</div>
</body>
</html>