Files
ProxyPanel/public/install.php
2020-08-05 03:51:27 +08:00

376 lines
9.1 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?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>