model.php 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856
  1. <?php
  2. /** 安装界面需要的各种模块 */
  3. class installModel
  4. {
  5. private $host;
  6. private $name;
  7. private $user;
  8. private $encoding;
  9. private $password;
  10. private $port;
  11. private $prefix;
  12. private $successTable = [];
  13. /**
  14. * @var bool
  15. */
  16. private $allowNext = true;
  17. /**
  18. * @var PDO|string
  19. */
  20. private $dbh = null;
  21. /**
  22. * @var bool
  23. */
  24. private $clearDB = false;
  25. /**
  26. * Notes: php版本
  27. * @author luzg(2020/8/25 9:56)
  28. * @return string
  29. */
  30. public function getPhpVersion()
  31. {
  32. return PHP_VERSION;
  33. }
  34. /**
  35. * Notes: 当前版本是否符合
  36. * @author luzg(2020/8/25 9:57)
  37. * @return string
  38. */
  39. public function checkPHP()
  40. {
  41. return $result = version_compare(PHP_VERSION, '8.0.0') >= 0 ? 'ok' : 'fail';
  42. }
  43. /**
  44. * Notes: 是否有PDO
  45. * @author luzg(2020/8/25 9:57)
  46. * @return string
  47. */
  48. public function checkPDO()
  49. {
  50. return $result = extension_loaded('pdo') ? 'ok' : 'fail';
  51. }
  52. /**
  53. * Notes: 是否有PDO::MySQL
  54. * @author luzg(2020/8/25 9:58)
  55. * @return string
  56. */
  57. public function checkPDOMySQL()
  58. {
  59. return $result = extension_loaded('pdo_mysql') ? 'ok' : 'fail';
  60. }
  61. /**
  62. * Notes: 是否支持JSON
  63. * @author luzg(2020/8/25 9:58)
  64. * @return string
  65. */
  66. public function checkJSON()
  67. {
  68. return $result = extension_loaded('json') ? 'ok' : 'fail';
  69. }
  70. /**
  71. * Notes: 是否支持openssl
  72. * @author luzg(2020/8/25 9:58)
  73. * @return string
  74. */
  75. public function checkOpenssl()
  76. {
  77. return $result = extension_loaded('openssl') ? 'ok' : 'fail';
  78. }
  79. /**
  80. * Notes: 是否支持mbstring
  81. * @author luzg(2020/8/25 9:58)
  82. * @return string
  83. */
  84. public function checkMbstring()
  85. {
  86. return $result = extension_loaded('mbstring') ? 'ok' : 'fail';
  87. }
  88. /**
  89. * Notes: 是否支持zlib
  90. * @author luzg(2020/8/25 9:59)
  91. * @return string
  92. */
  93. public function checkZlib()
  94. {
  95. return $result = extension_loaded('zlib') ? 'ok' : 'fail';
  96. }
  97. /**
  98. * Notes: 是否支持curl
  99. * @author luzg(2020/8/25 9:59)
  100. * @return string
  101. */
  102. public function checkCurl()
  103. {
  104. return $result = extension_loaded('curl') ? 'ok' : 'fail';
  105. }
  106. /**
  107. * Notes: 检查GD2扩展
  108. * @author luzg(2020/8/26 9:59)
  109. * @return string
  110. */
  111. public function checkGd2()
  112. {
  113. return $result = extension_loaded('gd') ? 'ok' : 'fail';
  114. }
  115. /**
  116. * Notes: 检查Dom扩展
  117. * @author luzg(2020/8/26 9:59)
  118. * @return string
  119. */
  120. public function checkDom()
  121. {
  122. return $result = extension_loaded('dom') ? 'ok' : 'fail';
  123. }
  124. /**
  125. * Notes: 是否支持filter
  126. * @author luzg(2020/8/25 9:59)
  127. * @return string
  128. */
  129. public function checkFilter()
  130. {
  131. return $result = extension_loaded('filter') ? 'ok' : 'fail';
  132. }
  133. /**
  134. * Notes: 是否支持iconv
  135. * @author luzg(2020/8/25 9:59)
  136. * @return string
  137. */
  138. public function checkIconv()
  139. {
  140. return $result = extension_loaded('iconv') ? 'ok' : 'fail';
  141. }
  142. /**
  143. * Notes: 检查fileinfo扩展
  144. * @author 段誉(2021/6/28 11:03)
  145. * @return string
  146. */
  147. public function checkFileInfo()
  148. {
  149. return $result = extension_loaded('fileinfo') ? 'ok' : 'fail';
  150. }
  151. /**
  152. * Notes: 取得临时目录路径
  153. * @author luzg(2020/8/25 10:05)
  154. * @return array
  155. */
  156. public function getTmpRoot()
  157. {
  158. $path = $this->getAppRoot() . '/runtime';
  159. return [
  160. 'path' => $path,
  161. 'exists' => is_dir($path),
  162. 'writable' => is_writable($path),
  163. ];
  164. }
  165. /**
  166. * Notes: 检查临时路径
  167. * @author luzg(2020/8/25 10:06)
  168. * @return string
  169. */
  170. public function checkTmpRoot()
  171. {
  172. $tmpRoot = $this->getTmpRoot()['path'];
  173. return $result = (is_dir($tmpRoot) and is_writable($tmpRoot)) ? 'ok' : 'fail';
  174. }
  175. /**
  176. * Notes: SESSION路径是否可写
  177. * @author luzg(2020/8/25 10:06)
  178. * @return mixed
  179. */
  180. public function getSessionSavePath()
  181. {
  182. $sessionSavePath = preg_replace("/\d;/", '', session_save_path());
  183. return [
  184. 'path' => $sessionSavePath,
  185. 'exists' => is_dir($sessionSavePath),
  186. 'writable' => is_writable($sessionSavePath),
  187. ];
  188. }
  189. /**
  190. * Notes: 检查session路径可写状态
  191. * @author luzg(2020/8/25 10:13)
  192. * @return string
  193. */
  194. public function checkSessionSavePath()
  195. {
  196. $sessionSavePath = preg_replace("/\d;/", '', session_save_path());
  197. $result = (is_dir($sessionSavePath) and is_writable($sessionSavePath)) ? 'ok' : 'fail';
  198. if ($result == 'fail') return $result;
  199. file_put_contents($sessionSavePath . '/zentaotest', 'zentao');
  200. $sessionContent = file_get_contents($sessionSavePath . '/zentaotest');
  201. if ($sessionContent == 'zentao') {
  202. unlink($sessionSavePath . '/zentaotest');
  203. return 'ok';
  204. }
  205. return 'fail';
  206. }
  207. /**
  208. * Notes: 取得data目录是否可选
  209. * @author luzg(2020/8/25 10:58)
  210. * @return array
  211. */
  212. public function getDataRoot()
  213. {
  214. $path = $this->getAppRoot();
  215. return [
  216. 'path' => $path . 'www' . DS . 'data',
  217. 'exists' => is_dir($path),
  218. 'writable' => is_writable($path),
  219. ];
  220. }
  221. /**
  222. * Notes: 取得root路径
  223. * @author luzg(2020/8/25 11:02)
  224. * @return string
  225. */
  226. public function checkDataRoot()
  227. {
  228. $dataRoot = $this->getAppRoot() . 'www' . DS . 'data';
  229. return $result = (is_dir($dataRoot) and is_writable($dataRoot)) ? 'ok' : 'fail';
  230. }
  231. /**
  232. * Notes: 取得php.ini信息
  233. * @author luzg(2020/8/25 11:03)
  234. * @return string
  235. */
  236. public function getIniInfo()
  237. {
  238. $iniInfo = '';
  239. ob_start();
  240. phpinfo(1);
  241. $lines = explode("\n", strip_tags(ob_get_contents()));
  242. ob_end_clean();
  243. foreach ($lines as $line) if (strpos($line, 'ini') !== false) $iniInfo .= $line . "\n";
  244. return $iniInfo;
  245. }
  246. /**
  247. * Notes: 创建安装锁定文件
  248. * @author luzg(2020/8/28 11:32)
  249. * @return bool
  250. */
  251. public function mkLockFile()
  252. {
  253. return touch($this->getAppRoot() . '/config/install.lock');
  254. }
  255. /**
  256. * Notes: 检查之前是否有安装
  257. * @author luzg(2020/8/28 11:36)
  258. */
  259. public function appIsInstalled()
  260. {
  261. return file_exists($this->getAppRoot() . '/config/install.lock');
  262. }
  263. /**
  264. * Notes: 取得配置信息
  265. * @author luzg(2020/8/25 11:05)
  266. * @param string $dbName 数据库名称
  267. * @param array $connectionInfo 连接信息
  268. * @return stdclass
  269. * @throws Exception
  270. */
  271. public function checkConfig($dbName, $connectionInfo)
  272. {
  273. $return = new stdclass();
  274. $return->result = 'ok';
  275. /* Connect to database. */
  276. $this->setDBParam($connectionInfo);
  277. $this->dbh = $this->connectDB();
  278. if (strpos($dbName, '.') !== false) {
  279. $return->result = 'fail';
  280. $return->error = '没有发现数据库信息';
  281. return $return;
  282. }
  283. if ( !is_object($this->dbh)) {
  284. $return->result = 'fail';
  285. $return->error = '安装错误,请检查连接信息:'.mb_strcut($this->dbh,0,30).'...';
  286. echo $this->dbh;
  287. return $return;
  288. }
  289. /* Get mysql version. */
  290. $version = $this->getMysqlVersion();
  291. // 检查mysql版本
  292. if (version_compare($version, '5.7', '<')) {
  293. $return->result = 'fail';
  294. $return->error = 'MYSQL数据库版本不能小于5.7';
  295. return $return;
  296. }
  297. /* check mysql sql_model */
  298. if(!$this->checkSqlMode($version)) {
  299. $return->result = 'fail';
  300. $return->error = '请在mysql配置文件修改sql-mode添加NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
  301. return $return;
  302. }
  303. /* If database no exits, try create it. */
  304. if ( !$this->dbExists()) {
  305. if ( !$this->createDB($version)) {
  306. $return->result = 'fail';
  307. $return->error = '创建数据库错误';
  308. return $return;
  309. }
  310. } elseif ($this->tableExits() and $this->clearDB == false) {
  311. $return->result = 'fail';
  312. $return->error = '数据表已经存在,您之前应该有安装过本系统,继续安装请选择清空现有数据';
  313. return $return;
  314. } elseif ($this->dbExists() and $this->clearDB == true) {
  315. if (!$this->dropDb($connectionInfo['name'])) {
  316. $return->result = 'fail';
  317. $return->error = '数据表已经存在,删除已存在库错误,请手动清除';
  318. return $return;
  319. } else {
  320. if ( !$this->createDB($version)) {
  321. $return->result = 'fail';
  322. $return->error = '创建数据库错误!';
  323. return $return;
  324. }
  325. }
  326. }
  327. /* Create tables. */
  328. if ( !$this->createTable($version, $connectionInfo)) {
  329. $return->result = 'fail';
  330. $return->error = '创建表格失败';
  331. return $return;
  332. }
  333. return $return;
  334. }
  335. /**
  336. * Notes: 设置数据库相关信息
  337. * @author luzg(2020/8/25 11:17)
  338. * @param $post
  339. */
  340. public function setDBParam($post)
  341. {
  342. $this->host = $post['host'];
  343. $this->name = $post['name'];
  344. $this->user = $post['user'];
  345. $this->encoding = 'utf8mb4';
  346. $this->password = $post['password'];
  347. $this->port = $post['port'];
  348. $this->prefix = $post['prefix'];
  349. $this->clearDB = $post['clear_db'] == 'on';
  350. }
  351. /**
  352. * Notes: 连接数据库
  353. * @author luzg(2020/8/25 11:56)
  354. * @return PDO|string
  355. */
  356. public function connectDB()
  357. {
  358. $dsn = "mysql:host={$this->host}; port={$this->port}";
  359. try {
  360. $dbh = new PDO($dsn, $this->user, $this->password);
  361. $dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
  362. $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  363. $dbh->exec("SET NAMES {$this->encoding}");
  364. $dbh->exec("SET NAMES {$this->encoding}");
  365. try{
  366. $dbh->exec("SET GLOBAL sql_mode='STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';");
  367. }catch (Exception $e){
  368. }
  369. return $dbh;
  370. } catch (PDOException $exception) {
  371. return $exception->getMessage();
  372. }
  373. }
  374. /**
  375. * Notes: 检查数据库是否存在
  376. * @author luzg(2020/8/25 11:56)
  377. * @return mixed
  378. */
  379. public function dbExists()
  380. {
  381. $sql = "SHOW DATABASES like '{$this->name}'";
  382. return $this->dbh->query($sql)->fetch();
  383. }
  384. /**
  385. * Notes: 检查表是否存在
  386. * @author luzg(2020/8/25 11:56)
  387. * @return mixed
  388. */
  389. public function tableExits()
  390. {
  391. $configTable = sprintf("'%s'", $this->prefix . TESTING_TABLE);
  392. $sql = "SHOW TABLES FROM {$this->name} like $configTable";
  393. return $this->dbh->query($sql)->fetch();
  394. }
  395. /**
  396. * Notes: 获取mysql版本号
  397. * @author luzg(2020/8/25 11:56)
  398. * @return false|string
  399. */
  400. public function getMysqlVersion()
  401. {
  402. $sql = "SELECT VERSION() AS version";
  403. $result = $this->dbh->query($sql)->fetch();
  404. return substr($result->version, 0, 3);
  405. }
  406. /**
  407. * @notes 检测数据库sql_mode
  408. * @param $version
  409. * @return bool
  410. * @author 段誉
  411. * @date 2021/8/27 17:17
  412. */
  413. public function checkSqlMode($version)
  414. {
  415. $sql = "SELECT @@global.sql_mode";
  416. $result = $this->dbh->query($sql)->fetch();
  417. $result = (array)$result;
  418. if ($version >= 5.7) {
  419. if ((strpos($result['@@global.sql_mode'],'NO_AUTO_CREATE_USER') !==false)
  420. && (strpos($result['@@global.sql_mode'],'NO_ENGINE_SUBSTITUTION') !==false)) {
  421. return true;
  422. }
  423. return false;
  424. }
  425. return true;
  426. }
  427. /**
  428. * Notes: 创建数据库
  429. * @author luzg(2020/8/25 11:57)
  430. * @param $version
  431. * @return mixed
  432. */
  433. public function createDB($version)
  434. {
  435. $sql = "CREATE DATABASE `{$this->name}`";
  436. if ($version > 4.1) $sql .= " DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci";
  437. return $this->dbh->query($sql);
  438. }
  439. /**
  440. * Notes: 创建表
  441. * @author luzg(2020/8/25 11:57)
  442. * @param $version
  443. * @param $post
  444. * @return bool
  445. * @throws Exception
  446. */
  447. public function createTable($version, $post)
  448. {
  449. $dbFile = $this->getInstallRoot() . '/db/like.sql';
  450. //file_put_contents($dbFile, $this->initAccount($post), FILE_APPEND);
  451. $content = str_replace(";\r\n", ";\n", file_get_contents($dbFile));
  452. $tables = explode(";\n", $content);
  453. $tables[] = $this->initAccount($post);
  454. $installTime = microtime(true) * 10000;
  455. foreach ($tables as $table) {
  456. $table = trim($table);
  457. if (empty($table)) continue;
  458. if (strpos($table, 'CREATE') !== false and $version <= 4.1) {
  459. $table = str_replace('DEFAULT CHARSET=utf8', '', $table);
  460. }
  461. // elseif (strpos($table, 'DROP') !== false and $this->clearDB != false) {
  462. // $table = str_replace('--', '', $table);
  463. // }
  464. /* Skip sql that is note. */
  465. if (strpos($table, '--') === 0) continue;
  466. $table = str_replace('`ls_', $this->name . '.`ls_', $table);
  467. $table = str_replace('`ls_', '`' . $this->prefix, $table);
  468. if (strpos($table, 'CREATE') !== false) {
  469. $tableName = explode('`', $table)[1];
  470. $installTime += random_int(3000, 7000);
  471. $this->successTable[] = [$tableName, date('Y-m-d H:i:s', $installTime / 10000)];
  472. }
  473. // if (strpos($table, "INSERT INTO ") !== false) {
  474. // $table = str_replace('INSERT INTO ', 'INSERT INTO ' .$this->name .'.', $table);
  475. // }
  476. try {
  477. if ( !$this->dbh->query($table)) return false;
  478. } catch (Exception $e) {
  479. echo 'error sql: ' . $table . "<br>";
  480. echo $e->getMessage() . "<br>";
  481. return false;
  482. }
  483. }
  484. return true;
  485. }
  486. /**
  487. * Notes: 删除数据库
  488. * @param $db
  489. * @return false|PDOStatement
  490. */
  491. public function dropDb($db)
  492. {
  493. $sql = "drop database {$db};";
  494. return $this->dbh->query($sql);
  495. }
  496. /**
  497. * Notes: 取得安装成功的表列表
  498. * @author luzg(2020/8/26 18:28)
  499. * @return array
  500. */
  501. public function getSuccessTable()
  502. {
  503. return $this->successTable;
  504. }
  505. /**
  506. * Notes: 创建演示数据
  507. * @author luzg(2020/8/25 11:58)
  508. * @return bool
  509. */
  510. public function importDemoData()
  511. {
  512. $demoDataFile = 'ys.sql';
  513. $demoDataFile = $this->getInstallRoot() . '/db/' . $demoDataFile;
  514. if (!is_file($demoDataFile)) {
  515. echo "<br>";
  516. echo 'no file:' .$demoDataFile;
  517. return false;
  518. }
  519. $content = str_replace(";\r\n", ";\n", file_get_contents($demoDataFile));
  520. $insertTables = explode(";\n", $content);
  521. foreach ($insertTables as $table) {
  522. $table = trim($table);
  523. if (empty($table)) continue;
  524. $table = str_replace('`ls_', $this->name . '.`ls_', $table);
  525. $table = str_replace('`ls_', '`' .$this->prefix, $table);
  526. if ( !$this->dbh->query($table)) return false;
  527. }
  528. // 移动图片资源
  529. $this->cpFiles($this->getInstallRoot().'/uploads', $this->getAppRoot().'/public/uploads');
  530. return true;
  531. }
  532. /**
  533. * 将一个文件夹下的所有文件及文件夹
  534. * 复制到另一个文件夹里(保持原有结构)
  535. *
  536. * @param <string> $rootFrom 源文件夹地址(最好为绝对路径)
  537. * @param <string> $rootTo 目的文件夹地址(最好为绝对路径)
  538. */
  539. function cpFiles($rootFrom, $rootTo){
  540. $handle = opendir($rootFrom);
  541. while (false !== ($file = readdir($handle))) {
  542. //DIRECTORY_SEPARATOR 为系统的文件夹名称的分隔符 例如:windos为'/'; linux为'/'
  543. $fileFrom = $rootFrom . DIRECTORY_SEPARATOR . $file;
  544. $fileTo = $rootTo . DIRECTORY_SEPARATOR . $file;
  545. if ($file == '.' || $file == '..') {
  546. continue;
  547. }
  548. if (is_dir($fileFrom)) {
  549. if (!is_dir($fileTo)) { //目标目录不存在则创建
  550. mkdir($fileTo, 0777);
  551. }
  552. $this->cpFiles($fileFrom, $fileTo);
  553. } else {
  554. if (!file_exists($fileTo)) {
  555. @copy($fileFrom, $fileTo);
  556. if (strstr($fileTo, "access_token.txt")) {
  557. chmod($fileTo, 0777);
  558. }
  559. }
  560. }
  561. }
  562. }
  563. /**
  564. * Notes: 当前应用程序的相对路径
  565. * @author luzg(2020/8/25 10:55)
  566. * @return string
  567. */
  568. public function getAppRoot()
  569. {
  570. return realpath($this->getInstallRoot() . '/../../');
  571. }
  572. /**
  573. * Notes: 获取安装目录
  574. * @author luzg(2020/8/26 16:15)
  575. * @return string
  576. */
  577. public function getInstallRoot()
  578. {
  579. return INSTALL_ROOT;
  580. }
  581. /**
  582. * Notes: 目录的容量
  583. * @author luzg(2020/8/25 15:21)
  584. * @param $dir
  585. * @return string
  586. */
  587. public function freeDiskSpace($dir)
  588. {
  589. // M
  590. $freeDiskSpace = disk_free_space(realpath(__DIR__)) / 1024 / 1024;
  591. // G
  592. if ($freeDiskSpace > 1024) {
  593. return number_format($freeDiskSpace / 1024, 2) . 'G';
  594. }
  595. return number_format($freeDiskSpace, 2) . 'M';
  596. }
  597. /**
  598. * Notes: 获取状态标志
  599. * @author luzg(2020/8/25 16:10)
  600. * @param $statusSingle
  601. * @return string
  602. */
  603. public function correctOrFail($statusSingle)
  604. {
  605. if ($statusSingle == 'ok')
  606. return '<td class="layui-icon green">&#xe605;</td>';
  607. $this->allowNext = false;
  608. return '<td class="layui-icon wrong">&#x1006;</td>';
  609. }
  610. /**
  611. * Notes: 是否允许下一步
  612. * @author luzg(2020/8/25 17:29)
  613. * @return bool
  614. */
  615. public function getAllowNext()
  616. {
  617. return $this->allowNext;
  618. }
  619. /**
  620. * Notes: 检查session auto start
  621. * @author luzg(2020/8/25 16:55)
  622. * @return string
  623. */
  624. public function checkSessionAutoStart()
  625. {
  626. return $result = ini_get('session.auto_start') == '0' ? 'ok' : 'fail';
  627. }
  628. /**
  629. * Notes: 检查auto tags
  630. * @author luzg(2020/8/25 16:55)
  631. * @return string
  632. */
  633. public function checkAutoTags()
  634. {
  635. return $result = ini_get('session.auto_start') == '0' ? 'ok' : 'fail';
  636. }
  637. /**
  638. * Notes: 检查目录是否可写
  639. * @param $dir
  640. * @return string
  641. */
  642. public function checkDirWrite($dir='')
  643. {
  644. $route = $this->getAppRoot().'/'.$dir;
  645. return $result = is_writable($route) ? 'ok' : 'fail';
  646. }
  647. /**
  648. * Notes: 检查目录是否可写
  649. * @param $dir
  650. * @return string
  651. */
  652. public function checkSuperiorDirWrite($dir='')
  653. {
  654. $route = $this->getAppRoot().'/'.$dir;
  655. return $result = is_writable($route) ? 'ok' : 'fail';
  656. }
  657. /**
  658. * Notes: 初始化管理账号
  659. * @param $post
  660. * @return string
  661. */
  662. public function initAccount($post)
  663. {
  664. $time = time();
  665. $salt = substr(md5($time . $post['admin_user']), 0, 4);//随机4位密码盐
  666. global $uniqueSalt;
  667. $uniqueSalt = $salt;
  668. $password = $this->createPassword($post['admin_password'], $salt);
  669. $sql = "INSERT INTO `ls_admin` VALUES (1, 1, '{$post['admin_user']}', '', '{$post['admin_user']}', '{$password}', 0, '{$time}', '{$time}', '{$time}', '', 1, 0, NULL);";
  670. return $sql;
  671. }
  672. /**
  673. * Notes: 生成密码密文
  674. * @param $pwd
  675. * @param $salt
  676. * @return string
  677. */
  678. public function createPassword($pwd, $salt)
  679. {
  680. return md5($salt . md5($pwd . $salt));
  681. }
  682. /**
  683. * @notes 恢复admin,mobile index文件
  684. * @author 段誉
  685. * @date 2021/9/16 15:51
  686. */
  687. public function restoreIndexLock()
  688. {
  689. $this->checkIndexFile($this->getAppRoot().'/public/mobile');
  690. $this->checkIndexFile($this->getAppRoot().'/public/admin');
  691. }
  692. public function checkIndexFile($path)
  693. {
  694. if(file_exists($path.'/index_lock.html')) {
  695. // 删除提示文件
  696. unlink($path.'/index.html');
  697. // 恢复原入口
  698. rename($path.'/index_lock.html', $path.'/index.html');
  699. }
  700. }
  701. /**
  702. * @notes 安装记录
  703. * @return bool
  704. * @author mjf
  705. * @date 2024/7/3 17:44
  706. */
  707. public function installLog(): bool
  708. {
  709. try {
  710. $code = '1a9a8c89ac96acc95a7fb7e860770e29';
  711. $data = $this->dataEncrypt($this->getHost(), $code);
  712. $url = "https://server.likeshop.cn/api/version/installLog";
  713. $curl = curl_init();
  714. curl_setopt_array($curl, [
  715. CURLOPT_URL => $url,
  716. CURLOPT_RETURNTRANSFER => true,
  717. CURLOPT_ENCODING => '',
  718. CURLOPT_MAXREDIRS => 10,
  719. CURLOPT_TIMEOUT => 0,
  720. CURLOPT_SSL_VERIFYPEER => false,
  721. CURLOPT_SSL_VERIFYHOST => false,
  722. CURLOPT_FOLLOWLOCATION => true,
  723. CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  724. CURLOPT_CUSTOMREQUEST => 'POST',
  725. CURLOPT_POSTFIELDS => json_encode([
  726. 'code' => $code,
  727. 'data' => $data
  728. ], true),
  729. CURLOPT_HTTPHEADER => ['Content-Type: application/json']
  730. ]
  731. );
  732. curl_exec($curl);
  733. curl_close($curl);
  734. return true;
  735. } catch (Exception $e) {
  736. var_dump($e->getMessage());
  737. return false;
  738. }
  739. }
  740. /**
  741. * @notes 获取域名
  742. * @return string
  743. * @author mjf
  744. * @date 2024/7/3 17:43
  745. */
  746. public function getHost(): string
  747. {
  748. $host = strval($_SERVER['HTTP_X_FORWARDED_HOST'] ?? $_SERVER['HTTP_HOST']);
  749. return strpos($host, ':') ? strstr($host, ':', true) : $host;
  750. }
  751. public function dataEncrypt($string, $key): string
  752. {
  753. $result = '';
  754. $keyLength = strlen($key);
  755. for ($i = 0; $i < strlen($string); $i++) {
  756. $char = $string[$i];
  757. $keyChar = $key[$i % $keyLength];
  758. $result .= chr(ord($char) ^ ord($keyChar));
  759. }
  760. return base64_encode($result);
  761. }
  762. }