mirror of https://github.com/flucont/btcloud.git
				
				
			
				 14 changed files with 480 additions and 34 deletions
			
			
		- 
					18.env
 - 
					18.env.example
 - 
					13README.md
 - 
					81app/controller/Install.php
 - 
					2app/lib/Btapi.php
 - 
					2app/lib/Plugins.php
 - 
					10app/middleware/AuthAdmin.php
 - 
					10app/middleware/LoadConfig.php
 - 
					76app/script/convert.sh
 - 
					3app/view/admin/layout.html
 - 
					11app/view/admin/set.html
 - 
					268app/view/install/index.html
 - 
					BINpublic/win/panel/panel_7.6.0.zip
 - 
					2route/app.php
 
@ -1,18 +0,0 @@ | 
				
			|||
APP_DEBUG = false | 
				
			|||
 | 
				
			|||
[APP] | 
				
			|||
DEFAULT_TIMEZONE = Asia/Shanghai | 
				
			|||
 | 
				
			|||
[DATABASE] | 
				
			|||
TYPE = mysql | 
				
			|||
HOSTNAME = localhost | 
				
			|||
DATABASE = btcloud | 
				
			|||
USERNAME = btcloud | 
				
			|||
PASSWORD = 123456 | 
				
			|||
HOSTPORT = 3306 | 
				
			|||
CHARSET = utf8mb4 | 
				
			|||
PREFIX = cloud_ | 
				
			|||
DEBUG = false | 
				
			|||
 | 
				
			|||
[LANG] | 
				
			|||
default_lang = zh-cn | 
				
			|||
@ -0,0 +1,18 @@ | 
				
			|||
APP_DEBUG = false | 
				
			|||
 | 
				
			|||
[APP] | 
				
			|||
DEFAULT_TIMEZONE = Asia/Shanghai | 
				
			|||
 | 
				
			|||
[DATABASE] | 
				
			|||
TYPE = mysql | 
				
			|||
HOSTNAME = {dbhost} | 
				
			|||
DATABASE = {dbname} | 
				
			|||
USERNAME = {dbuser} | 
				
			|||
PASSWORD = {dbpwd} | 
				
			|||
HOSTPORT = {dbport} | 
				
			|||
CHARSET = utf8mb4 | 
				
			|||
PREFIX = {dbprefix} | 
				
			|||
DEBUG = false | 
				
			|||
 | 
				
			|||
[LANG] | 
				
			|||
default_lang = zh-cn | 
				
			|||
@ -0,0 +1,81 @@ | 
				
			|||
<?php | 
				
			|||
namespace app\controller; | 
				
			|||
 | 
				
			|||
use PDO; | 
				
			|||
use Exception; | 
				
			|||
use app\BaseController; | 
				
			|||
use think\facade\View; | 
				
			|||
use think\facade\Cache; | 
				
			|||
 | 
				
			|||
class Install extends BaseController | 
				
			|||
{ | 
				
			|||
    public function index() | 
				
			|||
    { | 
				
			|||
        if (file_exists(app()->getRootPath().'.env')){ | 
				
			|||
            return '当前已经安装成功,如果需要重新安装,请手动删除根目录.env文件'; | 
				
			|||
        } | 
				
			|||
        if(request()->isPost()){ | 
				
			|||
            $mysql_host = input('post.mysql_host', null, 'trim'); | 
				
			|||
            $mysql_port = intval(input('post.mysql_port', '3306')); | 
				
			|||
            $mysql_user = input('post.mysql_user', null, 'trim'); | 
				
			|||
            $mysql_pwd = input('post.mysql_pwd', null, 'trim'); | 
				
			|||
            $mysql_name = input('post.mysql_name', null, 'trim'); | 
				
			|||
            $mysql_prefix = input('post.mysql_prefix', 'cloud_', 'trim'); | 
				
			|||
            $admin_username = input('post.admin_username', null, 'trim'); | 
				
			|||
            $admin_password = input('post.admin_password', null, 'trim'); | 
				
			|||
 | 
				
			|||
            if(!$mysql_host || !$mysql_user || !$mysql_pwd || !$mysql_name || !$admin_username || !$admin_password){ | 
				
			|||
                return json(['code'=>0, 'msg'=>'必填项不能为空']); | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            $configdata = file_get_contents(app()->getRootPath().'.env.example'); | 
				
			|||
            $configdata = str_replace(['{dbhost}','{dbname}','{dbuser}','{dbpwd}','{dbport}','{dbprefix}'], [$mysql_host, $mysql_name, $mysql_user, $mysql_pwd, $mysql_port, $mysql_prefix], $configdata); | 
				
			|||
 | 
				
			|||
            try{ | 
				
			|||
                $DB=new PDO("mysql:host=".$mysql_host.";dbname=".$mysql_name.";port=".$mysql_port,$mysql_user,$mysql_pwd); | 
				
			|||
            }catch(Exception $e){ | 
				
			|||
                if($e->getCode() == 2002){ | 
				
			|||
                    $errorMsg='连接数据库失败:数据库地址填写错误!'; | 
				
			|||
                }elseif($e->getCode() == 1045){ | 
				
			|||
                    $errorMsg='连接数据库失败:数据库用户名或密码填写错误!'; | 
				
			|||
                }elseif($e->getCode() == 1049){ | 
				
			|||
                    $errorMsg='连接数据库失败:数据库名不存在!'; | 
				
			|||
                }else{ | 
				
			|||
                    $errorMsg='连接数据库失败:'.$e->getMessage(); | 
				
			|||
                } | 
				
			|||
                return json(['code'=>0, 'msg'=>$errorMsg]); | 
				
			|||
            } | 
				
			|||
            $DB->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT); | 
				
			|||
            $DB->exec("set sql_mode = ''"); | 
				
			|||
            $DB->exec("set names utf8"); | 
				
			|||
 | 
				
			|||
            $sqls=file_get_contents(app()->getRootPath().'install.sql'); | 
				
			|||
            $sqls=explode(';', $sqls); | 
				
			|||
            $sqls[]="REPLACE INTO `".$mysql_prefix."config` VALUES ('syskey', '".random(16)."')"; | 
				
			|||
            $success=0;$error=0;$errorMsg=null; | 
				
			|||
            foreach ($sqls as $value) { | 
				
			|||
                $value=trim($value); | 
				
			|||
                if(empty($value))continue; | 
				
			|||
                $value = str_replace('cloud_',$mysql_prefix,$value); | 
				
			|||
                if($DB->exec($value)===false){ | 
				
			|||
                    $error++; | 
				
			|||
                    $dberror=$DB->errorInfo(); | 
				
			|||
                    $errorMsg.=$dberror[2]."\n"; | 
				
			|||
                }else{ | 
				
			|||
                    $success++; | 
				
			|||
                } | 
				
			|||
            } | 
				
			|||
            if(empty($errorMsg)){ | 
				
			|||
                if(!file_put_contents(app()->getRootPath().'.env', $configdata)){ | 
				
			|||
                    return json(['code'=>0, 'msg'=>'保存失败,请确保网站根目录有写入权限']); | 
				
			|||
                } | 
				
			|||
                Cache::clear(); | 
				
			|||
                return json(['code'=>1, 'msg'=>'安装完成!成功执行SQL语句'.$success.'条']); | 
				
			|||
            }else{ | 
				
			|||
                return json(['code'=>0, 'msg'=>$errorMsg]); | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
        return view(); | 
				
			|||
    } | 
				
			|||
     | 
				
			|||
} | 
				
			|||
@ -0,0 +1,76 @@ | 
				
			|||
#!/bin/bash | 
				
			|||
 | 
				
			|||
Linux_Version="7.9.3" | 
				
			|||
Windows_Version="7.6.0" | 
				
			|||
 | 
				
			|||
FILES=( | 
				
			|||
public/install/src/panel6.zip | 
				
			|||
public/install/update/LinuxPanel-${Linux_Version}.zip | 
				
			|||
public/install/install_6.0.sh | 
				
			|||
public/install/update_panel.sh | 
				
			|||
public/install/update6.sh | 
				
			|||
public/win/install/panel_update.py | 
				
			|||
public/win/panel/panel_${Windows_Version}.zip | 
				
			|||
public/win/panel/data/api.py | 
				
			|||
public/win/panel/data/setup.py | 
				
			|||
) | 
				
			|||
 | 
				
			|||
DIR=$1 | 
				
			|||
SITEURL=$2 | 
				
			|||
 | 
				
			|||
if [ ! -d "$DIR" ]; then | 
				
			|||
	echo "网站目录不存在" | 
				
			|||
	exit 1 | 
				
			|||
fi | 
				
			|||
if [ "$SITEURL" = "" ]; then | 
				
			|||
	echo "网站URL不正确" | 
				
			|||
	exit 1 | 
				
			|||
fi | 
				
			|||
 | 
				
			|||
function handleFile() | 
				
			|||
{ | 
				
			|||
	Filename=$1 | 
				
			|||
	if [ "${Filename##*.}" = "zip" ]; then | 
				
			|||
		handleZipFile $Filename | 
				
			|||
	else | 
				
			|||
		handleTextFile $Filename | 
				
			|||
	fi | 
				
			|||
} | 
				
			|||
 | 
				
			|||
function handleZipFile() | 
				
			|||
{ | 
				
			|||
	Filename=$1 | 
				
			|||
	mkdir -p /tmp/package | 
				
			|||
	unzip -o -q $Filename -d /tmp/package | 
				
			|||
	grep -rl --include=\*.py --include=\*.sh --include=index.js 'http://www.example.com' /tmp/package | xargs -I @ sed -i "s|http://www.example.com|${SITEURL}|g" @ | 
				
			|||
	Sprit_SITEURK=${SITEURL//\//\\\\\/} | 
				
			|||
	grep -rl --include=\*.sh 'http:\\\/\\\/www.example.com' /tmp/package | xargs -I @ sed -i "s|http:\\\/\\\/www.example.com|${Sprit_SITEURK}|g" @ | 
				
			|||
	rm -f $Filename | 
				
			|||
	cd /tmp/package && zip -9 -q -r $Filename * && cd - | 
				
			|||
	rm -rf /tmp/package | 
				
			|||
} | 
				
			|||
 | 
				
			|||
function handleTextFile() | 
				
			|||
{ | 
				
			|||
	sed -i "s|http://www.example.com|${SITEURL}|g" $1 | 
				
			|||
} | 
				
			|||
 | 
				
			|||
 | 
				
			|||
echo "==========================" | 
				
			|||
echo "正在处理中..." | 
				
			|||
echo "==========================" | 
				
			|||
 | 
				
			|||
for File in ${FILES[@]} | 
				
			|||
do | 
				
			|||
	Filename="${DIR}${File}" | 
				
			|||
	if [ -f "$Filename" ]; then | 
				
			|||
		handleFile $Filename | 
				
			|||
		echo -e "成功处理文件:\033[32m${Filename}\033[0m" | 
				
			|||
	else | 
				
			|||
		echo -e "文件不存在:\033[33m${Filename}\033[0m" | 
				
			|||
	fi | 
				
			|||
done | 
				
			|||
 | 
				
			|||
echo "==========================" | 
				
			|||
echo "处理完成" | 
				
			|||
echo "==========================" | 
				
			|||
@ -0,0 +1,268 @@ | 
				
			|||
<!doctype html> | 
				
			|||
<html> | 
				
			|||
<head> | 
				
			|||
    <meta charset="utf-8"> | 
				
			|||
    <meta http-equiv="X-UA-Compatible" content="IE=edge"> | 
				
			|||
    <title>宝塔第三方云端 - 安装程序</title> | 
				
			|||
    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" /> | 
				
			|||
    <meta name="renderer" content="webkit"> | 
				
			|||
    <style> | 
				
			|||
        body { | 
				
			|||
            background: #f1f6fd; | 
				
			|||
            margin: 0; | 
				
			|||
            padding: 0; | 
				
			|||
            line-height: 1.5; | 
				
			|||
            -webkit-font-smoothing: antialiased; | 
				
			|||
            -moz-osx-font-smoothing: grayscale; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        body, input, button { | 
				
			|||
            font-family: 'Source Sans Pro', 'Helvetica Neue', Helvetica, 'Microsoft Yahei', Arial, sans-serif; | 
				
			|||
            font-size: 14px; | 
				
			|||
            color: #7E96B3; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        .container { | 
				
			|||
            max-width: 480px; | 
				
			|||
            margin: 0 auto; | 
				
			|||
            padding: 20px; | 
				
			|||
            text-align: center; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        a { | 
				
			|||
            color: #4e73df; | 
				
			|||
            text-decoration: none; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        a:hover { | 
				
			|||
            text-decoration: underline; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        h1 { | 
				
			|||
            margin-top: 0; | 
				
			|||
            margin-bottom: 10px; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        h2 { | 
				
			|||
            font-size: 28px; | 
				
			|||
            font-weight: normal; | 
				
			|||
            color: #3C5675; | 
				
			|||
            margin-bottom: 0; | 
				
			|||
            margin-top: 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: #fff; | 
				
			|||
            margin: 0 0 2px; | 
				
			|||
            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: #4e73df; | 
				
			|||
            background: #fff; | 
				
			|||
            color: #444; | 
				
			|||
            outline: none; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        .form-field label { | 
				
			|||
            float: left; | 
				
			|||
            width: 160px; | 
				
			|||
            text-align: right; | 
				
			|||
            margin-right: -160px; | 
				
			|||
            position: relative; | 
				
			|||
            margin-top: 15px; | 
				
			|||
            font-size: 14px; | 
				
			|||
            pointer-events: none; | 
				
			|||
            opacity: 0.7; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        button, .btn { | 
				
			|||
            background: #3C5675; | 
				
			|||
            color: #fff; | 
				
			|||
            border: 0; | 
				
			|||
            font-weight: bold; | 
				
			|||
            border-radius: 4px; | 
				
			|||
            cursor: pointer; | 
				
			|||
            padding: 15px 30px; | 
				
			|||
            -webkit-appearance: none; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        button[disabled] { | 
				
			|||
            opacity: 0.5; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        .form-buttons { | 
				
			|||
            height: 52px; | 
				
			|||
            line-height: 52px; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        .form-buttons .btn { | 
				
			|||
            margin-right: 5px; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        #error, .error, #success, .success, #warmtips, .warmtips { | 
				
			|||
            background: #D83E3E; | 
				
			|||
            color: #fff; | 
				
			|||
            padding: 15px 20px; | 
				
			|||
            border-radius: 4px; | 
				
			|||
            margin-bottom: 20px; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        #success { | 
				
			|||
            background: #3C5675; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        #error a, .error a { | 
				
			|||
            color: white; | 
				
			|||
            text-decoration: underline; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        #warmtips { | 
				
			|||
            background: #fff; | 
				
			|||
            font-size: 14px; | 
				
			|||
            color: #3C5675; | 
				
			|||
            border: 2px solid #4e73df; | 
				
			|||
            text-align: left; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
    </style> | 
				
			|||
</head> | 
				
			|||
 | 
				
			|||
<body> | 
				
			|||
<div class="container"> | 
				
			|||
    <h1> | 
				
			|||
        <svg t="1660545699809" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4887" width="100px" height="100px"> | 
				
			|||
             <path d="M811.4 418.7C765.6 297.9 648.9 212 512.2 212S258.8 297.8 213 418.6C127.3 441.1 64 519.1 64 612c0 110.5 89.5 200 199.9 200h496.2C870.5 812 960 722.5 960 612c0-92.7-63.1-170.7-148.6-193.3z m36.3 281c-23.4 23.4-54.5 36.3-87.6 36.3H263.9c-33.1 0-64.2-12.9-87.6-36.3-23.4-23.4-36.3-54.6-36.3-87.7 0-28 9.1-54.3 26.2-76.3 16.7-21.3 40.2-36.8 66.1-43.7l37.9-9.9 13.9-36.6c8.6-22.8 20.6-44.1 35.7-63.4 14.9-19.2 32.6-35.9 52.4-49.9 41.1-28.9 89.5-44.2 140-44.2s98.9 15.3 140 44.2c19.9 14 37.5 30.8 52.4 49.9 15.1 19.3 27.1 40.7 35.7 63.4l13.8 36.5 37.8 10c54.3 14.5 92.1 63.8 92.1 120 0 33.1-12.9 64.3-36.3 87.7z" p-id="4888" fill="#4e73df"></path> | 
				
			|||
        </svg> | 
				
			|||
    </h1> | 
				
			|||
    <h2>宝塔第三方云端 - 安装程序</h2> | 
				
			|||
    <div> | 
				
			|||
 | 
				
			|||
        <form method="post"> | 
				
			|||
            <div id="error" style="display:none"></div> | 
				
			|||
            <div id="success" style="display:none"></div> | 
				
			|||
            <div id="warmtips" style="display:none"><p>安装完成后,你还需要进行以下操作:</p><p>1、在后台使用批量替换工具,执行命令一键替换压缩包与安装脚本中的域名。</p><p></p>2、在后台配置面板对接,同步插件列表与插件包。</p></div> | 
				
			|||
 | 
				
			|||
            <div class="form-group"> | 
				
			|||
                <div class="form-field"> | 
				
			|||
                    <label>MySQL 数据库地址</label> | 
				
			|||
                    <input type="text" name="mysql_host" value="localhost" required=""> | 
				
			|||
                </div> | 
				
			|||
 | 
				
			|||
                <div class="form-field"> | 
				
			|||
                    <label>MySQL 数据库端口</label> | 
				
			|||
                    <input type="number" name="mysql_port" value="3306"> | 
				
			|||
                </div> | 
				
			|||
 | 
				
			|||
                <div class="form-field"> | 
				
			|||
                    <label>MySQL 用户名</label> | 
				
			|||
                    <input type="text" name="mysql_user" value="" required=""> | 
				
			|||
                </div> | 
				
			|||
 | 
				
			|||
                <div class="form-field"> | 
				
			|||
                    <label>MySQL 密码</label> | 
				
			|||
                    <input type="text" name="mysql_pwd" value="" required=""> | 
				
			|||
                </div> | 
				
			|||
 | 
				
			|||
                <div class="form-field"> | 
				
			|||
                    <label>MySQL 数据库名</label> | 
				
			|||
                    <input type="text" name="mysql_name" value="" required=""> | 
				
			|||
                </div> | 
				
			|||
 | 
				
			|||
                <div class="form-field"> | 
				
			|||
                    <label>MySQL 数据表前缀</label> | 
				
			|||
                    <input type="text" name="mysql_prefix" value="cloud_"> | 
				
			|||
                </div> | 
				
			|||
            </div> | 
				
			|||
 | 
				
			|||
            <div class="form-group"> | 
				
			|||
                <div class="form-field"> | 
				
			|||
                    <label>管理员用户名</label> | 
				
			|||
                    <input type="text" name="admin_username" value="admin" required=""/> | 
				
			|||
                </div> | 
				
			|||
 | 
				
			|||
                <div class="form-field"> | 
				
			|||
                    <label>管理员密码</label> | 
				
			|||
                    <input type="text" name="admin_password" value="123456" required=""> | 
				
			|||
                </div> | 
				
			|||
            </div> | 
				
			|||
 | 
				
			|||
            <div class="form-buttons"> | 
				
			|||
                <!--@formatter:off--> | 
				
			|||
                <button type="submit" >点击安装</button> | 
				
			|||
                <!--@formatter:on--> | 
				
			|||
            </div> | 
				
			|||
        </form> | 
				
			|||
    </div> | 
				
			|||
</div> | 
				
			|||
<script src="//cdn.staticfile.org/jquery/2.1.4/jquery.min.js"></script> | 
				
			|||
<script> | 
				
			|||
    $(function () { | 
				
			|||
        $('form').on('submit', function (e) { | 
				
			|||
            e.preventDefault(); | 
				
			|||
            var form = this; | 
				
			|||
            var $error = $("#error"); | 
				
			|||
            var $success = $("#success"); | 
				
			|||
            var $button = $(this).find('button') | 
				
			|||
                .text("安装中...") | 
				
			|||
                .prop('disabled', true); | 
				
			|||
            $.ajax({ | 
				
			|||
                url: "", | 
				
			|||
                type: "POST", | 
				
			|||
                dataType: "json", | 
				
			|||
                data: $(this).serialize(), | 
				
			|||
                success: function (ret) { | 
				
			|||
                    if (ret.code == 1) { | 
				
			|||
                        $error.hide(); | 
				
			|||
                        $(".form-group", form).remove(); | 
				
			|||
                        $button.remove(); | 
				
			|||
                        $("#success").text(ret.msg).show(); | 
				
			|||
                        $("#warmtips").show(); | 
				
			|||
 | 
				
			|||
                        $buttons = $(".form-buttons", form); | 
				
			|||
                        $('<a class="btn" href="/admin" style="background:#4e73df">进入后台</a>').appendTo($buttons); | 
				
			|||
 | 
				
			|||
                    } else { | 
				
			|||
                        $error.show().text(ret.msg); | 
				
			|||
                        $button.prop('disabled', false).text("点击安装"); | 
				
			|||
                        $("html,body").animate({ | 
				
			|||
                            scrollTop: 0 | 
				
			|||
                        }, 500); | 
				
			|||
                    } | 
				
			|||
                }, | 
				
			|||
                error: function (xhr) { | 
				
			|||
                    $error.show().text(xhr.responseText); | 
				
			|||
                    $button.prop('disabled', false).text("点击安装"); | 
				
			|||
                    $("html,body").animate({ | 
				
			|||
                        scrollTop: 0 | 
				
			|||
                    }, 500); | 
				
			|||
                } | 
				
			|||
            }); | 
				
			|||
            return false; | 
				
			|||
        }); | 
				
			|||
    }); | 
				
			|||
</script> | 
				
			|||
</body> | 
				
			|||
</html> | 
				
			|||
						Write
						Preview
					
					
					Loading…
					
					Cancel
						Save
					
		Reference in new issue