You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

478 lines
18 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?php
// +----------------------------------------------------------------------
// | Description: 安装
// +----------------------------------------------------------------------
// | Author: Michael_xu | gengxiaoxu@5kcrm.com
// +----------------------------------------------------------------------
namespace app\admin\controller;
use think\Controller;
use think\Request;
use think\Db;
use Env;
class Install extends Controller
{
// private $count = 100;
// private $now = 0;
public function _initialize()
{
/*防止跨域*/
header('Access-Control-Allow-Origin: '.$_SERVER['HTTP_ORIGIN']);
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, authKey, sessionId");
$param = Request::instance()->param();
$this->param = $param;
// $request = request();
// $m = strtolower($request->module());
// $c = strtolower($request->controller());
// $a = strtolower($request->action());
//
// if (!in_array($a, array('upgrade','upgradeprocess','checkversion')) && file_exists(CONF_PATH . "install.lock")) {
// echo "<meta http-equiv='content-type' content='text/html; charset=UTF-8'> <script>alert('请勿重复安装!');location.href='".$_SERVER["HTTP_HOST"]."';</script>";
// die();
// }
}
private $upgrade_site = "http://message.72crm.com/";
/**
* [index 安装步骤]
* @author Michael_xu
* @param
*/
public function index()
{
$protocol = strpos(strtolower($_SERVER['HTTP_REFERER']), 'https') === false ? 'http' : 'https';
if (strpos(request()->url(), "index.php") === false) {
$url = $protocol. "://" .$_SERVER["HTTP_HOST"] . "/index.php" . request()->url();
header("Location:" . $url);
}
if (file_exists(CONF_PATH . "install.lock")) {
echo "<meta http-equiv='content-type' content='text/html; charset=UTF-8'> <script>alert('请勿重复安装!');location.href='".$protocol."://".$_SERVER["HTTP_HOST"]."';</script>";
die();
}
if (!file_exists(getcwd() . "/public/sql/5kcrm.sql")) {
echo "<meta http-equiv='content-type' content='text/html; charset=UTF-8'> <script>alert('缺少必要的数据库文件!');location.href='".$protocol."://".$_SERVER["HTTP_HOST"]."';</script>";
die();
}
return $this->fetch('index');
}
public function step1()
{
if (strpos(request()->url(), "index.php") === false) {
$protocol = strpos(strtolower($_SERVER['HTTP_REFERER']), 'https') === false ? 'http' : 'https';
$url = $protocol. "://" .$_SERVER["HTTP_HOST"] . "/index.php" . request()->url();
header("Location:" . $url);
}
session('install_error',null);
$data = [];
$data['env'] = self::checkNnv();
$data['dir'] = self::checkDir();
$data['version'] = $this->version();
$this->assign('data',$data);
return $this->fetch('step1');
}
//版本
public function version()
{
$res = include(CONF_PATH.'version.php');
return $res ? : array('VERSION' => '11.0.0','RELEASE' => '20210219');
}
public function step2(){
if (session('install_error')){
echo "<meta http-equiv='content-type' content='text/html; charset=UTF-8'> <script>alert('环境检测未通过,不能进行下一步操作!');location.href='".$_SERVER["HTTP_REFERER"]."';</script>";
die();
}
if (strpos(request()->url(), "index.php") === false) {
$protocol = strpos(strtolower($_SERVER['HTTP_REFERER']), 'https') === false ? 'http' : 'https';
$url = $protocol. "://" .$_SERVER["HTTP_HOST"] . "/index.php" . request()->url();
header("Location:" . $url);
}
$data['os'] = PHP_OS;
$data['php'] = phpversion();
$data['version'] = $this->version();
$this->assign('envir_data',$data);
return $this->fetch();
}
public function step3(){
return $this->fetch();
}
public function step4(){
if (session('install_error')){
return resultArray(['error' => '环境检测未通过,不能进行下一步操作!']);
}
if (file_exists(CONF_PATH . "install.lock")) {
return resultArray(['error' => '请勿重复安装!']);
}
if (!file_exists(getcwd() . "/public/sql/5kcrm.sql")) {
return resultArray(['error' => '缺少必要的数据库文件!']);
}
$temp = $this->param;
$param = $temp['form'];
$db_config['type'] = 'mysql';
$db_config['hostname'] = $param['databaseUrl'];
$db_config['hostport'] = $param['databasePort'];
$db_config['database'] = $param['databaseName'];
$db_config['username'] = $param['databaseUser'];
$db_config['password'] = $param['databasePwd'];
$db_config['prefix'] = '5kcrm_';
// $db_config['prefix'] = $param['databaseTable'];
$username = $param['root'];
$password = $param['pwd'];
$wkcode = $param['wkcode'];
if (empty($db_config['hostname'])) {
return resultArray(['error' => '请填写数据库主机!']);
}
if (empty($db_config['hostport'])) {
return resultArray(['error' => '请填写数据库端口!']);
}
if (preg_match('/[^0-9]/', $db_config['hostport'])) {
return resultArray(['error' => '数据库端口只能是数字!']);
}
if (empty($db_config['database'])) {
return resultArray(['error' => '请填写数据库名!']);
}
if (empty($db_config['username'])) {
return resultArray(['error' => '请填写数据库用户名!']);
}
if (empty($db_config['password'])) {
return resultArray(['error' => '请填写数据库密码!']);
}
if (empty($db_config['prefix'])) {
return resultArray(['error' => '请填写表前缀!']);
}
if (preg_match('/[^a-z0-9_]/i', $db_config['prefix'])) {
return resultArray(['error' => '表前缀只能包含数字、字母和下划线!']);
}
if (empty($username)) {
return resultArray(['error' => '请填写管理员用户名!']);
}
if (empty($wkcode)) {
return resultArray(['error' => '请填写序列号!']);
}
$resCheckData = checkWkCode($wkcode);
if (!$resCheckData) {
return resultArray(['error' => '序列号错误!']);
}
$resData = object_to_array(json_decode($resCheckData));
if ($resData['date'] != date('Y-m-d')) {
return resultArray(['error' => '序列号已失效,请前往悟空官网个人中心获取最新数据!']);
}
if (empty($password)) {
return resultArray(['error' => '请填写管理员密码!']);
}
session('install_count','');
session('install_now','');
$database = $db_config['database'];
unset($db_config['database']);
$connect = Db::connect($db_config);
// 检测数据库连接
try{
$ret = $connect->execute('select version()');
}catch(\Exception $e){
return resultArray(['error' => '数据库连接失败,请检查数据库配置!']);
}
$check = $connect->execute("SELECT * FROM information_schema.schemata WHERE schema_name='".$database."'");
if (!$check && !$connect->execute("CREATE DATABASE IF NOT EXISTS `".$database."` default collate utf8_general_ci ")) {
return resultArray(['error' => '没有找到您填写的数据库名且无法创建!请检查连接账号是否有创建数据库的权限!']);
}
$db_config['database'] = $database;
self::mkDatabase($db_config);
self::mkLicense($wkcode);
$C_Patch = substr($_SERVER['SCRIPT_FILENAME'],0,-10);
$sql = file_get_contents( $C_Patch.'/public/sql/5kcrm.sql');
$sqlList = parse_sql($sql, 0, ['5kcrm_' => $db_config['prefix']]);
if ($sqlList) {
$sqlList = array_filter($sqlList);
$install_count = count($sqlList);
session('install_count',$install_count);
foreach ($sqlList as $k=>$v) {
$install_now = $k+1;
session('install_now',$install_now);
try {
$temp_sql = $v.';';
Db::connect($db_config)->query($temp_sql);
} catch(\Exception $e) {
// return resultArray(['error' => '请启用InnoDB数据引擎并检查数据库是否有DROP和CREATE权限']);
return resultArray(['error' => '数据库sql安装出错请操作数据库手动导入sql文件']);
}
}
}
$salt = substr(md5(time()),0,4);
$password = user_md5(trim($password), $salt, $username);
//插入信息
Db::connect($db_config)->query("insert into ".$db_config['prefix']."admin_user (username, password, salt, img, thumb_img, realname, create_time, num, email, mobile, sex, status, structure_id, post, parent_id, type, authkey, authkey_time ) values ( '".$username."', '".$password."', '".$salt."', '', '', '管理员', ".time().", '', '', '".$username."', '', 1, 1, 'CEO', 0, 1, '', 0 )");
Db::connect($db_config)->query("insert into ".$db_config['prefix']."hrm_user_det (user_id, join_time, type, status, userstatus, create_time, update_time, mobile, sex, age, job_num, idtype, idnum, birth_time, nation, internship, done_time, parroll_id, email, political, location, leave_time ) values ( 1, ".time().", 1, 1, 2, ".time().", ".time().", '".$username."', '', 0, '', 0, '', '', 0, 0, 0, 0, '', '', '', 0 )");
touch(CONF_PATH . "install.lock");
return resultArray(['data'=>'安装成功']);
}
/**
* 安装成功界面
*
* @author fnqi
* @date 2021-03-11
* @return mixed
*/
public function step5()
{
return $this->fetch();
}
/**
* 安装超时界面
*
* @author fanqi
* @date 2021-03-11
* @return mixed
*/
public function step6()
{
return $this->fetch();
}
//ajax 进度条
public function progress()
{
$data['length'] = session('install_count');
$data['now'] = session('install_now');
return resultArray(['data'=>$data]);
}
//添加database.php文件
private function mkDatabase(array $data)
{
$code = <<<INFO
<?php
return [
// 数据库类型
'type' => 'mysql',
// 服务器地址
'hostname' => '{$data['hostname']}',
// 数据库名
'database' => '{$data['database']}',
// 用户名
'username' => '{$data['username']}',
// 密码
'password' => '{$data['password']}',
// 端口
'hostport' => '{$data['hostport']}',
// 连接dsn
'dsn' => '',
// 数据库连接参数
'params' => [],
// 数据库编码默认采用utf8
'charset' => 'utf8',
// 数据库表前缀
'prefix' => '{$data['prefix']}',
// 数据库调试模式
'debug' => true,
// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
'deploy' => 0,
// 数据库读写是否分离 主从式有效
'rw_separate' => false,
// 读写分离后 主服务器数量
'master_num' => 1,
// 指定从服务器序号
'slave_no' => '',
// 自动读取主库数据
'read_master' => false,
// 是否严格检查字段是否存在
'fields_strict' => true,
// 数据集返回类型
'resultset_type' => 'array',
];
INFO;
file_put_contents( CONF_PATH.'database.php', $code);
// 判断写入是否成功
$config = include CONF_PATH.'database.php';
if (empty($config['database']) || $config['database'] != $data['database']) {
return resultArray(['error' => '[config/database.php]数据库配置写入失败!']);
}
return true;
}
//检查目录权限
public function check_dir_iswritable($dir_path){
$dir_path=str_replace( '\\','/',$dir_path);
$is_writale=1;
if (!is_dir($dir_path)) {
$is_writale=0;
return $is_writale;
} else {
$file_hd=@fopen($dir_path.'/test.txt','w');
if (!$file_hd) {
@fclose($file_hd);
@unlink($dir_path.'/test.txt');
$is_writale=0;
return $is_writale;
}
$dir_hd = opendir($dir_path);
while (false !== ($file=readdir($dir_hd))) {
if ($file != "." && $file != "..") {
if (is_file($dir_path.'/'.$file)) {
//文件不可写,直接返回
if (!is_writable($dir_path.'/'.$file)) {
return 0;
}
} else {
$file_hd2=@fopen($dir_path.'/'.$file.'/test.txt','w');
if (!$file_hd2) {
@fclose($file_hd2);
@unlink($dir_path.'/'.$file.'/test.txt');
$is_writale=0;
return $is_writale;
}
//递归
$is_writale=check_dir_iswritable($dir_path.'/'.$file);
}
}
}
}
return $is_writale;
}
/**
* [checkVersion 检查升级]
* @author Michael_xu
* @param
*/
public function checkVersion(){
$version = Config::load('version');
$info = sendRequest($this->upgrade_site.'index.php?m=version&a=checkVersion', $version['VERSION']);
if ($info){
return resultArray(['data' => $info]);
} else {
return resultArray(['error' => '检查新版本出错!']);
}
}
/**
* 环境检测
* @return array
*/
private function checkNnv()
{
$items = [
'os' => ['操作系统', PHP_OS, '类Unix', 'ok'],
'php' => ['PHP版本', PHP_VERSION, '7.3 ( <em style="color: #888; font-size: 12px;">>= 7.0</em> )', 'ok','性能更佳'],
'gd' => ['gd', '开启', '开启', 'ok'],
'openssl' => ['openssl', '开启', '开启', 'ok'],
'pdo' => ['pdo', '开启', '开启', 'ok'],
];
// linux系统下需要posix扩展
if (in_array(PHP_OS, ['Linux', 'centos', 'Centos', 'ubuntu', 'Ubuntu'])) {
$items['posix'] = ['posix', '开启', '开启', 'ok'];
}
session('install_error','');
if (substr($items['php'][1],0,3) < '7.0') {
$items['php'][3] = 'error';
session('install_error', true);
}
if (!extension_loaded('gd')) {
$items['gd'][1] = '未开启';
$items['gd'][3] = 'error';
session('install_error', true);
}
if (!extension_loaded('openssl')) {
$items['openssl'][1] = '未开启';
$items['openssl'][3] = 'error';
session('install_error', true);
}
if (!extension_loaded('pdo')) {
$items['pdo'][1] = '未开启';
$items['pdo'][3] = 'error';
session('install_error', true);
}
// linux系统下检查是否加载了posix扩展
if (in_array(PHP_OS, ['Linux', 'centos', 'Centos', 'ubuntu', 'Ubuntu']) && !extension_loaded('posix')) {
$items['posix'][1] = '未开启';
$items['posix'][3] = 'error';
session('install_error', true);
}
return $items;
}
/**
* 目录权限检查
* @return array
*/
private function checkDir()
{
$items = [
['dir', $this->root_path.'application', 'application', '读写', '读写', 'ok'],
['dir', $this->root_path.'extend', 'extend', '读写', '读写', 'ok'],
['dir', $this->root_path.'runtime', './temp', '读写', '读写', 'ok'],
['dir', $this->root_path.'public', './upload', '读写', '读写', 'ok'],
['file', $this->root_path.'config', 'config', '读写', '读写', 'ok'],
];
foreach ($items as &$v) {
if ($v[0] == 'dir') {// 文件夹
if (!is_writable($v[1])) {
if (is_dir($v[1])) {
$v[4] = '不可写';
$v[5] = 'no';
} else {
$v[4] = '不存在';
$v[5] = 'no';
}
session('install_error', true);
}
} else {// 文件
if (!is_writable($v[1])) {
$v[4] = '不可写';
$v[5] = 'no';
session('install_error', true);
}
}
}
return $items;
}
/**
* 验证序列号
* @param
* @return
*/
public function checkCodeOld($username) {
$encryption = md5($username);
$substr = substr($username, strlen($username)-6);
$subArr = str_split($substr, 1);
$code = '';
for ($i = 0; $i <= 5; $i++) {
$code .= $encryption[$subArr[$i]];
}
return $code;
}
//写入license文件
private function mkLicense($wkcode)
{
file_put_contents( CONF_PATH.'license.dat', $wkcode);
// 判断写入是否成功
// $config = include CONF_PATH.'license.dat';
// if (empty($config)) {
// return resultArray(['error' => 'license配置写入失败']);
// }
return true;
}
}