mirror of
https://github.com/flucont/btcloud.git
synced 2025-10-14 14:20:22 +00:00
Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
9438c64796 | ||
![]() |
acb842a883 | ||
![]() |
6785d259f6 | ||
![]() |
04560cd70c | ||
![]() |
ecfe3c9e20 | ||
![]() |
d8de902f1b | ||
![]() |
fdbbd304cb | ||
![]() |
53a484093e | ||
![]() |
7010d79ca1 | ||
![]() |
99f9a28a73 | ||
![]() |
4c05974f09 | ||
![]() |
27a7281101 | ||
![]() |
c6a9fccc1c | ||
![]() |
0a9e5c3b92 |
130
README.md
130
README.md
@@ -1,64 +1,66 @@
|
||||
# 宝塔面板第三方云端
|
||||
这是一个用php开发的宝塔面板第三方云端站点程序。
|
||||
|
||||
你可以使用此程序搭建属于自己的宝塔面板第三方云端,实现最新版宝塔面板私有化部署,不与宝塔官方接口通信,满足隐私安全合规需求。同时还可以去除面板强制绑定账号,DIY面板功能等。
|
||||
|
||||
网站后台管理可一键同步宝塔官方的插件列表与增量更新插件包,还有云端使用记录、IP黑白名单、操作日志、定时任务等功能。
|
||||
|
||||
本项目自带的宝塔安装包和更新包是8.0.x最新版,已修改适配此第三方云端,并且全开源,无so等加密文件。
|
||||
|
||||
觉得该项目不错的可以给个Star~
|
||||
|
||||
## 声明
|
||||
|
||||
1.此项目只能以自用为目的,不得侵犯堡塔公司及其他第三方的知识产权和其他合法权利。
|
||||
|
||||
2.搭建使用此项目必须有一定的编程和Linux运维基础,纯小白不建议使用。
|
||||
|
||||
## 环境要求
|
||||
|
||||
* `PHP` >= 7.4
|
||||
* `MySQL` >= 5.6
|
||||
* `fileinfo`扩展
|
||||
* `ZipArchive`扩展
|
||||
|
||||
## 部署方法
|
||||
|
||||
- [下载最新版的Release包](https://github.com/flucont/btcloud/releases)
|
||||
- 如果是下载的源码包,需要执行 `composer install --no-dev` 安装依赖,如果是下载的Release包,则不需要
|
||||
- 设置网站运行目录为`public`
|
||||
- 设置伪静态为`ThinkPHP`
|
||||
- 访问网站,会自动跳转到安装页面,根据提示安装完成
|
||||
|
||||
## 使用方法
|
||||
|
||||
- 在`批量替换工具`,执行页面显示的命令,可将bt安装包、更新包和脚本文件里面的`http://www.example.com`批量替换成当前网站的网址。
|
||||
- 在`系统基本设置`修改宝塔面板接口设置。你需要准备一个使用官方最新脚本安装并绑定账号的宝塔面板,用于获取最新插件列表及插件包。并根据界面提示安装好专用插件。
|
||||
- 在`定时任务设置`执行所显示的命令从宝塔官方获取最新的插件列表并批量下载插件包(增量更新)。当然你也可以去插件列表,一个一个点击下载。
|
||||
- 访问网站`/download`查看使用此第三方云端的一键安装脚本。
|
||||
|
||||
## 更新方法
|
||||
|
||||
- [下载最新版的Release包](https://github.com/flucont/btcloud/releases)
|
||||
- 上传覆盖除data文件夹以外的全部文件
|
||||
- 后台使用批量替换工具->获取最新插件列表->修改Linux面板等版本号
|
||||
|
||||
## 其他
|
||||
|
||||
- [Linux面板官方更新包修改记录](./wiki/update.md)
|
||||
|
||||
- [Windows面板官方更新包修改记录](./wiki/updatewin.md)
|
||||
|
||||
- [宝塔云监控安装包修改记录](./wiki/btmonitor.md)
|
||||
|
||||
- 宝塔面板官方版与此第三方云端版对比:
|
||||
|
||||
| | 官方版 | 此第三方云端版 |
|
||||
| ---------- | ------------------------------------------------------------ | -------------------------------------------------- |
|
||||
| 版本更新 | 支持 | 支持 |
|
||||
| 面板广告 | 有广告 | 无广告 |
|
||||
| 是否全开源 | 没有全开源 | 全开源 |
|
||||
| 资源占用 | 各种统计上报等任务,资源占用略高 | 去除了很多无用的定时任务,资源占较少 |
|
||||
| 兼容性 | 由于编译的so文件有系统架构限制,兼容的系统仅限已编译的so对应的系统架构 | 由于全开源,没有已编译的so文件,因此无系统架构限制 |
|
||||
|
||||
|
||||
# 宝塔面板第三方云端
|
||||
这是一个用php开发的宝塔面板第三方云端站点程序。
|
||||
|
||||
你可以使用此程序搭建属于自己的宝塔面板第三方云端,实现最新版宝塔面板私有化部署,不与宝塔官方接口通信,满足隐私安全合规需求。同时还可以去除面板强制绑定账号,DIY面板功能等。
|
||||
|
||||
网站后台管理可一键同步宝塔官方的插件列表与增量更新插件包,还有云端使用记录、IP黑白名单、操作日志、定时任务等功能。
|
||||
|
||||
本项目自带 **宝塔Linux面板**、**宝塔Windows面板**、**aaPanel面板**、**宝塔云监控** 的最新版安装包和更新包,已修改适配此第三方云端,并且全开源,无.so等加密文件。
|
||||
|
||||
觉得该项目不错的可以给个Star~
|
||||
|
||||
## 声明
|
||||
|
||||
1.此项目只能以自用为目的,不得侵犯堡塔公司及其他第三方的知识产权和其他合法权利。
|
||||
|
||||
2.搭建使用此项目必须有一定的编程和Linux运维基础,纯小白不建议使用。
|
||||
|
||||
## 环境要求
|
||||
|
||||
* `PHP` >= 7.4
|
||||
* `MySQL` >= 5.6
|
||||
* `fileinfo`扩展
|
||||
* `ZipArchive`扩展
|
||||
|
||||
## 部署方法
|
||||
|
||||
- [下载最新版的Release包](https://github.com/flucont/btcloud/releases)
|
||||
- 如果是下载的源码包,需要执行 `composer install --no-dev` 安装依赖,如果是下载的Release包,则不需要
|
||||
- 设置网站运行目录为`public`
|
||||
- 设置伪静态为`ThinkPHP`
|
||||
- 访问网站,会自动跳转到安装页面,根据提示安装完成
|
||||
|
||||
## 使用方法
|
||||
|
||||
- 在`批量替换工具`,执行页面显示的命令,可将bt安装包、更新包和脚本文件里面的`http://www.example.com`批量替换成当前网站的网址。
|
||||
- 在`系统基本设置`修改宝塔面板接口设置。你需要准备一个使用官方最新脚本安装并绑定账号的宝塔面板,用于获取最新插件列表及插件包。并根据界面提示安装好专用插件。
|
||||
- 在`定时任务设置`执行所显示的命令从宝塔官方获取最新的插件列表并批量下载插件包(增量更新)。当然你也可以去插件列表,一个一个点击下载。
|
||||
- 访问网站`/download`查看使用此第三方云端的一键安装脚本。
|
||||
|
||||
## 更新方法
|
||||
|
||||
- [下载最新版的Release包](https://github.com/flucont/btcloud/releases)
|
||||
- 上传覆盖除data文件夹以外的全部文件
|
||||
- 后台使用批量替换工具->获取最新插件列表->修改软件版本设置里面的版本号
|
||||
|
||||
## 其他
|
||||
|
||||
- [Linux面板官方更新包修改记录](./wiki/update.md)
|
||||
|
||||
- [Windows面板官方更新包修改记录](./wiki/updatewin.md)
|
||||
|
||||
- [aaPanel面板官方更新包修改记录](./wiki/aapanel.md)
|
||||
|
||||
- [宝塔云监控安装包修改记录](./wiki/btmonitor.md)
|
||||
|
||||
- 宝塔面板官方版与此第三方云端版对比:
|
||||
|
||||
| | 官方版 | 此第三方云端版 |
|
||||
| ---------- | ------------------------------------------------------------ | -------------------------------------------------- |
|
||||
| 版本更新 | 支持 | 支持 |
|
||||
| 面板广告 | 有广告 | 无广告 |
|
||||
| 是否全开源 | 没有全开源 | 全开源 |
|
||||
| 资源占用 | 各种统计上报等任务,资源占用略高 | 去除了很多无用的定时任务,资源占较少 |
|
||||
| 兼容性 | 由于编译的so文件有系统架构限制,兼容的系统仅限已编译的so对应的系统架构 | 由于全开源,没有已编译的so文件,因此无系统架构限制 |
|
||||
|
||||
|
||||
|
@@ -67,7 +67,7 @@ class CleanViteJs extends Command
|
||||
$end = $start + strlen($code);
|
||||
for($i=$start;$i>=0;$i--){
|
||||
$char = substr($content,$i,1);
|
||||
if(!ctype_alpha($char)){
|
||||
if(!ctype_alpha($char)&&$char!='_'){
|
||||
$start = $i+1;
|
||||
break;
|
||||
}
|
||||
@@ -108,18 +108,20 @@ class CleanViteJs extends Command
|
||||
|
||||
if(strpos($file, 'window.location.protocol.indexOf("https")>=0')!==false){ //index
|
||||
$file = str_replace('(window.location.protocol.indexOf("https")>=0)', '1', $file);
|
||||
$file = preg_replace('!setTimeout\(\(\(\)=>\{\w+\(\)\}\),3e3\)!', '', $file);
|
||||
$file = preg_replace('!setTimeout\(\(function\(\)\{\w+\(\)\}\),3e3\)!', '', $file);
|
||||
$file = preg_replace('!recommendShow:\w+,!', 'recommendShow:!1,', $file);
|
||||
$code = $this->getExtendCode($file, '"需求反馈"', 2);
|
||||
$code = $this->getExtendCode($file, 'isGetCoupon:', 2);
|
||||
if($code){
|
||||
$file = str_replace($code, '{}', $file);
|
||||
}
|
||||
$file = preg_replace('!recommendShow:\w+,!', 'recommendShow:!1,', $file, 1);
|
||||
$code = $this->getExtendCode($file, '"需求反馈"', 1, '[', ']');
|
||||
if($code){
|
||||
$file = str_replace($code, '[]', $file);
|
||||
}
|
||||
$flag = true;
|
||||
}
|
||||
|
||||
if(strpos($file, '"WechatOfficial"')!==false){ //main
|
||||
$code = $this->getExtendCode($file, '"WechatOfficial"', 5);
|
||||
if(strpos($file, '论坛求助')!==false){ //main
|
||||
$code = $this->getExtendCode($file, '"微信公众号"', 1);
|
||||
$code = $this->getExtendFunction($file, $code);
|
||||
$start = strpos($file, $code) - 1;
|
||||
for($i=$start;$i>=0;$i--){
|
||||
@@ -128,37 +130,48 @@ class CleanViteJs extends Command
|
||||
break;
|
||||
}
|
||||
}
|
||||
$code = $this->getExtendCode($file, '"/other/customer-service.png"', 2);
|
||||
$code = $this->getExtendCode($file, $code, 2, '[', ']');
|
||||
$code = $this->getExtendCode($file, '"/other/customer-qrcode.png"', 2);
|
||||
$code = $this->getExtendFunction($file, $code);
|
||||
$end = strpos($file, $code)+strlen($code);
|
||||
$code = substr($file, $start, $end - $start + 1);
|
||||
$code = substr($file, $start, $end - $start);
|
||||
$file = str_replace($code, '', $file);
|
||||
$file = str_replace('startNegotiate(),', '', $file);
|
||||
$flag = true;
|
||||
}
|
||||
|
||||
if(strpos($file, '"calc"') !== false && strpos($file, '"checkConfirm"') !== false){ //main2
|
||||
$file = preg_replace('!,isCalc:\w+,isInput:\w+,!', ',isCalc:!1,isInput:!1,', $file);
|
||||
$file = preg_replace('!"calc"===\w+\.type!', '!1', $file);
|
||||
$file = preg_replace('!\w+\(\(\(\)=>"input"===\w+\.type\)\)!', '!1', $file);
|
||||
$file = preg_replace('!\w+\(\(function\(\)\{return"input"===\w+\.type\}\)\)!', '!1', $file);
|
||||
$flag = true;
|
||||
}
|
||||
|
||||
if(strpos($file, '请冷静几秒钟,确认以下要删除的数据')!==false && strpos($file, '"计算结果:"')!==false){ //site
|
||||
$code = $this->getExtendCode($file, '"计算结果:"', 2, '[', ']');
|
||||
$code = $this->getExtendFunction($file, $code);
|
||||
$file = str_replace($code, '', $file);
|
||||
$file = preg_replace('!\w+\.sum===\w+\.addend1\+\w+\.addend2!', '!0', $file);
|
||||
$file = preg_replace('!\w+\.sum\!==\w+\.addend1\+\w+\.addend2!', '!1', $file);
|
||||
$file = preg_replace('!,disableDeleteButton:\w+,countdown:\w+,!', ',disableDeleteButton:!1,countdown:!1,', $file);
|
||||
if(preg_match('/startCountdown:(\w+),/', $file, $matchs)){
|
||||
$file = str_replace([';'.$matchs[1].'()', $matchs[1].'(),'], '', $file);
|
||||
if(strpos($file, 'useNegotiate')!==false){ //utils
|
||||
$code = $this->getExtendCode($file, 'createPeerConnection()', 1);
|
||||
if($code){
|
||||
$file = str_replace($code, '{}', $file);
|
||||
}
|
||||
$file = preg_replace('!\w+\(\(\(\)=>"calc"===\w+\.\w+\.type\)\)!', '!1', $file);
|
||||
$file = preg_replace('!\w+\(\(\(\)=>"input"===\w+\.\w+\.type\)\)!', '!1', $file);
|
||||
$file = preg_replace('!\w+\(\(function\(\)\{return"calc"===\w+\.\w+\.type\}\)\)!', '!1', $file);
|
||||
$file = preg_replace('!\w+\(\(function\(\)\{return"input"===\w+\.\w+\.type\}\)\)!', '!1', $file);
|
||||
$code = $this->getExtendCode($file, '"自动部署"', 2);
|
||||
if($code){
|
||||
$file = str_replace($code, '', $file);
|
||||
}
|
||||
$flag = true;
|
||||
}
|
||||
|
||||
if(strpos($file, 'svgtofont-left-waf')!==false){ //site.table
|
||||
if(strpos($file, '请冷静几秒钟,确认以下要删除的数据')!==false && strpos($file, '"计算结果:"')!==false){ //site
|
||||
$code = $this->getExtendCode($file, '"计算结果:"', 1, '[', ']');
|
||||
$code = $this->getExtendFunction($file, $code);
|
||||
$file = str_replace($code, '', $file);
|
||||
$file = preg_replace('!\w+\.sum===\w+\.addend1\+\w+\.addend2!', '!0', $file);
|
||||
$file = preg_replace('!value=\!0,(\w+)\.value=5;!', 'value=!1,$1.value=0;', $file);
|
||||
$flag = true;
|
||||
}
|
||||
|
||||
if(strpos($file, '"left-waf"')!==false && strpos($file, '"iconWaf"')!==false){ //site.table
|
||||
$code = $this->getExtendCode($file, '"left-waf"');
|
||||
$code = $this->getExtendCode($file, $code, 1, '[', ']');
|
||||
$code = $this->getExtendFunction($file, $code);
|
||||
$file = str_replace($code, '""', $file);
|
||||
$flag = true;
|
||||
}
|
||||
|
||||
if(strpos($file, 'svgtofont-left-waf')!==false && strpos($file, '"iconWaf"')!==false){ //site.table
|
||||
$code = $this->getExtendCode($file, 'svgtofont-left-waf');
|
||||
$code = $this->getExtendCode($file, $code, 1, '[', ']');
|
||||
$code = $this->getExtendFunction($file, $code);
|
||||
@@ -171,9 +184,36 @@ class CleanViteJs extends Command
|
||||
$file = str_replace($code, '', $file);
|
||||
$code = $this->getExtendFunction($file, '"测试证书"', '{', '}');
|
||||
$file = str_replace($code, '', $file);
|
||||
$file = str_replace('"currentCertInfo":"busSslList"', '"currentCertInfo":"currentCertInfo"', $file);
|
||||
$file = preg_replace('!\{(\w+)\.value="busSslList",\w+\(\)\}!', '{$1.value="letsEncryptList"}', $file);
|
||||
$file = preg_replace('!defaultActive:(\w+)\("sslCertificate"\)!', 'defaultActive:$1("EncryptCertificate")', $file);
|
||||
$code = $this->getExtendCode($file, '"购买商业证书"', 2);
|
||||
if($code){
|
||||
$code2 = str_replace('"busSslList"', '"letsEncryptList"', $code);
|
||||
$code2 = str_replace($this->getExtendFunction($code, '"购买商业证书"'), '', $code2);
|
||||
$file = str_replace($code, $code2, $file);
|
||||
}
|
||||
$file = preg_replace('!(\w+)\("sslCertificate"\)!', '$1("EncryptCertificate")', $file);
|
||||
$flag = true;
|
||||
}
|
||||
if(strpos($file, '"busSslList"')!==false && strpos($filepath, '/useStore')){ //site-ssl
|
||||
$file = str_replace('"busSslList"', '"currentCertInfo"', $file);
|
||||
$flag = true;
|
||||
}
|
||||
|
||||
if(strpos($file, '"商用SSL"')!==false){ //ssl
|
||||
$code = $this->getExtendFunction($file, '"商用SSL"', '{', '}');
|
||||
$file = str_replace($code, '', $file);
|
||||
$code = $this->getExtendFunction($file, '"测试证书"', '{', '}');
|
||||
$file = str_replace($code, '', $file);
|
||||
$code = $this->getExtendCode($file, ',"联系客服"', 2, '[', ']');
|
||||
if($code){
|
||||
$file = str_replace($code, '[]', $file);
|
||||
}
|
||||
$code = $this->getExtendCode($file, ',"联系客服"', 2, '[', ']');
|
||||
if($code){
|
||||
$file = str_replace($code, '[]', $file);
|
||||
}
|
||||
}
|
||||
if(strpos($file, '"SSL-CERTIFICATE-STORE"')!==false){ //ssl
|
||||
$file = str_replace('("ssl")', '("encrypt")', $file);
|
||||
$flag = true;
|
||||
}
|
||||
|
||||
@@ -185,54 +225,102 @@ class CleanViteJs extends Command
|
||||
}
|
||||
|
||||
if(strpos($file, '"recom-view"')!==false){ //soft
|
||||
$code = $this->getExtendFunction($file, '"recom-view"');
|
||||
$file = str_replace($code, 'void(0)', $file);
|
||||
$code = $this->getExtendCode($file, '"recom-view"');
|
||||
$code = $this->getExtendFunction($file, $code);
|
||||
$file = str_replace($code, '', $file);
|
||||
$flag = true;
|
||||
}
|
||||
|
||||
if(strpos($file, '"打开插件文件目录"')!==false){ //soft.table
|
||||
$code = $this->getExtendFunction($file, '"(续费)"');
|
||||
$file = str_replace($code, '""', $file);
|
||||
$code = $this->getExtendFunction($file, '"(续费)"');
|
||||
$file = str_replace($code, '""', $file);
|
||||
$flag = true;
|
||||
}
|
||||
|
||||
if(strpos($file, '检测到同名文件')!==false){ //file.
|
||||
$code = $this->getExtendCode($file, '计算结果:', 3, '[', ']');
|
||||
$code = $this->getExtendFunction($file, $code);
|
||||
$file = str_replace($code, '', $file);
|
||||
$file = preg_replace('!\w+\.sum===\w+\.addend1\+\w+\.addend2!', '!0', $file);
|
||||
$flag = true;
|
||||
}
|
||||
|
||||
for($i=0;$i<5;$i++){
|
||||
$code = $this->getExtendCode($file, 'content:"需求反馈"', 2);
|
||||
$code = $this->getExtendCode($file, ',"需求反馈"', 1, '[', ']');
|
||||
if($code){
|
||||
$code = $this->getExtendFunction($file, $code);
|
||||
$start = strpos($file, $code);
|
||||
if(substr($file,$start-1,1) == ':'){
|
||||
$file = $this->str_replace_once($code, '{}', $file);
|
||||
if(strpos($code, 'svgtofont-desired')){
|
||||
$file = str_replace($code, '[]', $file);
|
||||
}else{
|
||||
$file = $this->str_replace_once($code, '', $file);
|
||||
$code = $this->getExtendFunction($code, ',"需求反馈"');
|
||||
$file = str_replace($code, '', $file);
|
||||
}
|
||||
$flag = true;
|
||||
}
|
||||
}
|
||||
$code = $this->getExtendFunction($file, '("需求反馈")');
|
||||
if($code){
|
||||
$file = str_replace($code, '', $file);
|
||||
$flag = true;
|
||||
}
|
||||
$code = $this->getExtendFunction($file, '(" 需求反馈 ")');
|
||||
$code = $this->getExtendCode($file, '("需求反馈")', 1, '[', ']');
|
||||
if($code){
|
||||
$file = str_replace($code, '[]', $file);
|
||||
$flag = true;
|
||||
}
|
||||
$code = $this->getExtendCode($file, '(" 需求反馈 ")', 1, '[', ']');
|
||||
if($code && strpos($filepath, 'vue_vue_type_') === false){
|
||||
$file = str_replace($code, '[]', $file);
|
||||
$flag = true;
|
||||
}
|
||||
$code = $this->getExtendFunction($file, 'label:"需求反馈",', '{', '}');
|
||||
if($code){
|
||||
$file = str_replace($code, '', $file);
|
||||
$flag = true;
|
||||
}
|
||||
|
||||
if(strpos('暂无搜索结果,<span class="text-primary cursor-pointer NpsDialog">提交需求反馈</span>', $file)!==false){
|
||||
$file = str_replace('暂无搜索结果,<span class="text-primary cursor-pointer NpsDialog">提交需求反馈</span>', '暂无搜索结果', $file);
|
||||
$flag = true;
|
||||
}
|
||||
|
||||
if(strpos($file, 'getReceiveCoupon()')!==false){ //aapanel-优惠券
|
||||
$code = $this->getExtendCode($file, 'getReceiveCoupon()');
|
||||
$file = str_replace($code, '{}', $file);
|
||||
$flag = true;
|
||||
}
|
||||
|
||||
if(strpos($file, '"Site.DelSite.index_1"')!==false){ //aapanel-site
|
||||
$code = $this->getExtendCode($file, '"Site.DelSite.index_10"', 3, '(', ')');
|
||||
if($code){
|
||||
$code = $this->getExtendFunction($file, $code);
|
||||
$file = str_replace($code, '', $file);
|
||||
$file = preg_replace('@\w+\.value!==\w+\.value\+\w+\.value@', '!1', $file);
|
||||
$file = preg_replace('@null==\w+\.value\|\|null==\w+\.value@', '!1', $file);
|
||||
$file = str_replace('disabled:!0', 'disabled:!1', $file);
|
||||
$flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(strpos($file, '"Component.Confirm.index_4"')!==false){ //aapanel-public
|
||||
$code = $this->getExtendCode($file, '"Component.Confirm.index_4"', 2, '(', ')');
|
||||
if($code){
|
||||
$code = $this->getExtendFunction($file, $code);
|
||||
$file = str_replace($code, '', $file);
|
||||
$file = preg_replace('@\w+\.value===\w+\.value\+\w+\.value@', '!0', $file);
|
||||
$flag = true;
|
||||
}
|
||||
$code = $this->getExtendCode($file, '"Component.Confirm.index_1"', 1, '(', ')');
|
||||
if($code){
|
||||
$code = $this->getExtendFunction($file, $code);
|
||||
$file = str_replace($code, '', $file);
|
||||
$file = preg_replace('@\w+\.value===\w+\.value\?@', '!0?', $file);
|
||||
$flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(strpos($file, '"Component.Feedback.index_7"')!==false){ //aapanel-需求反馈
|
||||
$code = $this->getExtendCode($file, '"Component.Feedback.index_7"', 2);
|
||||
if($code){
|
||||
$code = $this->getExtendFunction($file, $code);
|
||||
$file = str_replace($code, '', $file);
|
||||
$flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(strpos($file, '"Soft.index_16"')!==false){ //aapanel-soft
|
||||
$code = $this->getExtendCode($file, '"Soft.index_16"', 2);
|
||||
if($code){
|
||||
$file = str_replace($code, '{}', $file);
|
||||
$flag = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(!$flag) return;
|
||||
if(file_put_contents($filepath, $file)){
|
||||
|
@@ -45,37 +45,34 @@ class DecryptFile extends Command
|
||||
$output->writeln($e->getMessage());
|
||||
}
|
||||
}elseif($type == 'module'){
|
||||
try{
|
||||
$res = Plugins::decode_module_file($file);
|
||||
if($res == 2){
|
||||
$output->writeln('文件解密失败!');
|
||||
}elseif($res == 1){
|
||||
$output->writeln('文件解密成功!');
|
||||
}
|
||||
}catch(\Exception $e){
|
||||
$output->writeln($e->getMessage());
|
||||
}
|
||||
$this->decode_module_file($output, $file);
|
||||
}elseif($type == 'classdir'){
|
||||
$file = rtrim($file, '/');
|
||||
if(!file_exists($file.'/common.py')){
|
||||
if(file_exists($file.'/common.py')){
|
||||
$class_v = 1;
|
||||
}elseif(file_exists($file.'/common_v2.py')){
|
||||
$class_v = 2;
|
||||
}else{
|
||||
$output->writeln('当前路径非宝塔面板class目录');
|
||||
return;
|
||||
}
|
||||
$dirs = glob($file.'/*Model');
|
||||
$dirs = glob($file.'/*Model'.($class_v == 2 ? 'V2' : ''));
|
||||
foreach($dirs as $dir){
|
||||
if(!is_dir($dir))continue;
|
||||
$files = glob($dir.'/*Model.py');
|
||||
foreach($files as $file){
|
||||
try{
|
||||
$res = Plugins::decode_module_file($file);
|
||||
if($res == 2){
|
||||
$output->writeln('文件解密失败:'.$file);
|
||||
}elseif($res == 1){
|
||||
$output->writeln('文件解密成功:'.$file);
|
||||
}
|
||||
}catch(\Exception $e){
|
||||
$output->writeln($e->getMessage().':'.$file);
|
||||
}
|
||||
foreach($files as $filepath){
|
||||
$this->decode_module_file($output, $filepath);
|
||||
}
|
||||
}
|
||||
if($class_v == 2){
|
||||
$filepath = $file.'/wp_toolkit/core.py';
|
||||
if(file_exists($filepath)){
|
||||
$this->decode_module_file($output, $filepath);
|
||||
}
|
||||
}else{
|
||||
$filepath = $file.'/public/authorization.py';
|
||||
if(file_exists($filepath)){
|
||||
$this->decode_module_file($output, $filepath);
|
||||
}
|
||||
}
|
||||
}elseif($type == 'all'){
|
||||
@@ -95,21 +92,24 @@ class DecryptFile extends Command
|
||||
$this->scan_all_file($input, $output, $filepath);
|
||||
}
|
||||
elseif(substr($filepath, -3) == '.py') {
|
||||
try{
|
||||
$res = Plugins::decode_module_file($filepath);
|
||||
if($res == 2){
|
||||
$output->writeln('文件解密失败:'.$filepath);
|
||||
}elseif($res == 1){
|
||||
$output->writeln('文件解密成功:'.$filepath);
|
||||
}
|
||||
}catch(\Exception $e){
|
||||
$output->writeln($e->getMessage().':'.$filepath);
|
||||
}
|
||||
$this->decode_module_file($output, $filepath);
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir($dir);
|
||||
}
|
||||
|
||||
private function decode_module_file(Output $output, $filepath){
|
||||
try{
|
||||
$res = Plugins::decode_module_file($filepath);
|
||||
if($res == 2){
|
||||
$output->writeln('文件解密失败:'.$filepath);
|
||||
}elseif($res == 1){
|
||||
$output->writeln('文件解密成功:'.$filepath);
|
||||
}
|
||||
}catch(\Exception $e){
|
||||
$output->writeln($e->getMessage().':'.$filepath);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -31,6 +31,9 @@ class UpdateAll extends Command
|
||||
if(!config_get('wbt_type') && config_get('wbt_url') || config_get('wbt_type')==1 && config_get('wbt_surl')){
|
||||
$this->process_plugins($input, $output, 'Windows');
|
||||
}
|
||||
if(!config_get('enbt_type') && config_get('enbt_url') || config_get('enbt_type')==1 && config_get('enbt_surl')){
|
||||
$this->process_plugins($input, $output, 'en');
|
||||
}
|
||||
|
||||
config_set('runtime', date('Y-m-d H:i:s'));
|
||||
}
|
||||
@@ -43,7 +46,13 @@ class UpdateAll extends Command
|
||||
|
||||
$count = 0;
|
||||
|
||||
$type = intval(config_get($os=='Windows'?'updateall_type_win':'updateall_type'));
|
||||
if($os=='Windows'){
|
||||
$type = intval(config_get('updateall_type_win'));
|
||||
}elseif($os=='en'){
|
||||
$type = intval(config_get('updateall_type_en'));
|
||||
}else{
|
||||
$type = intval(config_get('updateall_type'));
|
||||
}
|
||||
|
||||
$json_arr = Plugins::get_plugin_list($os);
|
||||
//循环下载缺少的插件
|
||||
|
@@ -3,7 +3,13 @@
|
||||
use think\facade\Db;
|
||||
|
||||
function get_data_dir($os = 'Linux'){
|
||||
return app()->getRootPath().'data/'.($os == 'Windows' ? 'win/' : '');
|
||||
if($os == 'en'){
|
||||
return app()->getRootPath().'data/en/';
|
||||
}elseif($os == 'Windows'){
|
||||
return app()->getRootPath().'data/win/';
|
||||
}else{
|
||||
return app()->getRootPath().'data/';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@@ -151,7 +151,7 @@ class Admin extends BaseController
|
||||
if($result && isset($result['username'])){
|
||||
return json(['code'=>0, 'msg'=>'面板连接测试成功!']);
|
||||
}else{
|
||||
return json(['code'=>-1, 'msg'=>'面板连接测试成功,但未安装专用插件']);
|
||||
return json(['code'=>-1, 'msg'=>'面板连接测试成功,但未安装专用插件/未登录账号']);
|
||||
}
|
||||
}else{
|
||||
return json(['code'=>-1, 'msg'=>isset($result['msg'])?$result['msg']:'面板地址无法连接']);
|
||||
@@ -185,6 +185,19 @@ class Admin extends BaseController
|
||||
return view();
|
||||
}
|
||||
|
||||
public function pluginsen(){
|
||||
$typelist = [];
|
||||
$json_arr = Plugins::get_plugin_list('en');
|
||||
if($json_arr){
|
||||
foreach($json_arr['type'] as $type){
|
||||
if($type['title'] == '一键部署') continue;
|
||||
$typelist[$type['id']] = $type['title'];
|
||||
}
|
||||
}
|
||||
View::assign('typelist', $typelist);
|
||||
return view();
|
||||
}
|
||||
|
||||
public function plugins_data(){
|
||||
$type = input('post.type/d');
|
||||
$keyword = input('post.keyword', null, 'trim');
|
||||
@@ -226,7 +239,7 @@ class Admin extends BaseController
|
||||
'name' => $plugin['name'],
|
||||
'title' => $plugin['title'],
|
||||
'type' => $plugin['type'],
|
||||
'typename' => $typelist[$plugin['type']],
|
||||
'typename' => isset($typelist[$plugin['type']]) ? $typelist[$plugin['type']] : '未知',
|
||||
'desc' => str_replace('target="_blank"','target="_blank" rel="noopener noreferrer"',$plugin['ps']),
|
||||
'price' => $plugin['price'],
|
||||
'author' => isset($plugin['author']) ? $plugin['author'] : '官方',
|
||||
|
@@ -36,6 +36,20 @@ class Api extends BaseController
|
||||
return json($json_arr);
|
||||
}
|
||||
|
||||
//获取插件列表(aapanel)
|
||||
public function get_plugin_list_en(){
|
||||
if(!$this->checklist()) return json('你的服务器被禁止使用此云端');
|
||||
$record = Db::name('record')->where('ip',$this->clientip)->find();
|
||||
if($record){
|
||||
Db::name('record')->where('id',$record['id'])->update(['usetime'=>date("Y-m-d H:i:s")]);
|
||||
}else{
|
||||
Db::name('record')->insert(['ip'=>$this->clientip, 'addtime'=>date("Y-m-d H:i:s"), 'usetime'=>date("Y-m-d H:i:s")]);
|
||||
}
|
||||
$json_arr = Plugins::get_plugin_list('en');
|
||||
if(!$json_arr) return json((object)[]);
|
||||
return json($json_arr);
|
||||
}
|
||||
|
||||
//下载插件包
|
||||
public function download_plugin(){
|
||||
$plugin_name = input('post.name');
|
||||
@@ -58,6 +72,26 @@ class Api extends BaseController
|
||||
}
|
||||
}
|
||||
|
||||
//下载插件包aapanel
|
||||
public function download_plugin_en(){
|
||||
$plugin_name = input('post.name');
|
||||
$version = input('post.version');
|
||||
if(!$plugin_name || !$version){
|
||||
return '参数不能为空';
|
||||
}
|
||||
if(!preg_match('/^[a-zA-Z0-9_]+$/', $plugin_name) || !preg_match('/^[0-9.]+$/', $version)){
|
||||
return '参数不正确';
|
||||
}
|
||||
if(!$this->checklist()) return '你的服务器被禁止使用此云端';
|
||||
$filepath = get_data_dir('en').'plugins/package/'.$plugin_name.'-'.$version.'.zip';
|
||||
if(file_exists($filepath)){
|
||||
$filename = $plugin_name.'.zip';
|
||||
$this->output_file($filepath, $filename);
|
||||
}else{
|
||||
return '云端不存在该插件包';
|
||||
}
|
||||
}
|
||||
|
||||
//下载插件主文件
|
||||
public function download_plugin_main(){
|
||||
$plugin_name = input('post.name');
|
||||
@@ -92,7 +126,10 @@ class Api extends BaseController
|
||||
public function download_plugin_other(){
|
||||
$fname = input('get.fname');
|
||||
if(!$fname){
|
||||
return json(['status'=>false, 'msg'=>'参数不能为空']);
|
||||
$fname = input('get.filename');
|
||||
if(!$fname){
|
||||
return json(['status'=>false, 'msg'=>'参数不能为空']);
|
||||
}
|
||||
}
|
||||
if(strpos(dirname($fname),'.')!==false)return json(['status'=>false, 'msg'=>'参数不正确']);
|
||||
if(!$this->checklist()) return json(['status'=>false, 'msg'=>'你的服务器被禁止使用此云端']);
|
||||
@@ -139,6 +176,11 @@ class Api extends BaseController
|
||||
return $version;
|
||||
}
|
||||
|
||||
public function get_version_en(){
|
||||
$version = config_get('new_version_en');
|
||||
return $version;
|
||||
}
|
||||
|
||||
public function get_panel_version(){
|
||||
$version = config_get('new_version');
|
||||
$file = app()->getRootPath().'public/install/update/LinuxPanel-'.$version.'.zip';
|
||||
@@ -151,6 +193,22 @@ class Api extends BaseController
|
||||
return json($data);
|
||||
}
|
||||
|
||||
public function get_panel_version_v2(){
|
||||
$version = config_get('new_version');
|
||||
$down_url = request()->root(true).'/install/update/LinuxPanel-'.$version.'.zip';
|
||||
$data = [
|
||||
'OfficialVersion' => [
|
||||
'version' => $version,
|
||||
'downUrl' => $down_url,
|
||||
'updateMsg' => config_get('update_msg'),
|
||||
'uptime' => config_get('update_date'),
|
||||
],
|
||||
'OfficialVersionLatest' => [],
|
||||
'AccountVersion' => [],
|
||||
];
|
||||
return json($data);
|
||||
}
|
||||
|
||||
//安装统计
|
||||
public function setup_count(){
|
||||
return 'ok';
|
||||
@@ -205,6 +263,28 @@ class Api extends BaseController
|
||||
return json($data);
|
||||
}
|
||||
|
||||
//检测更新(aapanel)
|
||||
public function check_update_en(){
|
||||
$version = config_get('new_version_en');
|
||||
$down_url = request()->root(true).'/install/update/LinuxPanel_EN-'.$version.'.zip';
|
||||
$data = [
|
||||
'force' => false,
|
||||
'version' => $version,
|
||||
'downUrl' => $down_url,
|
||||
'updateMsg' => config_get('update_msg_en'),
|
||||
'uptime' => config_get('update_date_en'),
|
||||
'is_beta' => 0,
|
||||
'btb' => '',
|
||||
'beta' => [
|
||||
'version' => $version,
|
||||
'downUrl' => $down_url,
|
||||
'updateMsg' => config_get('update_msg_en'),
|
||||
'uptime' => config_get('update_date_en'),
|
||||
]
|
||||
];
|
||||
return json($data);
|
||||
}
|
||||
|
||||
//宝塔云监控获取最新版本
|
||||
public function btm_latest_version(){
|
||||
$data = [
|
||||
@@ -410,6 +490,22 @@ class Api extends BaseController
|
||||
return json(['page'=>"<div><span class='Pcurrent'>1</span><span class='Pnumber'>1/0</span><span class='Pline'>从1-1000条</span><span class='Pcount'>共计0条数据</span></div>", 'data'=>[]]);
|
||||
}
|
||||
|
||||
public function nps_check(){
|
||||
return json(['err_no'=>0, 'success'=>true, 'res'=>true, 'nonce'=>time()]);
|
||||
}
|
||||
|
||||
public function nps_questions(){
|
||||
return json(['err_no'=>0, 'success'=>true, 'res'=>[], 'nonce'=>time()]);
|
||||
}
|
||||
|
||||
public function nps_submit(){
|
||||
return json(['err_no'=>0, 'success'=>true, 'res'=>'Success', 'nonce'=>time()]);
|
||||
}
|
||||
|
||||
public function get_user_give_away(){
|
||||
return json(['no_exceed_limit'=>false, 'user_give'=>true]);
|
||||
}
|
||||
|
||||
//获取所有蜘蛛IP列表
|
||||
public function btwaf_getspiders(){
|
||||
try{
|
||||
@@ -427,6 +523,39 @@ class Api extends BaseController
|
||||
$result = Plugins::get_spider($type);
|
||||
return json($result);
|
||||
}
|
||||
|
||||
//获取堡塔恶意情报IP库
|
||||
public function btwaf_getmalicious(){
|
||||
try{
|
||||
$result = Plugins::btwaf_getmalicious();
|
||||
return json($result);
|
||||
}catch(\Exception $e){
|
||||
return json(['success'=>false, 'res'=>$e->getMessage()]);
|
||||
}
|
||||
}
|
||||
|
||||
//检查是否国内IP
|
||||
public function check_cnip(){
|
||||
$clientip = bindec(decbin(ip2long($this->clientip)));
|
||||
$json_file = app()->getBasePath().'lib/cn.json';
|
||||
$arr = json_decode(file_get_contents($json_file), true);
|
||||
if(!$arr) return 'False';
|
||||
foreach($arr as $ip_arr){
|
||||
if($clientip >= $ip_arr[0] && $clientip <= $ip_arr[1]){
|
||||
return 'True';
|
||||
}
|
||||
}
|
||||
return 'False';
|
||||
}
|
||||
|
||||
//邮件配额
|
||||
public function email_user_surplus(){
|
||||
$data = [
|
||||
'free' => ['surplus' => '120000', 'total' => '120000', 'used' => '0'],
|
||||
'period' => ['surplus' => '2000000', 'total' => '2000000', 'used' => '0'],
|
||||
];
|
||||
return json(['success'=>true, 'msg'=>'获取成功', 'res'=>$data]);
|
||||
}
|
||||
|
||||
//检查黑白名单
|
||||
private function checklist(){
|
||||
|
@@ -15,7 +15,10 @@ class BtPlugins
|
||||
|
||||
public function __construct($os){
|
||||
$this->os = $os;
|
||||
if($os == 'Windows'){
|
||||
if($os == 'en'){
|
||||
$bt_url = config_get('enbt_url');
|
||||
$bt_key = config_get('enbt_key');
|
||||
}elseif($os == 'Windows'){
|
||||
$bt_url = config_get('wbt_url');
|
||||
$bt_key = config_get('wbt_key');
|
||||
}else{
|
||||
@@ -33,9 +36,11 @@ class BtPlugins
|
||||
if(empty($result['list']) || empty($result['type'])){
|
||||
throw new Exception('获取插件列表失败:插件列表为空');
|
||||
}
|
||||
foreach($result['list'] as $k=>$v){
|
||||
if(in_array($v['name'], self::$block_plugins)) unset($result['list'][$k]);
|
||||
$newlist = [];
|
||||
foreach($result['list'] as $item){
|
||||
if(!in_array($item['name'], self::$block_plugins)) $newlist[] = $item;
|
||||
}
|
||||
$result['list'] = $newlist;
|
||||
return $result;
|
||||
}else{
|
||||
throw new Exception('获取插件列表失败:'.(isset($result['msg'])?$result['msg']:'面板连接失败'));
|
||||
@@ -157,9 +162,9 @@ class BtPlugins
|
||||
$de_text = '';
|
||||
foreach($data_arr as $data){
|
||||
$data = trim($data);
|
||||
if(!empty($data) && strlen($data)!=24){
|
||||
if(!empty($data)){
|
||||
$tmp = openssl_decrypt($data, 'aes-128-cbc', $key, 0, $iv);
|
||||
if($tmp) $de_text .= $tmp;
|
||||
if($tmp !== false) $de_text .= $tmp;
|
||||
}
|
||||
}
|
||||
if(!empty($de_text) && strpos($de_text, 'import ')!==false){
|
||||
@@ -191,17 +196,21 @@ class BtPlugins
|
||||
$data = str_replace('\'http://www.bt.cn/api/wpanel/notpro', 'public.GetConfigValue(\'home\')+\'/api/wpanel/notpro', $data);
|
||||
$data = str_replace('\'https://www.bt.cn/api/wpanel/notpro', 'public.GetConfigValue(\'home\')+\'/api/wpanel/notpro', $data);
|
||||
|
||||
$data = str_replace('"https://www.bt.cn/api/bt_waf/get_malicious', 'public.GetConfigValue(\'home\')+"/api/bt_waf/get_malicious', $data);
|
||||
$data = str_replace('\'http://www.bt.cn/api/bt_waf/getSpiders', 'public.GetConfigValue(\'home\')+\'/api/bt_waf/getSpiders', $data);
|
||||
$data = str_replace('\'https://www.bt.cn/api/bt_waf/getSpiders', 'public.GetConfigValue(\'home\')+\'/api/bt_waf/getSpiders', $data);
|
||||
$data = str_replace('\'http://www.bt.cn/api/bt_waf/addSpider', 'public.GetConfigValue(\'home\')+\'/api/bt_waf/addSpider', $data);
|
||||
$data = str_replace('\'https://www.bt.cn/api/bt_waf/addSpider', 'public.GetConfigValue(\'home\')+\'/api/bt_waf/addSpider', $data);
|
||||
$data = str_replace('\'https://www.bt.cn/api/bt_waf/getVulScanInfoList', 'public.GetConfigValue(\'home\')+\'/api/bt_waf/getVulScanInfoList', $data);
|
||||
$data = str_replace('\'https://www.bt.cn/api/bt_waf/reportInterceptFail', 'public.GetConfigValue(\'home\')+\'/api/bt_waf/reportInterceptFail', $data);
|
||||
$data = str_replace('"https://www.bt.cn/api/bt_waf/reportInterceptFail', 'public.GetConfigValue(\'home\')+"/api/bt_waf/reportInterceptFail', $data);
|
||||
$data = str_replace('\'https://www.bt.cn/api/v2/contact/nps/questions', 'public.GetConfigValue(\'home\')+\'/panel/notpro', $data);
|
||||
$data = str_replace('\'https://www.bt.cn/api/v2/contact/nps/submit', 'public.GetConfigValue(\'home\')+\'/panel/notpro', $data);
|
||||
$data = str_replace('\'http://www.bt.cn/api/Auth', 'public.GetConfigValue(\'home\')+\'/api/Auth', $data);
|
||||
$data = str_replace('\'https://www.bt.cn/api/Auth', 'public.GetConfigValue(\'home\')+\'/api/Auth', $data);
|
||||
|
||||
$data = str_replace('\'https://brandnew.aapanel.com/api/panel/getSoftList', 'public.OfficialApiBase()+\'/api/panel/getSoftList', $data);
|
||||
|
||||
file_put_contents($main_filepath, $data);
|
||||
}
|
||||
|
||||
@@ -283,4 +292,16 @@ class BtPlugins
|
||||
}
|
||||
}
|
||||
|
||||
//获取堡塔恶意情报IP库
|
||||
public function btwaf_getmalicious(){
|
||||
$result = $this->btapi->btwaf_getmalicious();
|
||||
if(isset($result['success'])){
|
||||
return $result;
|
||||
}elseif(isset($result['msg'])){
|
||||
throw new Exception($result['msg']);
|
||||
}else{
|
||||
throw new Exception(isset($result['res'])?$result['res']:'获取失败');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -169,6 +169,18 @@ class Btapi
|
||||
$data = json_decode($result,true);
|
||||
return $data;
|
||||
}
|
||||
|
||||
//BTWAF-获取堡塔恶意情报IP库
|
||||
public function btwaf_getmalicious(){
|
||||
$url = $this->BT_PANEL.'/plugin?action=a&name=kaixin&s=btwaf_getmalicious';
|
||||
|
||||
$p_data = $this->GetKeyData();
|
||||
|
||||
$result = $this->curl($url,$p_data);
|
||||
|
||||
$data = json_decode($result,true);
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
private function GetKeyData(){
|
||||
|
@@ -17,7 +17,13 @@ class Plugins
|
||||
}
|
||||
|
||||
private static function is_third($os){
|
||||
$type = $os == 'Windows' ? config_get('wbt_type') : config_get('bt_type');
|
||||
if($os == 'en'){
|
||||
$type = config_get('enbt_type');
|
||||
}elseif($os == 'Windows'){
|
||||
$type = config_get('wbt_type');
|
||||
}else{
|
||||
$type = config_get('bt_type');
|
||||
}
|
||||
return $type == 1;
|
||||
}
|
||||
|
||||
@@ -31,23 +37,45 @@ class Plugins
|
||||
//保存插件列表
|
||||
private static function save_plugin_list($data, $os){
|
||||
$data['ip'] = '127.0.0.1';
|
||||
$data['serverid'] = '';
|
||||
$data['beta'] = 0;
|
||||
$data['uid'] = 1;
|
||||
$data['skey'] = '';
|
||||
$list = [];
|
||||
foreach($data['list'] as $plugin){
|
||||
if(isset($plugin['endtime'])) $plugin['endtime'] = 0;
|
||||
$list[] = $plugin;
|
||||
if($os == 'en'){
|
||||
$data['serverId'] = '';
|
||||
$data['aln'] = self::get_aln();
|
||||
$data['pro'] = 0;
|
||||
$data['pro_authorization_sn'] = '0';
|
||||
if(!empty($data['authorization_map'])){
|
||||
foreach($data['authorization_map'] as $code => &$plugin){
|
||||
if($code != '0' && isset($plugin['end_time'])) $plugin['end_time'] = 0;
|
||||
}
|
||||
}
|
||||
if(isset($data['expansions']['mail'])){
|
||||
$data['expansions']['mail']['total'] = 2000000;
|
||||
$data['expansions']['mail']['available'] = 2000000;
|
||||
}
|
||||
}else{
|
||||
$data['serverid'] = '';
|
||||
$data['aln'] = self::get_aln();
|
||||
$data['beta'] = 0;
|
||||
$data['uid'] = 1;
|
||||
$data['skey'] = '';
|
||||
$data['pro'] = -1;
|
||||
$data['ltd'] = strtotime('+10 year');
|
||||
}
|
||||
foreach($data['list'] as &$plugin){
|
||||
if(isset($plugin['endtime'])) $plugin['endtime'] = 0;
|
||||
}
|
||||
$data['list'] = $list;
|
||||
$data['ltd'] = strtotime('+10 year');
|
||||
$json_file = get_data_dir($os).'config/plugin_list.json';
|
||||
if(!file_put_contents($json_file, json_encode($data))){
|
||||
throw new Exception('保存插件列表失败,文件无写入权限');
|
||||
}
|
||||
}
|
||||
|
||||
//多账号数量
|
||||
private static function get_aln($count = '9999'){
|
||||
$key = 'FB8upo8XMgP5by54';
|
||||
$iv = 'lOrrq3lNEURZNdK7';
|
||||
return openssl_encrypt($count, 'aes-128-cbc', $key, 0, $iv);
|
||||
}
|
||||
|
||||
//获取插件列表
|
||||
public static function get_plugin_list($os = 'Linux'){
|
||||
$json_file = get_data_dir($os).'config/plugin_list.json';
|
||||
@@ -106,7 +134,7 @@ class Plugins
|
||||
$data = trim($data);
|
||||
if(!empty($data)){
|
||||
$tmp = openssl_decrypt($data, 'aes-128-cbc', $key, 0, $iv);
|
||||
if($tmp) $de_text .= $tmp;
|
||||
if($tmp !== false) $de_text .= $tmp;
|
||||
}
|
||||
}
|
||||
if(!empty($de_text) && strpos($de_text, 'import ')!==false){
|
||||
@@ -165,4 +193,11 @@ class Plugins
|
||||
return $result;
|
||||
}
|
||||
|
||||
//获取堡塔恶意情报IP库
|
||||
public static function btwaf_getmalicious(){
|
||||
$btapi = self::get_btapi('Linux');
|
||||
$result = $btapi->btwaf_getmalicious();
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
@@ -13,7 +13,13 @@ class ThirdPlugins
|
||||
public function __construct($os)
|
||||
{
|
||||
$this->os = $os;
|
||||
$url = $os == 'Windows' ? config_get('wbt_surl') : config_get('bt_surl');
|
||||
if($os == 'en'){
|
||||
$url = config_get('enbt_surl');
|
||||
}elseif($os == 'Windows'){
|
||||
$url = config_get('wbt_surl');
|
||||
}else{
|
||||
$url = config_get('bt_surl');
|
||||
}
|
||||
if(!$url) throw new Exception('请先配置好第三方云端首页URL');
|
||||
$this->url = $url;
|
||||
}
|
||||
@@ -21,7 +27,13 @@ class ThirdPlugins
|
||||
//获取插件列表
|
||||
public function get_plugin_list()
|
||||
{
|
||||
$url = $this->os == 'Windows' ? $this->url . 'api/wpanel/get_soft_list' : $this->url . 'api/panel/get_soft_list';
|
||||
if($this->os == 'en'){
|
||||
$url = $this->url . 'api/panel/getSoftListEn';
|
||||
}elseif($this->os == 'Windows'){
|
||||
$url = $this->url . 'api/wpanel/get_soft_list';
|
||||
}else{
|
||||
$url = $this->url . 'api/panel/get_soft_list';
|
||||
}
|
||||
$res = $this->curl($url);
|
||||
$result = json_decode($res, true);
|
||||
if($result && isset($result['list']) && isset($result['type'])){
|
||||
@@ -162,6 +174,18 @@ class ThirdPlugins
|
||||
}
|
||||
}
|
||||
|
||||
//获取堡塔恶意情报IP库
|
||||
public function btwaf_getmalicious(){
|
||||
$url = $this->url . 'api/bt_waf/get_malicious';
|
||||
$res = $this->curl($url);
|
||||
$result = json_decode($res, true);
|
||||
if(isset($result['success'])){
|
||||
return $result;
|
||||
}else{
|
||||
throw new Exception(isset($result['res'])?$result['res']:'获取失败');
|
||||
}
|
||||
}
|
||||
|
||||
private function curl($url, $post = 0){
|
||||
$ua = "Mozilla/5.0 (BtCloud; ".request()->root(true).")";
|
||||
return get_curl($url, $post, 0, 0, 0, $ua);
|
||||
|
1
app/lib/cn.json
Normal file
1
app/lib/cn.json
Normal file
File diff suppressed because one or more lines are too long
@@ -1,13 +1,14 @@
|
||||
#!/bin/bash
|
||||
|
||||
Linux_Version="9.2.0"
|
||||
Windows_Version="8.2.0"
|
||||
Linux_Version="9.6.0"
|
||||
Windows_Version="8.2.2"
|
||||
Aapanel_Version="7.0.16"
|
||||
Btm_Version="2.3.0"
|
||||
|
||||
FILES=(
|
||||
public/install/src/panel6.zip
|
||||
public/install/update/LinuxPanel-${Linux_Version}.zip
|
||||
public/install/install_6.0.sh
|
||||
public/install/install_panel.sh
|
||||
public/install/update_panel.sh
|
||||
public/install/update6.sh
|
||||
public/win/install/panel_update.py
|
||||
@@ -17,6 +18,10 @@ public/win/panel/data/setup.py
|
||||
public/install/src/bt-monitor-${Btm_Version}.zip
|
||||
public/install/install_btmonitor.sh
|
||||
public/install/update_btmonitor.sh
|
||||
public/install/src/panel_7_en.zip
|
||||
public/install/update/LinuxPanel_EN-${Aapanel_Version}.zip
|
||||
public/install/install_7.0_en.sh
|
||||
public/install/update_7.x_en.sh
|
||||
)
|
||||
|
||||
DIR=$1
|
||||
|
@@ -34,11 +34,12 @@
|
||||
<li class="{:checkIfActive('index')}">
|
||||
<a href="/admin"><i class="fa fa-home"></i> 后台首页</a>
|
||||
</li>
|
||||
<li class="{:checkIfActive('plugins,pluginswin,deplist')}">
|
||||
<li class="{:checkIfActive('plugins,pluginswin,pluginsen,deplist')}">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="fa fa-cubes"></i> 插件列表<b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li class="{:checkIfActive('plugins')}"><a href="/admin/plugins">Linux面板</a></li>
|
||||
<li class="{:checkIfActive('pluginswin')}"><a href="/admin/pluginswin">Windows面板</a></li>
|
||||
<li class="{:checkIfActive('pluginsen')}"><a href="/admin/pluginsen">aaPanel面板</a></li>
|
||||
<li class="{:checkIfActive('deplist')}"><a href="/admin/deplist">一键部署列表</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
@@ -35,6 +35,7 @@ td{overflow: hidden;text-overflow: ellipsis;white-space: nowrap;max-width:340px;
|
||||
<div class="modal-body">
|
||||
<p>“版本与状态”一列中,红色的按钮代表本地不存在该版本插件包,需要点击下载;绿色的按钮代表已存在。</p>
|
||||
<p>官方插件包本地存储路径是/data/plugins/package/软件标识-版本号.zip,第三方插件包路径是/data/plugins/other/other/,对于部分包含二次验证的插件可以自行修改。</p>
|
||||
<p>若对接的服务器网速较慢,可能会导致下载失败,提示"服务器错误",可稍等一会,进入对接服务器/tmp/plugins目录下载插件包,将_改成-,并上传到本站/data/plugins/package目录下。</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
|
||||
|
276
app/view/admin/pluginsen.html
Normal file
276
app/view/admin/pluginsen.html
Normal file
@@ -0,0 +1,276 @@
|
||||
{extend name="admin/layout" /}
|
||||
{block name="title"}插件列表{/block}
|
||||
{block name="main"}
|
||||
<style>
|
||||
td{overflow: hidden;text-overflow: ellipsis;white-space: nowrap;max-width:340px;}
|
||||
.bt-ico-ask {
|
||||
border: 1px solid #fb7d00;
|
||||
border-radius: 8px;
|
||||
color: #fb7d00;
|
||||
cursor: help;
|
||||
display: inline-block;
|
||||
font-family: arial;
|
||||
font-size: 11px;
|
||||
font-style: normal;
|
||||
height: 16px;
|
||||
line-height: 16px;
|
||||
margin-left: 5px;
|
||||
text-align: center;
|
||||
width: 16px
|
||||
}
|
||||
.bt-ico-ask:hover {
|
||||
background-color: #fb7d00;
|
||||
color: #fff
|
||||
}
|
||||
</style>
|
||||
<div class="modal fade" id="help" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<h4 class="modal-title">帮助</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>“版本与状态”一列中,红色的按钮代表本地不存在该版本插件包,需要点击下载;绿色的按钮代表已存在。</p>
|
||||
<p>官方插件包本地存储路径是/data/en/plugins/package/软件标识-版本号.zip,第三方插件包路径是/data/plugins/other/other/,对于部分包含二次验证的插件可以自行修改。</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container" style="padding-top:70px;">
|
||||
<div class="col-xs-12 center-block" style="float: none;">
|
||||
|
||||
<div id="searchToolbar">
|
||||
<form onsubmit="return searchSubmit()" method="GET" class="form-inline">
|
||||
<div class="form-group">
|
||||
<label>搜索</label>
|
||||
<input type="text" class="form-control" name="keyword" placeholder="应用名称">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<select name="type" class="form-control"><option value="0">全部插件</option>
|
||||
{foreach $typelist as $k=>$v}<option value="{$k}">{$v}</option>{/foreach} </select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button class="btn btn-primary" type="submit"><i class="fa fa-search"></i> 搜索</button>
|
||||
<a href="javascript:searchClear()" class="btn btn-default"><i class="fa fa-repeat"></i> 重置</a>
|
||||
<a href="javascript:refresh_plugins()" class="btn btn-success"><i class="fa fa-refresh"></i> 刷新列表</a>
|
||||
<a href="javascript:download_plugins()" class="btn btn-warning" id="batch_down" style="display:none;"><i class="fa fa-download"></i> 批量下载</a>
|
||||
<button type="button" class="btn btn-default" data-toggle="modal" data-target="#help"><i class="fa fa-info-circle"></i> 帮助</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<table id="listTable">
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<script src="{$cdnpublic}layer/3.5.1/layer.js"></script>
|
||||
<script src="{$cdnpublic}bootstrap-table/1.19.1/bootstrap-table.min.js"></script>
|
||||
<script src="{$cdnpublic}bootstrap-table/1.19.1/extensions/page-jump-to/bootstrap-table-page-jump-to.min.js"></script>
|
||||
<script src="/static/js/custom.js"></script>
|
||||
<script>
|
||||
|
||||
function download_version(name, version, status){
|
||||
if(status == true){
|
||||
var confirm = layer.confirm('是否确定重新下载'+version+'版本插件包?', {
|
||||
btn: ['确定','取消']
|
||||
}, function(){
|
||||
download_plugin(name, version)
|
||||
}, function(){
|
||||
layer.close(confirm)
|
||||
});
|
||||
}else{
|
||||
download_plugin(name, version)
|
||||
}
|
||||
}
|
||||
|
||||
function download_plugin(name, version){
|
||||
var ii = layer.msg('正在下载,请稍候...', {icon: 16, shade:0.1, time: 0});
|
||||
$.ajax({
|
||||
type : 'POST',
|
||||
url : '/admin/download_plugin',
|
||||
data: { name:name, version:version, os:'en'},
|
||||
dataType : 'json',
|
||||
success : function(data) {
|
||||
layer.close(ii)
|
||||
if(data.code == 0){
|
||||
layer.alert(data.msg, {icon:1}, function(){layer.closeAll();searchSubmit();});
|
||||
}else{
|
||||
layer.alert(data.msg, {icon:2});
|
||||
}
|
||||
},
|
||||
error:function(data){
|
||||
layer.close(ii)
|
||||
layer.msg('服务器错误', {icon:2});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function refresh_plugins(){
|
||||
var confirm = layer.confirm('是否确定从宝塔官方获取最新插件列表?', {
|
||||
btn: ['确定','取消']
|
||||
}, function(){
|
||||
layer.close(confirm)
|
||||
var ii = layer.msg('正在获取插件列表,请稍候...', {icon: 16, shade:0.1, time: 0});
|
||||
$.ajax({
|
||||
type : 'GET',
|
||||
url : '/admin/refresh_plugins?os=en',
|
||||
dataType : 'json',
|
||||
success : function(data) {
|
||||
layer.close(ii)
|
||||
if(data.code == 0){
|
||||
layer.alert(data.msg, {icon:1}, function(){layer.closeAll();searchSubmit();});
|
||||
}else{
|
||||
layer.alert(data.msg, {icon:2});
|
||||
}
|
||||
},
|
||||
error:function(data){
|
||||
layer.close(ii)
|
||||
layer.msg('服务器错误', {icon:2});
|
||||
}
|
||||
});
|
||||
}, function(){
|
||||
layer.close(confirm)
|
||||
});
|
||||
}
|
||||
|
||||
function download_plugins(){
|
||||
var confirm = layer.confirm('批量下载当前分类下未下载的插件包', {
|
||||
btn: ['确定','取消']
|
||||
}, function(){
|
||||
layer.close(confirm)
|
||||
$.downloadCount = 0;
|
||||
$.preDownloadCount = $.preDownload.length;
|
||||
download_item();
|
||||
}, function(){
|
||||
layer.close(confirm)
|
||||
});
|
||||
}
|
||||
|
||||
function download_item(){
|
||||
if($.preDownload.length == 0){
|
||||
layer.alert('成功下载'+$.downloadCount+'个插件包!', {icon:1}, function(){layer.closeAll();searchSubmit();});
|
||||
return;
|
||||
}
|
||||
$.downloadCount++;
|
||||
var plugin = $.preDownload[0];
|
||||
var ii = layer.msg('['+$.downloadCount+'/'+$.preDownloadCount+']正在下载'+plugin.name+'-'+plugin.version, {icon: 16, shade:0.1, time: 0});
|
||||
$.ajax({
|
||||
type : 'POST',
|
||||
url : '/admin/download_plugin',
|
||||
data: { name:plugin.name, version:plugin.version, os:'en'},
|
||||
dataType : 'json',
|
||||
success : function(data) {
|
||||
layer.close(ii)
|
||||
if(data.code == 0){
|
||||
$.preDownload.shift();
|
||||
download_item();
|
||||
}else{
|
||||
layer.alert(data.msg, {icon:2});
|
||||
}
|
||||
},
|
||||
error:function(data){
|
||||
layer.close(ii)
|
||||
layer.msg('服务器错误', {icon:2});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function searchByType(type){
|
||||
$("input[name=keyword]").val('');
|
||||
$("select[name=type]").val(type);
|
||||
searchSubmit()
|
||||
}
|
||||
|
||||
$(document).ready(function(){
|
||||
updateToolbar();
|
||||
const defaultPageSize = 20;
|
||||
|
||||
$("#listTable").bootstrapTable({
|
||||
url: '/admin/plugins_data?os=en',
|
||||
pageNumber: 1,
|
||||
pageSize: 15,
|
||||
sidePagination: 'client',
|
||||
classes: 'table table-striped table-hover table-bottom-border',
|
||||
columns: [
|
||||
{
|
||||
field: 'name',
|
||||
title: '软件标识',
|
||||
formatter: function(value, row, index) {
|
||||
return '<b>'+value+'</b>';
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'title',
|
||||
title: '软件名称'
|
||||
},
|
||||
{
|
||||
field: 'type',
|
||||
title: '软件分类',
|
||||
formatter: function(value, row, index) {
|
||||
return '<a href="javascript:searchByType('+value+')" title="查看该分类下的插件">'+row.typename+'</a>';
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'desc',
|
||||
title: '说明',
|
||||
},
|
||||
{
|
||||
field: 'price',
|
||||
title: '价格',
|
||||
formatter: function(value, row, index) {
|
||||
return value > 0 ? '<span style="color:#fc6d26">¥'+value+'</span>' : '免费';
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'author',
|
||||
title: '开发商'
|
||||
},
|
||||
{
|
||||
field: 'versions',
|
||||
title: '版本与状态',
|
||||
formatter: function(value, row, index) {
|
||||
var html = '';
|
||||
if(row.type == 5 || row.name == 'mail_sys' || row.name == 'dns_manager'){
|
||||
html += '<a href="javascript:" class="btn btn-xs btn-success" disabled>无需下载</a>';
|
||||
}else{
|
||||
$.each(value, function(index,item){
|
||||
if(item.status)
|
||||
html += '<a href="javascript:download_version(\''+row.name+'\',\''+item.version+'\','+item.status+')" class="btn btn-xs btn-success">'+item.version+'</a> ';
|
||||
else
|
||||
html += '<a href="javascript:download_version(\''+row.name+'\',\''+item.version+'\','+item.status+')" class="btn btn-xs btn-danger">'+item.version+'</a> ';
|
||||
})
|
||||
}
|
||||
return html
|
||||
}
|
||||
},
|
||||
],
|
||||
onLoadSuccess: function(data){
|
||||
$.preDownload = [];
|
||||
var type = $("select[name=type] option:selected").text();
|
||||
if(type != '全部插件' && type != '运行环境' && type != '第三方应用'){
|
||||
$("#batch_down").show();
|
||||
if(data.length > 0){
|
||||
$.each(data, function(index, plugin){
|
||||
if(plugin.versions.length > 0 && plugin.name!='mail_sys' && plugin.name!='dns_manager'){
|
||||
$.each(plugin.versions, function(index, version){
|
||||
if(!version.status){
|
||||
$.preDownload.push({name:plugin.name, version:version.version})
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}else{
|
||||
$("#batch_down").hide();
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
</script>
|
||||
{/block}
|
@@ -49,8 +49,6 @@
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-6 center-block">
|
||||
<div class="panel panel-info">
|
||||
<div class="panel-heading"><h3 class="panel-title">Windows面板版本设置</h3></div>
|
||||
<div class="panel-body">
|
||||
@@ -76,6 +74,8 @@
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-6 center-block">
|
||||
<div class="panel panel-info">
|
||||
<div class="panel-heading"><h3 class="panel-title">云监控版本设置</h3></div>
|
||||
<div class="panel-body">
|
||||
@@ -99,6 +99,31 @@
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-info">
|
||||
<div class="panel-heading"><h3 class="panel-title">aaPanel面板版本设置</h3></div>
|
||||
<div class="panel-body">
|
||||
<form onsubmit="return saveSetting(this)" method="post" class="form" role="form">
|
||||
<div class="form-group">
|
||||
<label>宝塔Linux面板最新版本号:</label>
|
||||
<input type="text" name="new_version_en" value="{:config_get('new_version_en')}" class="form-control"/>
|
||||
<font color="green">用于一键更新脚本获取最新版本号,以及检测更新接口。并确保已在/public/install/update/放置对应版本更新包</font>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>宝塔Linux面板更新日志:</label>
|
||||
<textarea class="form-control" name="update_msg_en" rows="5" placeholder="支持HTML代码">{:config_get('update_msg_en')}</textarea>
|
||||
<font color="green">用于检测更新接口返回</font>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>宝塔Linux面板更新日期:</label>
|
||||
<input type="date" name="update_date_en" value="{:config_get('update_date_en')}" class="form-control"/>
|
||||
<font color="green">用于检测更新接口返回</font>
|
||||
</div>
|
||||
<div class="form-group text-center">
|
||||
<input type="submit" name="submit" value="保存" class="btn btn-success btn-block"/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{elseif $mod=='api'}
|
||||
<div class="col-sm-12 col-md-6 center-block">
|
||||
@@ -175,6 +200,43 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-6 center-block">
|
||||
<div class="panel panel-info">
|
||||
<div class="panel-heading"><h3 class="panel-title">aaPanel面板接口设置</h3></div>
|
||||
<div class="panel-body">
|
||||
<form onsubmit="return saveSetting(this)" method="post" class="form" role="form">
|
||||
<div class="form-group">
|
||||
<label>对接方式:</label><br/>
|
||||
<select class="form-control" name="enbt_type" default="{:config_get('enbt_type')}"><option value="0">对接aaPanel面板接口</option><option value="1">对接其他第三方云端</option></select>
|
||||
</div><hr/>
|
||||
<div id="enbt_type_0" style="{if config_get('enbt_type')==1}display:none;{/if}">
|
||||
<p>以下aaPanel面板请使用官方最新脚本安装并绑定账号,用于获取插件列表及插件包</p>
|
||||
<p><a href="/static/file/en/kaixin.zip">下载专用插件(aaPanel)</a>,在面板【软件商店】->【第三方应用】,点击【导入插件】,导入该专用插件。</p>
|
||||
<div class="form-group">
|
||||
<label>aaPanel面板URL:</label><br/>
|
||||
<input type="text" name="enbt_url" value="{:config_get('enbt_url')}" class="form-control"/>
|
||||
<font color="green">填写规则如:<u>http://192.168.1.1:8888</u> ,不要带其他后缀</font>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>aaPanel面板接口密钥:</label>
|
||||
<input type="text" name="enbt_key" value="{:config_get('enbt_key')}" class="form-control"/>
|
||||
</div>
|
||||
</div>
|
||||
<div id="enbt_type_1" style="{if !config_get('enbt_type')}display:none;{/if}">
|
||||
<div class="form-group">
|
||||
<label>第三方云端首页URL:</label><br/>
|
||||
<input type="text" name="enbt_surl" value="{:config_get('enbt_surl')}" class="form-control"/>
|
||||
<font color="green">填写规则如:<u>http://www.example.com/</u> ,必须以/结尾</font>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group text-center">
|
||||
<button type="button" class="btn btn-info btn-block" id="testbturl3">测试连接</button>
|
||||
<input type="submit" name="submit" value="保存" class="btn btn-success btn-block"/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$("select[name='bt_type']").change(function(){
|
||||
if($(this).val() == 1){
|
||||
@@ -194,6 +256,15 @@ $("select[name='wbt_type']").change(function(){
|
||||
$("#wbt_type_1").hide();
|
||||
}
|
||||
});
|
||||
$("select[name='enbt_type']").change(function(){
|
||||
if($(this).val() == 1){
|
||||
$("#enbt_type_0").hide();
|
||||
$("#enbt_type_1").show();
|
||||
}else{
|
||||
$("#enbt_type_0").show();
|
||||
$("#enbt_type_1").hide();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{elseif $mod=='task'}
|
||||
<div class="col-sm-12 col-md-6 center-block">
|
||||
@@ -222,6 +293,10 @@ $("select[name='wbt_type']").change(function(){
|
||||
<label>Windows面板批量下载插件范围:</label><br/>
|
||||
<select class="form-control" name="updateall_type_win" default="{:config_get('updateall_type_win')}"><option value="0">仅免费插件</option><option value="1">免费插件+专业版插件</option><option value="2">免费插件+专业版插件+企业版插件</option></select><font color="green">(批量下载不包含所有第三方插件,第三方插件需要去手动下载。)</font>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>aaPanel面板批量下载插件范围:</label><br/>
|
||||
<select class="form-control" name="updateall_type_en" default="{:config_get('updateall_type_en')}"><option value="0">仅免费插件</option><option value="1">免费插件+专业版插件</option><option value="2">免费插件+专业版插件+企业版插件</option></select><font color="green">(批量下载不包含所有第三方插件,第三方插件需要去手动下载。)</font>
|
||||
</div>
|
||||
<div class="form-group text-center">
|
||||
<input type="submit" name="submit" value="保存" class="btn btn-success btn-block"/>
|
||||
</div>
|
||||
@@ -376,6 +451,51 @@ $(document).ready(function(){
|
||||
}
|
||||
});
|
||||
})
|
||||
$("#testbturl3").click(function(){
|
||||
var enbt_type = $("select[name=enbt_type]").val();
|
||||
if(enbt_type == '1'){
|
||||
var enbt_surl = $("input[name=enbt_surl]").val();
|
||||
if(enbt_surl == ''){
|
||||
layer.alert('第三方云端URL不能为空');return;
|
||||
}
|
||||
if(enbt_surl.indexOf('http://')==-1 && enbt_surl.indexOf('https://')==-1){
|
||||
layer.alert('第三方云端URL不正确');return;
|
||||
}
|
||||
var postdata = {bt_type:enbt_type, bt_surl:enbt_surl};
|
||||
}else{
|
||||
var enbt_url = $("input[name=enbt_url]").val();
|
||||
var enbt_key = $("input[name=enbt_key]").val();
|
||||
if(enbt_url == ''){
|
||||
layer.alert('宝塔面板URL不能为空');return;
|
||||
}
|
||||
if(enbt_url.indexOf('http://')==-1 && enbt_url.indexOf('https://')==-1){
|
||||
layer.alert('宝塔面板URL不正确');return;
|
||||
}
|
||||
if(enbt_key == ''){
|
||||
layer.alert('宝塔面板接口密钥不能为空');return;
|
||||
}
|
||||
var postdata = {bt_type:enbt_type, bt_url:enbt_url, bt_key:enbt_key};
|
||||
}
|
||||
var ii = layer.load(2, {shade:[0.1,'#fff']});
|
||||
$.ajax({
|
||||
type : 'POST',
|
||||
url : '/admin/testbturl',
|
||||
data : postdata,
|
||||
dataType : 'json',
|
||||
success : function(data) {
|
||||
layer.close(ii);
|
||||
if(data.code == 0){
|
||||
layer.msg(data.msg, {icon: 1, time:1000})
|
||||
}else{
|
||||
layer.alert(data.msg, {icon: 2})
|
||||
}
|
||||
},
|
||||
error:function(data){
|
||||
layer.close(ii);
|
||||
layer.msg('服务器错误');
|
||||
}
|
||||
});
|
||||
})
|
||||
})
|
||||
function saveSetting(obj){
|
||||
var ii = layer.load(2, {shade:[0.1,'#fff']});
|
||||
|
@@ -43,7 +43,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="install-box windows">
|
||||
{if config_get('new_version_win')}<div class="install-box windows">
|
||||
<div class="img">
|
||||
<img src="/static/images/prd_2_03.png">
|
||||
</div>
|
||||
@@ -60,10 +60,10 @@
|
||||
<a class="btn" href="javascript:;" id="goInstallWindows">查看安装方法</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>{/if}
|
||||
</div>
|
||||
{if config_get('new_version_btm')}<div class="disflex flex_lrcenter mt_30 install-list">
|
||||
<div class="install-box monitor">
|
||||
{if config_get('new_version_btm') || config_get('new_version_en')}<div class="disflex flex_lrcenter mt_30 install-list">
|
||||
{if config_get('new_version_win')}<div class="install-box monitor">
|
||||
<div class="img">
|
||||
<img src="/static/images/bt_monitor.png" style="height: 96px;"/>
|
||||
</div>
|
||||
@@ -76,7 +76,21 @@
|
||||
<a class="btn" href="javascript:;" id="goInstallMonitor">查看安装脚本</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>{/if}
|
||||
{if config_get('new_version_en')}<div class="install-box monitor">
|
||||
<div class="img">
|
||||
<img src="/static/images/aapanel.png" style="height: 96px;"/>
|
||||
</div>
|
||||
<div class="cont">
|
||||
<div class="top">
|
||||
<div class="title">aaPanel {:config_get('new_version_en')}</div>
|
||||
<div class="desc">宝塔面板国际版</div>
|
||||
</div>
|
||||
<div class="bottom">
|
||||
<a class="btn" href="javascript:;" id="goInstallAaPanel">查看安装脚本</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>{/if}
|
||||
</div>{/if}
|
||||
</div>
|
||||
</div>
|
||||
@@ -96,15 +110,15 @@
|
||||
<div class="install-code">
|
||||
<span class="osname">Centos安装脚本</span>
|
||||
<div class="code-cont">
|
||||
<div class="command" title="点击复制Centos安装脚本">yum install -y wget && wget -O install.sh {$siteurl}/install/install_6.0.sh && sh install.sh</div>
|
||||
<span class="ico-copy" title="点击复制Centos安装脚本" data-clipboard-text="yum install -y wget && wget -O install.sh {$siteurl}/install/install_6.0.sh && sh install.sh">复制</span>
|
||||
<div class="command" title="点击复制Centos安装脚本">yum install -y wget && wget -O install.sh {$siteurl}/install/install_panel.sh && sh install.sh</div>
|
||||
<span class="ico-copy" title="点击复制Centos安装脚本" data-clipboard-text="yum install -y wget && wget -O install.sh {$siteurl}/install/install_panel.sh && sh install.sh">复制</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="install-code">
|
||||
<span class="osname">Ubuntu/Debian安装脚本</span>
|
||||
<div class="code-cont">
|
||||
<div class="command" title="点击复制Ubuntu/Debian安装脚本">wget -O install.sh {$siteurl}/install/install_6.0.sh && bash install.sh</div>
|
||||
<span class="ico-copy" title="点击复制Ubuntu/Debian安装脚本" data-clipboard-text="wget -O install.sh {$siteurl}/install/install_6.0.sh && bash install.sh">复制</span>
|
||||
<div class="command" title="点击复制Ubuntu/Debian安装脚本">wget -O install.sh {$siteurl}/install/install_panel.sh && bash install.sh</div>
|
||||
<span class="ico-copy" title="点击复制Ubuntu/Debian安装脚本" data-clipboard-text="wget -O install.sh {$siteurl}/install/install_panel.sh && bash install.sh">复制</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="install-code">
|
||||
@@ -121,6 +135,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{if config_get('new_version_win')}
|
||||
<div class="d4" id="instal-windows" style="background-color: #edf6ef;">
|
||||
<div class="wrap">
|
||||
<div class="wrap-title">
|
||||
@@ -140,7 +155,7 @@
|
||||
<p>注意:仅支持Windows Server 2008 R2/2012/2016/2019/2022,64位系统(中文简体),且未安装其它环境</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>{/if}
|
||||
{if config_get('new_version_btm')}
|
||||
<div class="d4" id="instal-monitor">
|
||||
<div class="wrap">
|
||||
@@ -171,6 +186,31 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>{/if}
|
||||
{if config_get('new_version_en')}
|
||||
<div class="d4" id="instal-aapanel" style="background-color: #edf6ef;">
|
||||
<div class="wrap">
|
||||
<div class="wrap-title">
|
||||
<div class="text">aaPanel {:config_get('new_version_en')} install script</div>
|
||||
</div>
|
||||
<div class="desc">
|
||||
<p>It is recommended that you use Ubuntu22.04 to install aaPanel</p>
|
||||
</div>
|
||||
<div class="install-code">
|
||||
<span class="osname">Instarll script</span>
|
||||
<div class="code-cont">
|
||||
<div class="command" title="Copy successfully, please paste it to the server installation">URL={$siteurl}/install/install_7.0_en.sh && if [ -f /usr/bin/curl ];then curl -ksSO $URL ;else wget -O install_7.0_en.sh $URL;fi;bash install_7.0_en.sh</div>
|
||||
<span class="ico-copy" title="Copy successfully, please paste it to the server installation" data-clipboard-text="URL={$siteurl}/install/install_7.0_en.sh && if [ -f /usr/bin/curl ];then curl -ksSO $URL ;else wget -O install_7.0_en.sh $URL;fi;bash install_7.0_en.sh">复制</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="install-code">
|
||||
<span class="osname">Upgrade script</span>
|
||||
<div class="code-cont">
|
||||
<div class="command" title="Copy successfully, please paste it to the server installation">curl {$siteurl}/install/update_7.x_en.sh|bash</div>
|
||||
<span class="ico-copy" title="Copy successfully, please paste it to the server installation" data-clipboard-text="curl {$siteurl}/install/update_7.x_en.sh|bash">复制</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>{/if}
|
||||
<div class="animate-bg"></div>
|
||||
</div>
|
||||
|
||||
@@ -236,6 +276,10 @@
|
||||
scrollTop('#instal-monitor');
|
||||
});
|
||||
|
||||
$('#goInstallAaPanel').click(function () {
|
||||
scrollTop('#instal-aapanel');
|
||||
});
|
||||
|
||||
function GetRequest() {
|
||||
var url = location.search;
|
||||
//获取url中"?"符后的字串
|
||||
|
0
data/en/config/.gitkeep
Normal file
0
data/en/config/.gitkeep
Normal file
0
data/en/plugins/folder/.gitkeep
Normal file
0
data/en/plugins/folder/.gitkeep
Normal file
0
data/en/plugins/main/.gitkeep
Normal file
0
data/en/plugins/main/.gitkeep
Normal file
0
data/en/plugins/package/.gitkeep
Normal file
0
data/en/plugins/package/.gitkeep
Normal file
17
install.sql
17
install.sql
@@ -12,12 +12,15 @@ INSERT INTO `cloud_config` (`key`, `value`) VALUES
|
||||
('bt_key', ''),
|
||||
('whitelist', '0'),
|
||||
('download_page', '1'),
|
||||
('new_version', '9.2.0'),
|
||||
('new_version', '9.4.0'),
|
||||
('update_msg', '暂无更新日志'),
|
||||
('update_date', '2024-09-13'),
|
||||
('new_version_win', '8.1.0'),
|
||||
('update_date', '2025-01-09'),
|
||||
('new_version_win', '8.2.2'),
|
||||
('update_msg_win', '暂无更新日志'),
|
||||
('update_date_win', '2024-07-17'),
|
||||
('update_date_win', '2024-12-30'),
|
||||
('new_version_en', '7.0.13'),
|
||||
('update_msg_en', '暂无更新日志'),
|
||||
('update_date_en', '2024-11-17'),
|
||||
('new_version_btm', '2.3.0'),
|
||||
('update_msg_btm', '暂无更新日志'),
|
||||
('update_date_btm', '2024-04-24'),
|
||||
@@ -28,7 +31,7 @@ INSERT INTO `cloud_config` (`key`, `value`) VALUES
|
||||
DROP TABLE IF EXISTS `cloud_black`;
|
||||
CREATE TABLE `cloud_black` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`ip` varchar(20) NOT NULL,
|
||||
`ip` varchar(50) NOT NULL,
|
||||
`enable` tinyint(1) NOT NULL DEFAULT '1',
|
||||
`addtime` datetime NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
@@ -38,7 +41,7 @@ CREATE TABLE `cloud_black` (
|
||||
DROP TABLE IF EXISTS `cloud_white`;
|
||||
CREATE TABLE `cloud_white` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`ip` varchar(20) NOT NULL,
|
||||
`ip` varchar(50) NOT NULL,
|
||||
`enable` tinyint(1) NOT NULL DEFAULT '1',
|
||||
`addtime` datetime NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
@@ -48,7 +51,7 @@ CREATE TABLE `cloud_white` (
|
||||
DROP TABLE IF EXISTS `cloud_record`;
|
||||
CREATE TABLE `cloud_record` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`ip` varchar(20) NOT NULL,
|
||||
`ip` varchar(50) NOT NULL,
|
||||
`addtime` datetime NOT NULL,
|
||||
`usetime` datetime NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
|
2027
public/install/install_7.0_en.sh
Normal file
2027
public/install/install_7.0_en.sh
Normal file
File diff suppressed because it is too large
Load Diff
@@ -3,9 +3,6 @@ PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
|
||||
export PATH
|
||||
LANG=en_US.UTF-8
|
||||
|
||||
INSTALL_LOGFILE="/tmp/btpanel-install.log"
|
||||
# exec > >(tee -a "$INSTALL_LOGFILE") 2>&1
|
||||
|
||||
Btapi_Url='http://www.example.com'
|
||||
Check_Api=$(curl -Ss --connect-timeout 5 -m 2 $Btapi_Url/api/SetupCount)
|
||||
if [ "$Check_Api" != 'ok' ];then
|
||||
@@ -23,44 +20,6 @@ if [ "${is64bit}" != '64' ];then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
Ready_Check(){
|
||||
WWW_DISK_SPACE=$(df |grep /www|awk '{print $4}')
|
||||
ROOT_DISK_SPACE=$(df |grep /$|awk '{print $4}')
|
||||
|
||||
if [ "${ROOT_DISK_SPACE}" -le 412000 ];then
|
||||
df -h
|
||||
echo -e "系统盘剩余空间不足400M 无法继续安装宝塔面板!"
|
||||
echo -e "请尝试清理磁盘空间后再重新进行安装"
|
||||
exit 1
|
||||
fi
|
||||
if [ "${WWW_DISK_SPACE}" ] && [ "${WWW_DISK_SPACE}" -le 412000 ] ;then
|
||||
echo -e "/www盘剩余空间不足400M 无法继续安装宝塔面板!"
|
||||
echo -e "请尝试清理磁盘空间后再重新进行安装"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ROOT_DISK_INODE=$(df -i|grep /$|awk '{print $2}')
|
||||
if [ "${ROOT_DISK_INODE}" != "0" ];then
|
||||
ROOT_DISK_INODE_FREE=$(df -i|grep /$|awk '{print $4}')
|
||||
if [ "${ROOT_DISK_INODE_FREE}" -le 1000 ];then
|
||||
echo -e "系统盘剩余inodes空间不足1000,无法继续安装!"
|
||||
echo -e "请尝试清理磁盘空间后再重新进行安装"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
WWW_DISK_INODE==$(df -i|grep /www|awk '{print $2}')
|
||||
if [ "${WWW_DISK_INODE}" ] && [ "${WWW_DISK_INODE}" != "0" ] ;then
|
||||
WWW_DISK_INODE_FREE=$(df -i|grep /www|awk '{print $4}')
|
||||
if [ "${WWW_DISK_INODE_FREE}" ] && [ "${WWW_DISK_INODE_FREE}" -le 1000 ] ;then
|
||||
echo -e "/www盘剩余inodes空间不足1000, 无法继续安装!"
|
||||
echo -e "请尝试清理磁盘空间后再重新进行安装"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
Centos6Check=$(cat /etc/redhat-release | grep ' 6.' | grep -iE 'centos|Red Hat')
|
||||
if [ "${Centos6Check}" ];then
|
||||
echo "Centos6不支持安装宝塔面板,请更换Centos7/8安装宝塔面板"
|
||||
@@ -69,13 +28,14 @@ fi
|
||||
|
||||
UbuntuCheck=$(cat /etc/issue|grep Ubuntu|awk '{print $2}'|cut -f 1 -d '.')
|
||||
if [ "${UbuntuCheck}" ] && [ "${UbuntuCheck}" -lt "16" ];then
|
||||
echo "Ubuntu ${UbuntuCheck}不支持安装宝塔面板,建议更换Ubuntu22/24安装宝塔面板"
|
||||
echo "Ubuntu ${UbuntuCheck}不支持安装宝塔面板,建议更换Ubuntu18/20安装宝塔面板"
|
||||
exit 1
|
||||
fi
|
||||
HOSTNAME_CHECK=$(cat /etc/hostname)
|
||||
if [ -z "${HOSTNAME_CHECK}" ];then
|
||||
echo "当前主机名hostname为空无法安装宝塔面板,请咨询服务器运营商设置好hostname后再重新安装"
|
||||
exit 1
|
||||
echo "localhost" > /etc/hostname
|
||||
# echo "当前主机名hostname为空无法安装宝塔面板,请咨询服务器运营商设置好hostname后再重新安装"
|
||||
# exit 1
|
||||
fi
|
||||
|
||||
UBUNTU_NO_LTS=$(cat /etc/issue|grep Ubuntu|grep -E "19|21|23|25")
|
||||
@@ -101,6 +61,43 @@ panelPort=$(expr $RANDOM % 55535 + 10000)
|
||||
# IDC_CODE=$1
|
||||
# fi
|
||||
|
||||
Ready_Check(){
|
||||
WWW_DISK_SPACE=$(df |grep /www|awk '{print $4}')
|
||||
ROOT_DISK_SPACE=$(df |grep /$|awk '{print $4}')
|
||||
|
||||
if [ "${ROOT_DISK_SPACE}" -le 412000 ];then
|
||||
df -h
|
||||
echo -e "系统盘剩余空间不足400M 无法继续安装宝塔面板!"
|
||||
echo -e "请尝试清理磁盘空间后再重新进行安装"
|
||||
exit 1
|
||||
fi
|
||||
if [ "${WWW_DISK_SPACE}" ] && [ "${WWW_DISK_SPACE}" -le 412000 ] ;then
|
||||
echo -e "/www盘剩余空间不足400M 无法继续安装宝塔面板!"
|
||||
echo -e "请尝试清理磁盘空间后再重新进行安装"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ROOT_DISK_INODE=$(df -i|grep /$|awk '{print $2}')
|
||||
# if [ "${ROOT_DISK_INODE}" != "0" ];then
|
||||
# ROOT_DISK_INODE_FREE=$(df -i|grep /$|awk '{print $4}')
|
||||
# if [ "${ROOT_DISK_INODE_FREE}" -le 1000 ];then
|
||||
# echo -e "系统盘剩余inodes空间不足1000,无法继续安装!"
|
||||
# echo -e "请尝试清理磁盘空间后再重新进行安装"
|
||||
# exit 1
|
||||
# fi
|
||||
# fi
|
||||
|
||||
# WWW_DISK_INODE==$(df -i|grep /www|awk '{print $2}')
|
||||
# if [ "${WWW_DISK_INODE}" ] && [ "${WWW_DISK_INODE}" != "0" ] ;then
|
||||
# WWW_DISK_INODE_FREE=$(df -i|grep /www|awk '{print $4}')
|
||||
# if [ "${WWW_DISK_INODE_FREE}" ] && [ "${WWW_DISK_INODE_FREE}" -le 1000 ] ;then
|
||||
# echo -e "/www盘剩余inodes空间不足1000, 无法继续安装!"
|
||||
# echo -e "请尝试清理磁盘空间后再重新进行安装"
|
||||
# exit 1
|
||||
# fi
|
||||
# fi
|
||||
}
|
||||
|
||||
GetSysInfo(){
|
||||
if [ -s "/etc/redhat-release" ];then
|
||||
SYS_VERSION=$(cat /etc/redhat-release)
|
||||
@@ -126,6 +123,28 @@ GetSysInfo(){
|
||||
echo -e "如是新安装系统服务器建议更换至Debian-12/Ubuntu-22/Centos-9系统安装宝塔面板"
|
||||
echo -e "============================================"
|
||||
fi
|
||||
|
||||
|
||||
if [ -f "/usr/sbin/setstatus" ] || [ -f "/usr/sbin/setstatus" ];then
|
||||
echo -e "=================================================="
|
||||
echo -e " 检测到为麒麟系统,可能默认开启安全功能导致安装失败"
|
||||
echo -e " 请执行以下命令关闭安全加固后,再重新安装宝塔面板看是否正常"
|
||||
echo -e " 命令:sudo setstatus softmode -p"
|
||||
echo -e "=================================================="
|
||||
fi
|
||||
|
||||
SYS_SSL_LIBS=$(pkg-config --list-all | grep -q libssl)
|
||||
if [ -z "$SYS_SSL_LIBS" ];then
|
||||
echo "检测到缺少系统ssl相关依赖,可执行下面命令安装依赖后再重新安装宝塔看是否正常"
|
||||
echo "执行前请确保系统源正常"
|
||||
if [ -f "/usr/bin/yum" ];then
|
||||
echo "安装依赖命令: yum install openssl-devel -y"
|
||||
elif [ -f "/usr/bin/apt-get" ];then
|
||||
echo "安装依赖命令: apt-get install libssl-dev -y"
|
||||
fi
|
||||
rm -rf /www/server/panel/pyenv
|
||||
echo -e "=================================================="
|
||||
fi
|
||||
}
|
||||
Red_Error(){
|
||||
echo '=================================================';
|
||||
@@ -175,11 +194,38 @@ Set_Ssl(){
|
||||
fi
|
||||
}
|
||||
Add_lib_Install(){
|
||||
Get_Versions
|
||||
if [ "${os_type}" == "el" ] && [ "${os_version}" == "7" ];then
|
||||
if [ -f "/etc/os-release" ];then
|
||||
. /etc/os-release
|
||||
OS_V=${VERSION_ID%%.*}
|
||||
if [ "${ID}" == "debian" ] && [[ "${OS_V}" =~ ^(11|12)$ ]];then
|
||||
OS_NAME=${ID}
|
||||
elif [ "${ID}" == "ubuntu" ] && [[ "${OS_V}" =~ ^(22|24)$ ]];then
|
||||
OS_NAME=${ID}
|
||||
elif [ "${ID}" == "centos" ] && [[ "${OS_V}" =~ ^(7)$ ]];then
|
||||
OS_NAME="el"
|
||||
elif [ "${ID}" == "opencloudos" ] && [[ "${OS_V}" =~ ^(9)$ ]];then
|
||||
OS_NAME=${ID}
|
||||
elif [ "${ID}" == "tencentos" ] && [[ "${OS_V}" =~ ^(4)$ ]];then
|
||||
OS_NAME=${ID}
|
||||
elif [ "${ID}" == "hce" ] && [[ "${OS_V}" =~ ^(2)$ ]];then
|
||||
OS_NAME=${ID}
|
||||
elif { [ "${ID}" == "almalinux" ] || [ "${ID}" == "centos" ] || [ "${ID}" == "rocky" ]; } && [[ "${OS_V}" =~ ^(9)$ ]]; then
|
||||
OS_NAME="el"
|
||||
fi
|
||||
fi
|
||||
|
||||
X86_CHECK=$(uname -m|grep x86_64)
|
||||
|
||||
if [ "${OS_NAME}" ] && [ "${X86_CHECK}" ];then
|
||||
if [ "${PM}" = "yum" ]; then
|
||||
mtype="1"
|
||||
elif [ "${PM}" = "apt-get" ]; then
|
||||
mtype="4"
|
||||
fi
|
||||
cd /www/server/panel/class
|
||||
#btpython -c "import panelPlugin; plugin = panelPlugin.panelPlugin(); plugin.check_install_lib('1')"
|
||||
#echo "True" > /tmp/panelTask.pl
|
||||
btpython -c "import panelPlugin; plugin = panelPlugin.panelPlugin(); plugin.check_install_lib('${mtype}')"
|
||||
echo "True" > /tmp/panelTask.pl
|
||||
echo "True" > /www/server/panel/install/ins_lib.pl
|
||||
fi
|
||||
}
|
||||
Get_Pack_Manager(){
|
||||
@@ -189,6 +235,67 @@ Get_Pack_Manager(){
|
||||
PM="apt-get"
|
||||
fi
|
||||
}
|
||||
Set_Repo_Url(){
|
||||
if [ "${PM}"="apt-get" ];then
|
||||
ALI_CLOUD_CHECK=$(grep Alibaba /etc/motd)
|
||||
Tencent_Cloud=$(cat /etc/hostname |grep -E VM-[0-9]+-[0-9]+)
|
||||
if [ "${ALI_CLOUD_CHECK}" ] || [ "${Tencent_Cloud}" ];then
|
||||
return
|
||||
fi
|
||||
|
||||
CN_CHECK=$(curl -sS --connect-timeout 10 -m 10 https://api.bt.cn/api/isCN)
|
||||
if [ "${CN_CHECK}" == "True" ];then
|
||||
SOURCE_URL_CHECK=$(grep -E 'security.ubuntu.com|archive.ubuntu.com|security.debian.org|deb.debian.org' /etc/apt/sources.list)
|
||||
# if [ -f "/etc/apt/sources.list.d/ubuntu.sources" ];then
|
||||
# SOURCE_URL_CHECK=$(grep -E 'security.ubuntu.com|archive.ubuntu.com|security.debian.org|deb.debian.org' /etc/apt/sources.list.d/ubuntu.sources)
|
||||
# fi
|
||||
fi
|
||||
|
||||
#GET_SOURCES_URL=$(cat /etc/apt/sources.list|grep ^deb|head -n 1|awk -F[/:] '{print $4}')
|
||||
GET_SOURCES_URL=$(cat /etc/apt/sources.list|grep ^deb|head -n 1|sed -E 's|^[^ ]+ https?://([^/]+).*|\1|')
|
||||
# if [ -f "/etc/apt/sources.list.d/ubuntu.sources" ];then
|
||||
# GET_SOURCES_URL=$(cat /etc/apt/sources.list.d/ubuntu.sources|grep URIs:|head -n 1|sed -E 's|^[^ ]+ https?://([^/]+).*|\1|')
|
||||
# fi
|
||||
NODE_CHECK=$(curl --connect-timeout 3 -m 3 2>/dev/null -w "%{http_code} %{time_total}" ${GET_SOURCES_URL} -o /dev/null)
|
||||
NODE_STATUS=$(echo ${NODE_CHECK}|awk '{print $1}')
|
||||
TIME_TOTAL=$(echo ${NODE_CHECK}|awk '{print $2 * 1000}'|cut -d '.' -f 1)
|
||||
|
||||
if { [ "${NODE_STATUS}" != "200" ] && [ "${NODE_STATUS}" != "301" ]; } || [ "${TIME_TOTAL}" -ge "150" ] || [ "${SOURCE_URL_CHECK}" ]; then
|
||||
\cp -rpa /etc/apt/sources.list /etc/apt/sources.list.btbackup
|
||||
apt_lists=(mirrors.cloud.tencent.com mirrors.163.com repo.huaweicloud.com mirrors.tuna.tsinghua.edu.cn mirrors.aliyun.com mirrors.ustc.edu.cn )
|
||||
for list in ${apt_lists[@]};
|
||||
do
|
||||
NODE_CHECK=$(curl --connect-timeout 3 -m 3 2>/dev/null -w "%{http_code} %{time_total}" ${list} -o /dev/null)
|
||||
NODE_STATUS=$(echo ${NODE_CHECK}|awk '{print $1}')
|
||||
TIME_TOTAL=$(echo ${NODE_CHECK}|awk '{print $2 * 1000}'|cut -d '.' -f 1)
|
||||
if [ "${NODE_STATUS}" == "200" ] || [ "${NODE_STATUS}" == "301" ];then
|
||||
if [ "${TIME_TOTAL}" -le "150" ];then
|
||||
if [ -f "/etc/apt/sources.list" ];then
|
||||
sed -i "s/${GET_SOURCES_URL}/${list}/g" /etc/apt/sources.list
|
||||
sed -i "s/cn.security.ubuntu.com/${list}/g" /etc/apt/sources.list
|
||||
sed -i "s/cn.archive.ubuntu.com/${list}/g" /etc/apt/sources.list
|
||||
sed -i "s/security.ubuntu.com/${list}/g" /etc/apt/sources.list
|
||||
sed -i "s/archive.ubuntu.com/${list}/g" /etc/apt/sources.list
|
||||
sed -i "s/security.debian.org/${list}/g" /etc/apt/sources.list
|
||||
sed -i "s/deb.debian.org/${list}/g" /etc/apt/sources.list
|
||||
fi
|
||||
# if [ -f "/etc/apt/sources.list.d/ubuntu.sources" ];then
|
||||
# \cp -rpa /etc/apt/sources.list.d/ubuntu.sources /etc/apt/sources.list.d/ubuntu.sources.bak
|
||||
# sed -i "s/${GET_SOURCES_URL}/${list}/g" /etc/apt/sources.list.d/ubuntu.sources
|
||||
# sed -i "s/cn.security.ubuntu.com/${list}/g" /etc/apt/sources.list.d/ubuntu.sources
|
||||
# sed -i "s/cn.archive.ubuntu.com/${list}/g" /etc/apt/sources.list.d/ubuntu.sources
|
||||
# sed -i "s/security.ubuntu.com/${list}/g" /etc/apt/sources.list.d/ubuntu.sources
|
||||
# sed -i "s/archive.ubuntu.com/${list}/g" /etc/apt/sources.list.d/ubuntu.sources
|
||||
# sed -i "s/security.debian.org/${list}/g" /etc/apt/sources.list.d/ubuntu.sources
|
||||
# sed -i "s/deb.debian.org/${list}/g" /etc/apt/sources.list.d/ubuntu.sources
|
||||
# fi
|
||||
break;
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
fi
|
||||
}
|
||||
Auto_Swap()
|
||||
{
|
||||
swap=$(free |grep Swap|awk '{print $2}')
|
||||
@@ -278,14 +385,7 @@ Set_Centos7_Repo(){
|
||||
if [ "$?" != "0" ] ;then
|
||||
sed -i "s/vault.epel.cloud/mirrors.cloud.tencent.com/g" /etc/yum.repos.d/*.repo
|
||||
fi
|
||||
|
||||
}
|
||||
# Set_Centos7_Repo(){
|
||||
# if [ -z "${download_Url}" ];then
|
||||
# download_Url="http://download.bt.cn"
|
||||
# fi
|
||||
# curl -Ss --connect-timeout 3 -m 60 ${download_Url}/install/vault-repo.sh|bash
|
||||
# }
|
||||
Set_Centos8_Repo(){
|
||||
HUAWEI_CHECK=$(cat /etc/motd |grep "Huawei Cloud")
|
||||
if [ "${HUAWEI_CHECK}" ] && [ "${is64bit}" == "64" ];then
|
||||
@@ -324,12 +424,16 @@ Set_Centos8_Repo(){
|
||||
rm -f /etc/yum.repos.d/*.repo
|
||||
tar -xvzf el8repo.tar.gz -C /etc/yum.repos.d/
|
||||
fi
|
||||
yum install unzip -y
|
||||
|
||||
yum install unzip tar -y
|
||||
if [ "$?" != "0" ] ;then
|
||||
sed -i "s/vault.epel.cloud/mirrors.cloud.tencent.com/g" /etc/yum.repos.d/*.repo
|
||||
fi
|
||||
}
|
||||
get_node_url(){
|
||||
if [ "${PM}" = "yum" ]; then
|
||||
yum install wget -y
|
||||
fi
|
||||
if [ ! -f /bin/curl ];then
|
||||
if [ "${PM}" = "yum" ]; then
|
||||
yum install curl -y
|
||||
@@ -432,7 +536,7 @@ Install_RPM_Pack(){
|
||||
sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.epel.cloud|g' /etc/yum.repos.d/CentOS-*.repo
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
Centos8Check=$(cat /etc/redhat-release | grep ' 8.' | grep -iE 'centos|Red Hat')
|
||||
if [ "${Centos8Check}" ];then
|
||||
Set_Centos8_Repo
|
||||
@@ -483,7 +587,7 @@ Install_RPM_Pack(){
|
||||
|
||||
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
|
||||
#yum remove -y python-requests python3-requests python-greenlet python3-greenlet
|
||||
yumPacks="libcurl-devel wget tar gcc make zip unzip openssl openssl-devel gcc libxml2 libxml2-devel libxslt* zlib zlib-devel libjpeg-devel libpng-devel libwebp libwebp-devel freetype freetype-devel lsof pcre pcre-devel vixie-cron crontabs icu libicu-devel c-ares libffi-devel bzip2-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel qrencode"
|
||||
yumPacks="libcurl-devel wget tar gcc make zip unzip openssl openssl-devel gcc libxml2 libxml2-devel libxslt* zlib zlib-devel libjpeg-devel libpng-devel libwebp libwebp-devel freetype freetype-devel lsof pcre pcre-devel vixie-cron crontabs icu libicu-devel c-ares libffi-devel bzip2-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel qrencode at mariadb rsyslog net-tools"
|
||||
yum install -y ${yumPacks}
|
||||
|
||||
for yumPack in ${yumPacks}
|
||||
@@ -506,7 +610,8 @@ Install_RPM_Pack(){
|
||||
Install_Deb_Pack(){
|
||||
ln -sf bash /bin/sh
|
||||
UBUNTU_22=$(cat /etc/issue|grep "Ubuntu 22")
|
||||
if [ "${UBUNTU_22}" ];then
|
||||
UBUNTU_24=$(cat /etc/issue|grep "Ubuntu 24")
|
||||
if [ "${UBUNTU_22}" ] || [ "${UBUNTU_24}" ];then
|
||||
apt-get remove needrestart -y
|
||||
fi
|
||||
ALIYUN_CHECK=$(cat /etc/motd|grep "Alibaba Cloud ")
|
||||
@@ -514,6 +619,13 @@ Install_Deb_Pack(){
|
||||
apt-get remove libicu70 -y
|
||||
fi
|
||||
apt-get update -y
|
||||
|
||||
FNOS_CHECK=$(cat /etc/issue|grep fnOS)
|
||||
if [ "${FNOS_CHECK}" ];then
|
||||
apt-get install libc6 --allow-change-held-packages -y
|
||||
apt-get install libc6-dev --allow-change-held-packages -y
|
||||
fi
|
||||
|
||||
apt-get install bash -y
|
||||
if [ -f "/usr/bin/bash" ];then
|
||||
ln -sf /usr/bin/bash /bin/sh
|
||||
@@ -537,7 +649,7 @@ Install_Deb_Pack(){
|
||||
apt-get install curl -y
|
||||
fi
|
||||
|
||||
debPacks="wget curl libcurl4-openssl-dev gcc make zip unzip tar openssl libssl-dev gcc libxml2 libxml2-dev zlib1g zlib1g-dev libjpeg-dev libpng-dev lsof libpcre3 libpcre3-dev cron net-tools swig build-essential libffi-dev libbz2-dev libncurses-dev libsqlite3-dev libreadline-dev tk-dev libgdbm-dev libdb-dev libdb++-dev libpcap-dev xz-utils git qrencode sqlite3";
|
||||
debPacks="wget curl libcurl4-openssl-dev gcc make zip unzip tar openssl libssl-dev gcc libxml2 libxml2-dev zlib1g zlib1g-dev libjpeg-dev libpng-dev lsof libpcre3 libpcre3-dev cron net-tools swig build-essential libffi-dev libbz2-dev libncurses-dev libsqlite3-dev libreadline-dev tk-dev libgdbm-dev libdb-dev libdb++-dev libpcap-dev xz-utils git qrencode sqlite3 at mariadb-client rsyslog net-tools";
|
||||
apt-get install -y $debPacks --force-yes
|
||||
|
||||
for debPack in ${debPacks}
|
||||
@@ -738,10 +850,10 @@ Install_Python_Lib(){
|
||||
echo "==============================================="
|
||||
if [ "${os_version}" != "" ];then
|
||||
pyenv_file="/www/pyenv.tar.gz"
|
||||
wget -O $pyenv_file $download_Url/install/pyenv/pyenv-${os_type}${os_version}-x${is64bit}.tar.gz -T 15
|
||||
wget -O $pyenv_file $download_Url/install/pyenv/pyenv-${os_type}${os_version}-x${is64bit}.tar.gz -T 20
|
||||
if [ "$?" != "0" ];then
|
||||
get_node_url $download_Url
|
||||
wget -O $pyenv_file $download_Url/install/pyenv/pyenv-${os_type}${os_version}-x${is64bit}.tar.gz -T 15
|
||||
wget -O $pyenv_file $download_Url/install/pyenv/pyenv-${os_type}${os_version}-x${is64bit}.tar.gz -T 20
|
||||
fi
|
||||
tmp_size=$(du -b $pyenv_file|awk '{print $1}')
|
||||
if [ $tmp_size -lt 703460 ];then
|
||||
@@ -803,6 +915,7 @@ Install_Python_Lib(){
|
||||
$pyenv_path/pyenv/bin/pip install -r $pyenv_path/pyenv/pip.txt
|
||||
|
||||
wget -O pip-packs.txt $download_Url/install/pyenv/pip-packs.txt
|
||||
echo "正在后台安装pip依赖请稍等.........."
|
||||
PIP_PACKS=$(cat pip-packs.txt)
|
||||
for P_PACK in ${PIP_PACKS};
|
||||
do
|
||||
@@ -882,7 +995,27 @@ Install_Bt(){
|
||||
yum install unzip -y
|
||||
elif [ "${PM}" = "apt-get" ]; then
|
||||
apt-get update
|
||||
apt-get install unzip -y
|
||||
apt-get install unzip -y 2>&1|tee /tmp/apt_install_log.log
|
||||
UNZIP_CHECK=$(which unzip)
|
||||
if [ "$?" != "0" ];then
|
||||
RECONFIGURE_CHECK=$(grep "dpkg --configure -a" /tmp/apt_install_log.log)
|
||||
if [ "${RECONFIGURE_CHECK}" ];then
|
||||
dpkg --configure -a
|
||||
fi
|
||||
APT_LOCK_CHECH=$(grep "/var/lib/dpkg/lock" /tmp/apt_install_log.log)
|
||||
if [ "${APT_LOCK_CHECH}" ];then
|
||||
pkill dpkg
|
||||
pkill apt-get
|
||||
pkill apt
|
||||
[ -e /var/lib/dpkg/lock-frontend ] && rm -f /var/lib/dpkg/lock-frontend
|
||||
[ -e /var/lib/dpkg/lock ] && rm -f /var/lib/dpkg/lock
|
||||
[ -e /var/lib/apt/lists/lock ] && rm -f /var/lib/apt/lists/lock
|
||||
[ -e /var/cache/apt/archives/lock ] && rm -f /var/cache/apt/archives/lock
|
||||
dpkg --configure -a
|
||||
fi
|
||||
sleep 5
|
||||
apt-get install unzip -y
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -931,7 +1064,7 @@ Install_Bt(){
|
||||
echo "True" > /www/server/panel/data/not_workorder.pl
|
||||
fi
|
||||
if [ ! -f /www/server/panel/data/userInfo.json ]; then
|
||||
echo "{\"uid\":1,\"username\":\"Administrator\",\"address\":\"127.0.0.1\",\"serverid\":\"1\",\"access_key\":\"test\",\"secret_key\":\"123456\",\"ukey\":\"123456\",\"state\":1}" > /www/server/panel/data/userInfo.json
|
||||
echo "{\"uid\":1,\"username\":\"Administrator\",\"address\":\"127.0.0.1\",\"access_key\":\"test\",\"secret_key\":\"123456\",\"ukey\":\"123456\",\"state\":1}" > /www/server/panel/data/userInfo.json
|
||||
fi
|
||||
if [ ! -f /www/server/panel/data/panel_nps.pl ]; then
|
||||
echo "" > /www/server/panel/data/panel_nps.pl
|
||||
@@ -1023,6 +1156,7 @@ Set_Bt_Panel(){
|
||||
touch t.pl
|
||||
ls -al python3.7 python
|
||||
lsattr python3.7 python
|
||||
btpython /www/server/panel/BT-Panel
|
||||
Red_Error "ERROR: The BT-Panel service startup failed." "ERROR: 宝塔启动失败"
|
||||
fi
|
||||
|
||||
@@ -1098,7 +1232,40 @@ Set_Firewall(){
|
||||
}
|
||||
Get_Ip_Address(){
|
||||
getIpAddress=""
|
||||
getIpAddress=$(curl -sS --connect-timeout 10 -m 60 https://www.bt.cn/Api/getIpAddress)
|
||||
#getIpAddress=$(curl -sS --connect-timeout 10 -m 60 https://www.bt.cn/Api/getIpAddress)
|
||||
|
||||
ipv4_address=""
|
||||
ipv6_address=""
|
||||
|
||||
ipv4_address=$(curl -4 -sS --connect-timeout 4 -m 5 https://api.bt.cn/Api/getIpAddress 2>&1)
|
||||
if [ -z "${ipv4_address}" ];then
|
||||
ipv4_address=$(curl -4 -sS --connect-timeout 4 -m 5 https://www.bt.cn/Api/getIpAddress 2>&1)
|
||||
if [ -z "${ipv4_address}" ];then
|
||||
ipv4_address=$(curl -4 -sS --connect-timeout 4 -m 5 https://www.aapanel.com/api/common/getClientIP 2>&1)
|
||||
fi
|
||||
fi
|
||||
IPV4_REGEX="^([0-9]{1,3}\.){3}[0-9]{1,3}$"
|
||||
if ! [[ $ipv4_address =~ $IPV4_REGEX ]]; then
|
||||
ipv4_address=""
|
||||
fi
|
||||
|
||||
ipv6_address=$(curl -6 -sS --connect-timeout 4 -m 5 https://www.bt.cn/Api/getIpAddress 2>&1)
|
||||
IPV6_REGEX="^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$"
|
||||
if ! [[ $ipv6_address =~ $IPV6_REGEX ]]; then
|
||||
ipv6_address=""
|
||||
else
|
||||
if [[ ! $ipv6_address =~ ^\[ ]]; then
|
||||
ipv6_address="[$ipv6_address]"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "${ipv4_address}" ];then
|
||||
getIpAddress=$ipv4_address
|
||||
elif [ "${ipv6_address}" ];then
|
||||
getIpAddress=$ipv6_address
|
||||
fi
|
||||
|
||||
|
||||
if [ -z "${getIpAddress}" ] || [ "${getIpAddress}" = "0.0.0.0" ]; then
|
||||
isHosts=$(cat /etc/hosts|grep 'www.bt.cn')
|
||||
if [ -z "${isHosts}" ];then
|
||||
@@ -1109,6 +1276,13 @@ Get_Ip_Address(){
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
CN_CHECK=$(curl -sS --connect-timeout 10 -m 10 http://www.example.com/api/isCN)
|
||||
if [ "${CN_CHECK}" == "True" ];then
|
||||
echo "True" > /www/server/panel/data/domestic_ip.pl
|
||||
else
|
||||
echo "True" > /www/server/panel/data/foreign_ip.pl
|
||||
fi
|
||||
|
||||
ipv4Check=$($python_bin -c "import re; print(re.match('^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$','${getIpAddress}'))")
|
||||
if [ "${ipv4Check}" == "None" ];then
|
||||
@@ -1120,6 +1294,7 @@ Get_Ip_Address(){
|
||||
echo "True" > ${setup_path}/server/panel/data/ipv6.pl
|
||||
sleep 1
|
||||
/etc/init.d/bt restart
|
||||
getIpAddress=$(echo "[$getIpAddress]")
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -1144,6 +1319,7 @@ Install_Main(){
|
||||
Lock_Clear
|
||||
System_Check
|
||||
Get_Pack_Manager
|
||||
Set_Repo_Url
|
||||
get_node_url
|
||||
|
||||
MEM_TOTAL=$(free -g|grep Mem|awk '{print $2}')
|
||||
@@ -1182,6 +1358,7 @@ echo "
|
||||
+----------------------------------------------------------------------
|
||||
"
|
||||
|
||||
|
||||
while [ ${#} -gt 0 ]; do
|
||||
case $1 in
|
||||
-u|--user)
|
||||
@@ -1245,6 +1422,7 @@ if [ -f "/www/server/panel/BT-Panel" ];then
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
ARCH_LINUX=$(cat /etc/os-release |grep "Arch Linux")
|
||||
if [ "${ARCH_LINUX}" ] && [ -f "/usr/bin/pacman" ];then
|
||||
pacman -Sy
|
||||
@@ -1265,21 +1443,26 @@ echo -e "=================================================================="
|
||||
echo -e "\033[32mCongratulations! Installed successfully!\033[0m"
|
||||
echo -e "========================面板账户登录信息=========================="
|
||||
echo -e ""
|
||||
echo -e " 外网面板地址: ${HTTP_S}://${getIpAddress}:${panelPort}${auth_path}"
|
||||
echo -e " 内网面板地址: ${HTTP_S}://${LOCAL_IP}:${panelPort}${auth_path}"
|
||||
echo -e " 【云服务器】请在安全组放行 $panelPort 端口"
|
||||
if [ -z "${ipv4_address}" ] && [ -z "${ipv6_address}" ];then
|
||||
echo -e " 外网面板地址: ${HTTP_S}://SERVER_IP:${panelPort}${auth_path}"
|
||||
fi
|
||||
if [ "${ipv4_address}" ];then
|
||||
echo -e " 外网ipv4面板地址: ${HTTP_S}://${ipv4_address}:${panelPort}${auth_path}"
|
||||
fi
|
||||
if [ "${ipv6_address}" ];then
|
||||
echo -e " 外网ipv6面板地址: ${HTTP_S}://${ipv6_address}:${panelPort}${auth_path}"
|
||||
fi
|
||||
echo -e " 内网面板地址: ${HTTP_S}://${LOCAL_IP}:${panelPort}${auth_path}"
|
||||
echo -e " username: $username"
|
||||
echo -e " password: $password"
|
||||
echo -e " "
|
||||
echo -e "=========================打开面板前请看==========================="
|
||||
echo -e ""
|
||||
echo -e " 【云服务器】请在安全组放行 $panelPort 端口"
|
||||
echo -e " 因默认启用自签证书https加密访问,浏览器将提示不安全"
|
||||
echo -e " 点击【高级】-【继续访问】或【接受风险并继续】访问"
|
||||
echo -e " 教程:https://www.bt.cn/bbs/thread-117246-1-1.html"
|
||||
echo -e ""
|
||||
echo -e "=================================================================="
|
||||
endTime=`date +%s`
|
||||
((outTime=($endTime-$startTime)/60))
|
||||
if [ "${outTime}" -le "5" ];then
|
||||
echo ${download_Url} > /www/server/panel/install/d_node.pl
|
||||
fi
|
||||
if [ "${outTime}" == "0" ];then
|
||||
((outTime=($endTime-$startTime)))
|
||||
echo -e "Time consumed:\033[32m $outTime \033[0mseconds!"
|
@@ -14,9 +14,31 @@ if [ "${NODE_FILE_CHECK}" ];then
|
||||
rm -f /www/server/panel/data/node.json
|
||||
fi
|
||||
|
||||
if [ -f "/www/server/panel/install/d_node.pl" ];then
|
||||
LOCAL_DATE=$(date +%Y-%m-%d)
|
||||
FILE_DATE=$(stat /www/server/panel/install/d_node.pl|grep Change|awk '{print $2}')
|
||||
if [ "${LOCAL_DATE}" != "${FILE_DATE}" ];then
|
||||
rm -f /www/server/panel/install/d_node.pl
|
||||
else
|
||||
test_url=$(cat /www/server/panel/install/d_node.pl)
|
||||
HTTP_CHECK=$(curl --connect-timeout 3 -m 3 2>/dev/null -w "%{http_code} %{time_total}" ${test_url}/net_test|xargs|awk '{print $2}')
|
||||
if [ "${HTTP_CHECK}" == "200" ];then
|
||||
NODE_URL=$test_url
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
get_node_url(){
|
||||
nodes=(https://dg2.bt.cn https://download.bt.cn https://ctcc1-node.bt.cn https://cmcc1-node.bt.cn https://ctcc2-node.bt.cn https://hk1-node.bt.cn https://na1-node.bt.cn https://jp1-node.bt.cn https://cf1-node.aapanel.com);
|
||||
|
||||
if [ -f "/www/server/panel/data/domestic_ip.pl" ];then
|
||||
nodes=(https://dg2.bt.cn https://download.bt.cn https://ctcc1-node.bt.cn https://cmcc1-node.bt.cn https://ctcc2-node.bt.cn https://hk1-node.bt.cn);
|
||||
fi
|
||||
|
||||
if [ -f "/www/server/panel/data/foreign_ip.pl" ];then
|
||||
nodes=(https://cf1-node.aapanel.com https://dg2.bt.cn https://na1-node.bt.cn https://jp1-node.bt.cn https://download.bt.cn https://ctcc1-node.bt.cn https://ctcc2-node.bt.cn https://hk1-node.bt.cn);
|
||||
fi
|
||||
|
||||
if [ "$1" ];then
|
||||
nodes=($(echo ${nodes[*]}|sed "s#${1}##"))
|
||||
fi
|
||||
@@ -29,7 +51,11 @@ get_node_url(){
|
||||
touch $tmp_file2
|
||||
for node in ${nodes[@]};
|
||||
do
|
||||
NODE_CHECK=$(curl --connect-timeout 3 -m 3 2>/dev/null -w "%{http_code} %{time_total}" ${node}/net_test|xargs)
|
||||
if [ "${node}" == "https://cf1-node.aapanel.com" ];then
|
||||
NODE_CHECK=$(curl --connect-timeout 3 -m 3 2>/dev/null -w "%{http_code} %{time_total}" ${node}/1net_test|xargs)
|
||||
else
|
||||
NODE_CHECK=$(curl --connect-timeout 3 -m 3 2>/dev/null -w "%{http_code} %{time_total}" ${node}/net_test|xargs)
|
||||
fi
|
||||
RES=$(echo ${NODE_CHECK}|awk '{print $1}')
|
||||
NODE_STATUS=$(echo ${NODE_CHECK}|awk '{print $2}')
|
||||
TIME_TOTAL=$(echo ${NODE_CHECK}|awk '{print $3 * 1000 - 500 }'|cut -d '.' -f 1)
|
||||
@@ -113,7 +139,7 @@ send_check(){
|
||||
chmod +x /etc/init.d/bt
|
||||
p_path2=/www/server/panel/class/common.py
|
||||
p_version=$(cat $p_path2|grep "version = "|awk '{print $3}'|tr -cd [0-9.])
|
||||
curl -sS --connect-timeout 3 -m 60 https://www.bt.cn/api/panel/notpro?version=$p_version
|
||||
curl -sS --connect-timeout 3 -m 60 http://www.example.com/api/panel/notpro?version=$p_version
|
||||
NODE_URL=""
|
||||
exit 0;
|
||||
}
|
||||
|
Binary file not shown.
BIN
public/install/src/panel_7_en.zip
Normal file
BIN
public/install/src/panel_7_en.zip
Normal file
Binary file not shown.
1
public/install/update/LinuxPanel-9.5.0.pl
Normal file
1
public/install/update/LinuxPanel-9.5.0.pl
Normal file
@@ -0,0 +1 @@
|
||||
{"hash": "c097e387cb3f2baf34a222191de7130bd878215ffa4ba8cef2d337e3466e6963", "update_time": "1747723203"}
|
1
public/install/update/LinuxPanel-9.6.0.pl
Normal file
1
public/install/update/LinuxPanel-9.6.0.pl
Normal file
@@ -0,0 +1 @@
|
||||
{"hash": "d869ee4b8bdcfae324c4fdef9ec647db4a1529e7f6890b8cb4693f40b8a24626", "update_time": "1748242787"}
|
BIN
public/install/update/LinuxPanel-9.6.0.zip
Normal file
BIN
public/install/update/LinuxPanel-9.6.0.zip
Normal file
Binary file not shown.
Binary file not shown.
@@ -102,8 +102,8 @@ if [ -f "/etc/redhat-release" ];then
|
||||
fi
|
||||
setup_path=/www
|
||||
version=$(curl -Ss --connect-timeout 5 -m 2 $Btapi_Url/api/panel/get_version)
|
||||
if [ -z "$VERSION_CHECK" ];then
|
||||
version='9.2.0'
|
||||
if [ -z "$version" ];then
|
||||
version='9.5.0'
|
||||
fi
|
||||
armCheck=$(uname -m|grep arm)
|
||||
if [ "${armCheck}" ];then
|
||||
@@ -136,6 +136,33 @@ rm -f /www/server/panel/class/*.pyc
|
||||
#pip install flask_sqlalchemy
|
||||
#pip install itsdangerous==0.24
|
||||
|
||||
if [ -f "/www/server/panel/pyenv/bin/pip3" ];then
|
||||
btpip_path="/www/server/panel/pyenv/bin/pip3"
|
||||
FlaskV=$($btpip_path list 2>/dev/null|grep "Flask " |awk '{print $2}'|cut -f 1 -d .)
|
||||
piplist_count=$($btpip_path list 2>/dev/null|wc -l)
|
||||
if [ "${FlaskV}" -le "2" ] && [ "${piplist_count}" -le "118" ];then
|
||||
echo "检测到面板运行环境过老,正常尝试修复面板依赖"
|
||||
pyenv_path="/www/server/panel"
|
||||
wget -O $pyenv_path/pyenv/pip.txt $download_Url/install/pyenv/pip-3.7.16.txt -T 5
|
||||
$pyenv_path/pyenv/bin/pip install -U pip
|
||||
$pyenv_path/pyenv/bin/pip install -U setuptools==65.5.0
|
||||
$pyenv_path/pyenv/bin/pip install -U wheel==0.34.2
|
||||
$pyenv_path/pyenv/bin/pip install -r $pyenv_path/pyenv/pip.txt
|
||||
echo "依赖修复完成,如面板仍无法正常访问,请联系宝塔官方人员进行求助"
|
||||
fi
|
||||
|
||||
#wget -O pip-packs.txt $download_Url/install/pyenv/pip-packs.txt
|
||||
#PIP_PACKS=$(cat pip-packs.txt)
|
||||
#for P_PACK in ${PIP_PACKS};
|
||||
#do
|
||||
# btpip show ${P_PACK} > /dev/null 2>&1
|
||||
# if [ "$?" == "1" ];then
|
||||
# btpip install ${P_PACK}
|
||||
# fi
|
||||
#done
|
||||
fi
|
||||
|
||||
|
||||
pip_list=$($mypip list 2>&1)
|
||||
request_v=$(btpip list 2>/dev/null|grep "requests "|awk '{print $2}'|cut -d '.' -f 2)
|
||||
if [ "$request_v" = "" ] || [ "${request_v}" -gt "28" ];then
|
||||
@@ -227,7 +254,7 @@ if [ ! -f /www/server/panel/data/not_workorder.pl ]; then
|
||||
echo "True" > /www/server/panel/data/not_workorder.pl
|
||||
fi
|
||||
if [ ! -f /www/server/panel/data/userInfo.json ]; then
|
||||
echo "{\"uid\":1,\"username\":\"Administrator\",\"address\":\"127.0.0.1\",\"serverid\":\"1\",\"access_key\":\"test\",\"secret_key\":\"123456\",\"ukey\":\"123456\",\"state\":1}" > /www/server/panel/data/userInfo.json
|
||||
echo "{\"uid\":1,\"username\":\"Administrator\",\"address\":\"127.0.0.1\",\"access_key\":\"test\",\"secret_key\":\"123456\",\"ukey\":\"123456\",\"state\":1}" > /www/server/panel/data/userInfo.json
|
||||
fi
|
||||
if [ ! -f /www/server/panel/data/panel_nps.pl ]; then
|
||||
echo "" > /www/server/panel/data/panel_nps.pl
|
||||
|
1017
public/install/update_7.x_en.sh
Normal file
1017
public/install/update_7.x_en.sh
Normal file
File diff suppressed because it is too large
Load Diff
BIN
public/static/file/en/kaixin.zip
Normal file
BIN
public/static/file/en/kaixin.zip
Normal file
Binary file not shown.
Binary file not shown.
BIN
public/static/images/aapanel.png
Normal file
BIN
public/static/images/aapanel.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 94 KiB |
Binary file not shown.
@@ -15,6 +15,7 @@ Route::post('/panel/get_unbinding', 'api/return_success');
|
||||
Route::post('/bt_cert', 'api/bt_cert');
|
||||
Route::post('/Auth/GetAuthToken', 'api/get_auth_token');
|
||||
Route::post('/Auth/GetBindCode', 'api/return_error');
|
||||
Route::post('/auth/GetUserGiveAway', 'api/get_user_give_away');
|
||||
Route::any('/bt_monitor/update_history', 'api/btm_update_history');
|
||||
Route::any('/bt_monitor/latest_version', 'api/btm_latest_version');
|
||||
Route::any('/bt_waf/get_malicious_ip', 'api/get_ssl_list');
|
||||
@@ -40,6 +41,7 @@ Route::group('api', function () {
|
||||
Route::get('/panel/get_version', 'api/get_version');
|
||||
Route::get('/wpanel/get_version', 'api/get_version_win');
|
||||
Route::get('/panel/get_panel_version', 'api/get_panel_version');
|
||||
Route::any('/panel/get_panel_version_v2', 'api/get_panel_version_v2');
|
||||
Route::get('/SetupCount', 'api/setup_count');
|
||||
Route::any('/panel/updateLinux', 'api/check_update');
|
||||
Route::any('/wpanel/updateWindows', 'api/check_update_win');
|
||||
@@ -57,6 +59,7 @@ Route::group('api', function () {
|
||||
Route::post('/Cert/get_order_list', 'api/return_empty_array');
|
||||
Route::post('/Cert/get_product_list', 'api/return_success');
|
||||
Route::get('/Pluginother/get_file', 'api/download_plugin_other');
|
||||
Route::get('/isCN', 'api/check_cnip');
|
||||
|
||||
Route::post('/Pluginother/create_order', 'api/return_success');
|
||||
Route::post('/Pluginother/renew_order', 'api/return_success');
|
||||
@@ -113,11 +116,16 @@ Route::group('api', function () {
|
||||
|
||||
Route::post('/v2/common_v1_authorization/get_pricing', 'api/return_error2');
|
||||
Route::post('/v2/common_v2_authorization/get_pricing', 'api/return_error2');
|
||||
Route::post('/v2/synchron', 'api/return_error2');
|
||||
Route::post('/v2/product/email/user_surplus', 'api/email_user_surplus');
|
||||
Route::post('/v2/product/email', 'api/return_error2');
|
||||
|
||||
Route::any('/bt_waf/getSpiders', 'api/btwaf_getspiders');
|
||||
Route::any('/bt_waf/get_malicious', 'api/btwaf_getmalicious');
|
||||
Route::post('/bt_waf/addSpider', 'api/return_empty');
|
||||
Route::post('/bt_waf/getVulScanInfoList', 'api/return_empty');
|
||||
Route::post('/bt_waf/reportInterceptFail', 'api/return_empty');
|
||||
Route::any('/bt_waf/get_system_malicious', 'api/return_error2');
|
||||
Route::any('/panel/get_spider', 'api/get_spider');
|
||||
|
||||
Route::post('/Auth/GetSocre', 'api/get_ssl_list');
|
||||
@@ -127,6 +135,22 @@ Route::group('api', function () {
|
||||
Route::post('/Cert_cloud_deploy/get_cert_list', 'api/return_success');
|
||||
Route::post('/Cert_cloud_deploy/del_cert', 'api/return_success');
|
||||
|
||||
Route::any('/panel/getSoftList', 'api/get_plugin_list_en');
|
||||
Route::any('/panel/getSoftListEn', 'api/get_plugin_list_en');
|
||||
Route::post('/panel/download_plugin', 'api/download_plugin_en');
|
||||
Route::get('/plugin/download', 'api/download_plugin_other');
|
||||
Route::get('/common/getClientIP', 'api/get_ip_address');
|
||||
Route::post('/panel/checkDomain', 'api/check_domain');
|
||||
Route::get('/panel/getBetaVersionLogs', 'api/get_beta_logs');
|
||||
Route::any('/panel/updateLinuxEn', 'api/check_update_en');
|
||||
Route::post('/user/verifyToken', 'api/return_success');
|
||||
Route::post('/panel/nps/check', 'api/nps_check');
|
||||
Route::post('/panel/nps/questions', 'api/nps_questions');
|
||||
Route::post('/panel/nps/submit', 'api/nps_submit');
|
||||
Route::post('/panel/submit_feature_invoked_bulk', 'api/return_success');
|
||||
Route::post('/panel/submit_expand_pack_used', 'api/return_success');
|
||||
Route::get('/panel/getLatestOfficialVersion', 'api/get_version_en');
|
||||
|
||||
Route::miss('api/return_error');
|
||||
});
|
||||
|
||||
@@ -141,6 +165,7 @@ Route::group('admin', function () {
|
||||
Route::post('/testbturl', 'admin/testbturl');
|
||||
Route::get('/plugins', 'admin/plugins');
|
||||
Route::get('/pluginswin', 'admin/pluginswin');
|
||||
Route::get('/pluginsen', 'admin/pluginsen');
|
||||
Route::post('/plugins_data', 'admin/plugins_data');
|
||||
Route::post('/download_plugin', 'admin/download_plugin');
|
||||
Route::get('/refresh_plugins', 'admin/refresh_plugins');
|
||||
|
115
wiki/aapanel.md
Normal file
115
wiki/aapanel.md
Normal file
@@ -0,0 +1,115 @@
|
||||
# aapanel面板官方更新包修改记录
|
||||
|
||||
查询最新版本号:https://brandnew.aapanel.com/api/panel/getLatestOfficialVersion
|
||||
|
||||
官方更新包下载链接:http://download.bt.cn/install/update/LinuxPanel_EN-版本号.zip
|
||||
|
||||
假设搭建的宝塔第三方云端网址是 http://www.example.com
|
||||
|
||||
- 将class文件夹里面所有的.so文件删除
|
||||
|
||||
- 将aapanel/PluginLoader.py复制到class文件夹
|
||||
|
||||
- 批量解密模块文件:执行 php think decrypt classdir <面板class文件夹路径>
|
||||
|
||||
php think decrypt classdir <面板class_v2文件夹路径>
|
||||
|
||||
- 全局搜索替换 https://wafapi2.aapanel.com => http://www.example.com(需排除task.py、ipsModel.py、js文件)
|
||||
|
||||
- 全局搜索替换 https://node.aapanel.com/install/update_7.x_en.sh => http://www.example.com/install/update_7.x_en.sh
|
||||
|
||||
https://node.aapanel.com/install/update_pro_en.sh => http://www.example.com/install/update_7.x_en.sh
|
||||
|
||||
- 搜索并删除提交异常报告的代码 bt_error/index.php
|
||||
|
||||
- class/ajax.py 文件 \#是否执行升级程序 下面的 public.get_url() 改成 public.OfficialApiBase()
|
||||
|
||||
class/ajax.py 文件 __official_url = 'https://www.aapanel.com' 改成 http://www.example.com
|
||||
|
||||
class/jobs.py 文件 \#尝试升级到独立环境 下面的 public.get_url() 改成 public.OfficialApiBase()
|
||||
|
||||
class/system.py 文件 RepPanel和UpdatePro方法内的 public.get_url() 改成 public.OfficialApiBase()
|
||||
|
||||
- class/public/common.py
|
||||
|
||||
def OfficialApiBase(): 改成 return 'http://www.example.com'
|
||||
|
||||
def load_soft_list 去除 if force 部分
|
||||
|
||||
plugin_list_data = PluginLoader.get_plugin_list(0) 部分改成 plugin_list_data = PluginLoader.get_plugin_list(force)
|
||||
|
||||
在 def check_domain_cloud(domain): 这一行下面加上 return
|
||||
|
||||
在 def count_wp(): 这一行下面加上 return
|
||||
|
||||
在 def err_collect 这一行下面加上 return
|
||||
|
||||
在 def get_improvement(): 这一行下面加上 return False
|
||||
|
||||
在free_login_area方法内get_free_ips_area替换成get_ips_area
|
||||
|
||||
在login_send_body方法内,free_login_area(login_ip=server_ip_area的server_ip_area改成login_ip
|
||||
|
||||
在 def write_request_log(reques=None): 这一行下面加上 return
|
||||
|
||||
- class/panelPlugin.py 文件,set_pyenv方法内,temp_file = public.readFile(filename)这行代码下面加上
|
||||
|
||||
```python
|
||||
temp_file = temp_file.replace('http://download.bt.cn/install/public.sh', 'http://www.example.com/install/public.sh')
|
||||
temp_file = temp_file.replace('https://download.bt.cn/install/public.sh', 'http://www.example.com/install/public.sh')
|
||||
```
|
||||
|
||||
- class_v2/btdockerModelV2/flush_plugin.py 文件,删除clear_hosts()一行
|
||||
|
||||
- install/install_soft.sh 在. 执行之前加入以下代码
|
||||
|
||||
```shell
|
||||
sed -i "s/http:\/\/download.bt.cn\/install\/public.sh/http:\/\/www.example.com\/install\/public.sh/" $name.sh
|
||||
sed -i "s/https:\/\/download.bt.cn\/install\/public.sh/http:\/\/www.example.com\/install\/public.sh/" $name.sh
|
||||
```
|
||||
|
||||
- install/public.sh 用官网最新版的[public.sh](http://download.bt.cn/install/public.sh)替换,并去除最下面bt_check一行
|
||||
|
||||
- 去除无用的定时任务:task.py 文件 删除以下几行
|
||||
|
||||
"update_software_list": update_software_list,
|
||||
|
||||
"check_panel_msg": check_panel_msg,
|
||||
|
||||
"check_panel_auth": check_panel_auth,
|
||||
|
||||
"count_ssh_logs": count_ssh_logs,
|
||||
|
||||
"submit_email_statistics": submit_email_statistics,
|
||||
|
||||
"submit_module_call_statistics": submit_module_call_statistics,
|
||||
|
||||
"mailsys_domain_restrictions": mailsys_domain_restrictions,
|
||||
|
||||
- [可选]去除各种计算题:将bt.js里面的内容复制到 BTPanel/static/vite/oldjs/public_backup.js 末尾
|
||||
|
||||
- [可选]去除创建网站自动创建的垃圾文件:在class/panelSite.py,分别删除
|
||||
|
||||
htaccess = self.sitePath + '/.htaccess'
|
||||
|
||||
index = self.sitePath + '/index.html'
|
||||
|
||||
doc404 = self.sitePath + '/404.html'
|
||||
|
||||
这3行及分别接下来的4行代码
|
||||
|
||||
- [可选]关闭未绑定域名提示页面:在class/panelSite.py,root /www/server/nginx/html改成return 400
|
||||
|
||||
- [可选]上传文件默认选中覆盖,在BTPanel/static/vite/oldjs/upload-drog.js,id="all_operation"加checked属性
|
||||
|
||||
- [可选] BTPanel/static/vite/oldjs/site.js,优化SSL证书配置页面
|
||||
|
||||
- [可选]新版vite页面去除需求反馈、各种广告、计算题等,执行 php think cleanvitejs <面板BTPanel/static/js路径>
|
||||
|
||||
- 新增简体中文语言:修改BTPanel/languages/settings.json,并增加 zh/server.json、all/zh.json
|
||||
|
||||
|
||||
解压安装包[panel_7_en.zip](http://download.bt.cn/install/src/panel_7_en.zip),将更新包改好的文件覆盖到里面,然后重新打包,即可更新安装包。(
|
||||
|
||||
别忘了删除class文件夹里面所有的.so文件)
|
||||
|
408
wiki/files/aapanel/PluginLoader.py
Normal file
408
wiki/files/aapanel/PluginLoader.py
Normal file
@@ -0,0 +1,408 @@
|
||||
#coding: utf-8
|
||||
# +-------------------------------------------------------------------
|
||||
# | 宝塔Linux面板
|
||||
# +-------------------------------------------------------------------
|
||||
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
#+--------------------------------------------------------------------
|
||||
#| 插件和模块加载器
|
||||
#+--------------------------------------------------------------------
|
||||
|
||||
import public,os,sys,json,hashlib
|
||||
|
||||
def plugin_run(plugin_name,def_name,args):
|
||||
'''
|
||||
@name 执行插件方法
|
||||
@param plugin_name<string> 插件名称
|
||||
@param def_name<string> 方法名称
|
||||
@param args<dict_obj> 参数对像
|
||||
@return mixed
|
||||
'''
|
||||
if not plugin_name or not def_name: return public.returnMsg(False,'parameter incorrect: module_name and def_name cannot be empty.')
|
||||
|
||||
# 获取插件目录
|
||||
plugin_path = public.get_plugin_path(plugin_name)
|
||||
is_php = os.path.exists(os.path.join(plugin_path,'index.php'))
|
||||
|
||||
# 检查插件目录是否合法
|
||||
if is_php:
|
||||
plugin_file = os.path.join(plugin_path,'index.php')
|
||||
else:
|
||||
plugin_file = os.path.join(plugin_path, plugin_name + '_main.py')
|
||||
if not public.path_safe_check(plugin_file): return public.returnMsg(False,'parameter incorrect: module_name and def_name cannot contains special symbols.')
|
||||
|
||||
# 检查插件入口文件是否存在
|
||||
if not os.path.exists(plugin_file): return public.returnMsg(False,'plugin not found')
|
||||
|
||||
# 添加插件目录到系统路径
|
||||
public.sys_path_append(plugin_path)
|
||||
|
||||
if not is_php:
|
||||
# 引用插件入口文件
|
||||
_name = "{}_main".format(plugin_name)
|
||||
plugin_main = __import__(_name)
|
||||
|
||||
# 检查类名是否符合规范
|
||||
if not hasattr(plugin_main,_name):
|
||||
return public.returnMsg(False,'plugin class name is invalid')
|
||||
|
||||
try:
|
||||
if sys.version_info[0] == 2:
|
||||
reload(plugin_main)
|
||||
else:
|
||||
from imp import reload
|
||||
reload(plugin_main)
|
||||
except:
|
||||
pass
|
||||
|
||||
# 实例化插件类
|
||||
plugin_obj = getattr(plugin_main,_name)()
|
||||
|
||||
# 检查方法是否存在
|
||||
if not hasattr(plugin_obj,def_name):
|
||||
return public.returnMsg(False,'not find method [%s] in plugin [%s]' % (def_name,plugin_name))
|
||||
|
||||
if args is not None and 'plugin_get_object' in args and args.plugin_get_object == 1:
|
||||
return getattr(plugin_obj, def_name)
|
||||
|
||||
# 执行方法
|
||||
return getattr(plugin_obj,def_name)(args)
|
||||
else:
|
||||
if args is not None and 'plugin_get_object' in args and args.plugin_get_object == 1:
|
||||
return None
|
||||
import panelPHP
|
||||
args.s = def_name
|
||||
args.name = plugin_name
|
||||
return panelPHP.panelPHP(plugin_name).exec_php_script(args)
|
||||
|
||||
|
||||
def get_module_list():
|
||||
'''
|
||||
@name 获取模块列表
|
||||
@return list
|
||||
'''
|
||||
module_list = []
|
||||
class_path = public.get_class_path()
|
||||
for name in os.listdir(class_path):
|
||||
path = os.path.join(class_path,name)
|
||||
# 过滤无效文件
|
||||
if not name or name.endswith('.py') or name[0] == '.' or not name.endswith('Model') or os.path.isfile(path):continue
|
||||
module_list.append(name)
|
||||
return module_list
|
||||
|
||||
def module_run(module_name,def_name,args):
|
||||
'''
|
||||
@name 执行模块方法
|
||||
@param module_name<string> 模块名称
|
||||
@param def_name<string> 方法名称
|
||||
@param args<dict_obj> 参数对像
|
||||
@return mixed
|
||||
'''
|
||||
if not module_name or not def_name: return public.returnMsg(False,'parameter incorrect: module_name and def_name cannot be empty.')
|
||||
model_index = args.get('model_index',None)
|
||||
class_path = public.get_class_path()
|
||||
panel_path = public.get_panel_path()
|
||||
|
||||
module_file = None
|
||||
if 'model_index' in args:
|
||||
# 新模块目录
|
||||
if model_index in ['mod']:
|
||||
module_file = os.path.join(panel_path,'mod','project',module_name + 'Mod.py')
|
||||
elif model_index:
|
||||
# 旧模块目录
|
||||
module_file = os.path.join(class_path,model_index+"Model",module_name + 'Model.py')
|
||||
else:
|
||||
module_file = os.path.join(class_path,"projectModel",module_name + 'Model.py')
|
||||
else:
|
||||
# 如果没指定模块名称,则遍历所有模块目录
|
||||
module_list = get_module_list()
|
||||
for name in module_list:
|
||||
module_file = os.path.join(class_path,name,module_name + 'Model.py')
|
||||
if os.path.exists(module_file): break
|
||||
|
||||
# 判断模块入口文件是否存在
|
||||
if not os.path.exists(module_file):
|
||||
return public.returnMsg(False,'module file [%s] not exist' % module_name)
|
||||
|
||||
# 判断模块路径是否合法
|
||||
if not public.path_safe_check(module_file):
|
||||
return public.returnMsg(False,'parameter incorrect: module_name and def_name cannot contains special symbols.')
|
||||
|
||||
def_object = public.get_script_object(module_file)
|
||||
if not def_object: return public.returnMsg(False,'module [%s] not found' % module_name)
|
||||
|
||||
# 模块实例化并返回方法对象
|
||||
try:
|
||||
run_object = getattr(def_object.main(),def_name,None)
|
||||
except:
|
||||
return public.returnMsg(False,'module [%s] failed to instance class' % module_name)
|
||||
if not run_object: return public.returnMsg(False,'not found method [%s] in module [%s]' % (def_name,module_name))
|
||||
|
||||
if 'module_get_object' in args and args.module_get_object == 1:
|
||||
return run_object
|
||||
|
||||
# 执行方法
|
||||
result = run_object(args)
|
||||
return result
|
||||
|
||||
|
||||
def get_plugin_list(upgrade_force = False):
|
||||
'''
|
||||
@name 获取插件列表
|
||||
@param upgrade_force<bool> 是否强制重新获取列表
|
||||
@return dict
|
||||
'''
|
||||
|
||||
api_root_url = public.OfficialApiBase()
|
||||
api_url = api_root_url+ '/api/panel/getSoftListEn'
|
||||
panel_path = public.get_panel_path()
|
||||
data_path = os.path.join(panel_path,'data')
|
||||
|
||||
if not os.path.exists(data_path):
|
||||
os.makedirs(data_path,384)
|
||||
|
||||
plugin_list = {}
|
||||
plugin_list_file = os.path.join(data_path,'plugin_list.json')
|
||||
if os.path.exists(plugin_list_file) and not upgrade_force:
|
||||
plugin_list_body = public.readFile(plugin_list_file)
|
||||
try:
|
||||
plugin_list = json.loads(plugin_list_body)
|
||||
except:
|
||||
plugin_list = {}
|
||||
|
||||
if not os.path.exists(plugin_list_file) or upgrade_force or not plugin_list:
|
||||
try:
|
||||
res = public.HttpGet(api_url)
|
||||
except Exception as ex:
|
||||
raise public.error_conn_cloud(str(ex))
|
||||
if not res: raise Exception(False,'failed to get soft list')
|
||||
|
||||
plugin_list = json.loads(res)
|
||||
if type(plugin_list)!=dict or 'list' not in plugin_list:
|
||||
if type(plugin_list)==str:
|
||||
raise Exception(plugin_list)
|
||||
else:
|
||||
raise Exception('failed to parse soft list')
|
||||
content = json.dumps(plugin_list)
|
||||
public.writeFile(plugin_list_file,content)
|
||||
|
||||
plugin_bin_file = os.path.join(data_path,'plugin_bin.pl')
|
||||
encode_content = __encode_plugin_list(content)
|
||||
if encode_content:
|
||||
public.writeFile(plugin_bin_file,encode_content)
|
||||
|
||||
return plugin_list
|
||||
|
||||
def __encode_plugin_list(content):
|
||||
try:
|
||||
userInfo = public.get_user_info()
|
||||
if not userInfo or 'server_id' not in userInfo: return None
|
||||
block_size = 51200
|
||||
uid = str(userInfo['uid'])
|
||||
server_id = userInfo['server_id']
|
||||
key = server_id[10:26] + uid + server_id
|
||||
key = hashlib.md5(key.encode()).hexdigest()
|
||||
iv = key + server_id
|
||||
iv = hashlib.md5(iv.encode()).hexdigest()
|
||||
key = key[8:24]
|
||||
iv = iv[8:24]
|
||||
blocks = [content[i:i + block_size] for i in range(0, len(content), block_size)]
|
||||
encrypted_content = ''
|
||||
for block in blocks:
|
||||
encrypted_content += __aes_encrypt(block, key, iv) + '\n'
|
||||
return encrypted_content
|
||||
except:
|
||||
pass
|
||||
return None
|
||||
|
||||
def get_module(filename):
|
||||
if not filename: return public.returnMsg(False,'parameter error: get_module(filename<str>)')
|
||||
if filename[0:2] == './': return public.returnMsg(False,'filename cannot be relative path.')
|
||||
if not public.path_safe_check(filename): return public.returnMsg(False,'filename cannot contains special symbols.')
|
||||
if not os.path.exists(filename): return public.returnMsg(False,'file does not exist')
|
||||
return __get_class_module(filename)
|
||||
|
||||
def __get_class_module(filename):
|
||||
_obj = sys.modules.get(filename, None)
|
||||
if _obj: return _obj
|
||||
_code = public.readFile(filename)
|
||||
if _code.find('import') == -1:
|
||||
en_arr = _code.split('\n')
|
||||
de_text = ''
|
||||
for data in en_arr:
|
||||
data = str.strip(data)
|
||||
if not data: continue
|
||||
de_text += __aes_decrypt_module(data)
|
||||
_code = de_text
|
||||
if not _code or _code.find('import') == -1:
|
||||
return public.returnMsg(False,'load failed: decode error')
|
||||
_code_object = compile(_code, filename, 'exec')
|
||||
from types import ModuleType
|
||||
_obj = sys.modules.setdefault(filename, ModuleType(filename))
|
||||
_obj.__file__ = filename
|
||||
_obj.__package__ = ''
|
||||
exec(_code_object, _obj.__dict__)
|
||||
return _obj
|
||||
|
||||
def start_total():
|
||||
'''
|
||||
@name 启动统计服务
|
||||
@return dict
|
||||
'''
|
||||
pass
|
||||
|
||||
def get_soft_list(args):
|
||||
'''
|
||||
@name 获取软件列表
|
||||
@param args<dict_obj> 参数对像
|
||||
@return dict
|
||||
'''
|
||||
pass
|
||||
|
||||
def db_encrypt(data):
|
||||
'''
|
||||
@name 数据库加密
|
||||
@param args<dict_obj> 参数对像
|
||||
@return dict
|
||||
'''
|
||||
try:
|
||||
key = __get_db_sgin()
|
||||
iv = __get_db_iv()
|
||||
str_arr = data.split('\n')
|
||||
res_str = ''
|
||||
for data in str_arr:
|
||||
if not data: continue
|
||||
res_str += __aes_encrypt(data, key, iv)
|
||||
except:
|
||||
res_str = data
|
||||
result = {
|
||||
'status' : True,
|
||||
'msg' : res_str
|
||||
}
|
||||
return result
|
||||
|
||||
def db_decrypt(data):
|
||||
'''
|
||||
@name 数据库解密
|
||||
@param args<dict_obj> 参数对像
|
||||
@return dict
|
||||
'''
|
||||
try:
|
||||
key = __get_db_sgin()
|
||||
iv = __get_db_iv()
|
||||
str_arr = data.split('\n')
|
||||
res_str = ''
|
||||
for data in str_arr:
|
||||
if not data: continue
|
||||
res_str += __aes_decrypt(data, key, iv)
|
||||
except:
|
||||
res_str = data
|
||||
result = {
|
||||
'status' : True,
|
||||
'msg' : res_str
|
||||
}
|
||||
return result
|
||||
|
||||
def __get_db_sgin():
|
||||
keystr = '3gP7+k_7lSNg3$+Fj!PKW+6$KYgHtw#R'
|
||||
key = ''
|
||||
for i in range(31):
|
||||
if i & 1 == 0:
|
||||
key += keystr[i]
|
||||
return key
|
||||
|
||||
def __get_db_iv():
|
||||
div_file = "{}/data/div.pl".format(public.get_panel_path())
|
||||
if not os.path.exists(div_file):
|
||||
str = public.GetRandomString(16)
|
||||
str = __aes_encrypt_module(str)
|
||||
div = public.get_div(str)
|
||||
public.WriteFile(div_file, div)
|
||||
if os.path.exists(div_file):
|
||||
div = public.ReadFile(div_file)
|
||||
div = __aes_decrypt_module(div)
|
||||
else:
|
||||
keystr = '4jHCpBOFzL4*piTn^-4IHBhj-OL!fGlB'
|
||||
div = ''
|
||||
for i in range(31):
|
||||
if i & 1 == 0:
|
||||
div += keystr[i]
|
||||
return div
|
||||
|
||||
def __aes_encrypt_module(data):
|
||||
key = 'Z2B87NEAS2BkxTrh'
|
||||
iv = 'WwadH66EGWpeeTT6'
|
||||
return __aes_encrypt(data, key, iv)
|
||||
|
||||
def __aes_decrypt_module(data):
|
||||
key = 'Z2B87NEAS2BkxTrh'
|
||||
iv = 'WwadH66EGWpeeTT6'
|
||||
return __aes_decrypt(data, key, iv)
|
||||
|
||||
def __aes_decrypt(data, key, iv):
|
||||
from Crypto.Cipher import AES
|
||||
import base64
|
||||
encodebytes = base64.decodebytes(data.encode('utf-8'))
|
||||
aes = AES.new(key.encode('utf-8'), AES.MODE_CBC, iv.encode('utf-8'))
|
||||
de_text = aes.decrypt(encodebytes)
|
||||
unpad = lambda s: s[0:-s[-1]]
|
||||
de_text = unpad(de_text)
|
||||
return de_text.decode('utf-8')
|
||||
|
||||
def __aes_encrypt(data, key, iv):
|
||||
from Crypto.Cipher import AES
|
||||
import base64
|
||||
data = (lambda s: s + (16 - len(s) % 16) * chr(16 - len(s) % 16).encode('utf-8'))(data.encode('utf-8'))
|
||||
aes = AES.new(key.encode('utf8'), AES.MODE_CBC, iv.encode('utf8'))
|
||||
encryptedbytes = aes.encrypt(data)
|
||||
en_text = base64.b64encode(encryptedbytes)
|
||||
return en_text.decode('utf-8')
|
||||
|
||||
def plugin_end():
|
||||
'''
|
||||
@name 插件到期处理
|
||||
@return dict
|
||||
'''
|
||||
pass
|
||||
|
||||
def daemon_task():
|
||||
'''
|
||||
@name 后台任务守护
|
||||
@return dict
|
||||
'''
|
||||
pass
|
||||
|
||||
def daemon_panel():
|
||||
'''
|
||||
@name 面板守护
|
||||
@return dict
|
||||
'''
|
||||
pass
|
||||
|
||||
def flush_auth_key():
|
||||
'''
|
||||
@name 刷新授权密钥
|
||||
@return dict
|
||||
'''
|
||||
pass
|
||||
|
||||
def get_auth_state():
|
||||
'''
|
||||
@name 获取授权状态
|
||||
@return 返回:0.免费版 1.专业版 2.企业版 -1.获取失败
|
||||
'''
|
||||
try:
|
||||
softList = get_plugin_list()
|
||||
if softList['ltd'] > -1:
|
||||
return 2
|
||||
elif softList['pro'] > -1:
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
except:
|
||||
return -1
|
||||
|
||||
|
83
wiki/files/aapanel/bt.js
Normal file
83
wiki/files/aapanel/bt.js
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
*宝塔面板去除各种计算题与延时等待
|
||||
*/
|
||||
if("undefined" != typeof bt && bt.hasOwnProperty("show_confirm")){
|
||||
bt.show_confirm = function(title, msg, fun, error) {
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: title,
|
||||
area: "350px",
|
||||
closeBtn: 2,
|
||||
shadeClose: true,
|
||||
btn: [lan['public'].ok, lan['public'].cancel],
|
||||
content: "<div class='bt-form webDelete pd20'>\
|
||||
<p>" + msg + "</p>" + (error || '') + "\
|
||||
</div>",
|
||||
yes: function (index, layero) {
|
||||
layer.close(index);
|
||||
if (fun) fun();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
if("undefined" != typeof bt && bt.hasOwnProperty("prompt_confirm")){
|
||||
bt.prompt_confirm = function (title, msg, callback) {
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: title,
|
||||
area: "480px",
|
||||
closeBtn: 2,
|
||||
btn: ['OK', 'Cancel'],
|
||||
content: "<div class='bt-form promptDelete pd20'>\
|
||||
<p>" + msg + "</p>\
|
||||
</div>",
|
||||
yes: function (layers, index) {
|
||||
layer.close(layers)
|
||||
if (callback) callback()
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
if("undefined" != typeof bt && bt.hasOwnProperty("compute_confirm")){
|
||||
bt.compute_confirm = function (config, callback) {
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: config.title,
|
||||
area: '430px',
|
||||
closeBtn: 2,
|
||||
shadeClose: true,
|
||||
btn: [lan['public'].ok, lan['public'].cancel],
|
||||
content:
|
||||
'<div class="bt-form hint_confirm pd30">\
|
||||
<div class="hint_title">\
|
||||
<i class="hint-confirm-icon"></i>\
|
||||
<div class="hint_con">' +
|
||||
config.msg +
|
||||
'</div>\
|
||||
</div>\
|
||||
</div>',
|
||||
yes: function (layers, index) {
|
||||
layer.close(layers)
|
||||
if (callback) callback()
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
function SafeMessage(j, h, g, f) {
|
||||
if (f == undefined) f = '';
|
||||
var mess = layer.open({
|
||||
type: 1,
|
||||
title: j,
|
||||
area: "350px",
|
||||
closeBtn: 2,
|
||||
shadeClose: true,
|
||||
content: "<div class='bt-form webDelete pd20 pb70'><p>" + h + "</p>" + f + "<div class='bt-form-submit-btn'><button type='button' class='btn btn-danger btn-sm bt-cancel'>"+lan.public.cancel+"</button> <button type='button' id='toSubmit' class='btn btn-success btn-sm' >"+lan.public.ok+"</button></div></div>"
|
||||
});
|
||||
$(".bt-cancel").click(function(){
|
||||
layer.close(mess);
|
||||
});
|
||||
$("#toSubmit").click(function() {
|
||||
layer.close(mess);
|
||||
g();
|
||||
})
|
||||
}
|
@@ -11,7 +11,7 @@
|
||||
#| 插件和模块加载器
|
||||
#+--------------------------------------------------------------------
|
||||
|
||||
import public,os,sys,json
|
||||
import public,os,sys,json,hashlib
|
||||
|
||||
def plugin_run(plugin_name,def_name,args):
|
||||
'''
|
||||
@@ -186,10 +186,37 @@ def get_plugin_list(upgrade_force = False):
|
||||
raise Exception(plugin_list)
|
||||
else:
|
||||
raise Exception('云端插件列表获取失败')
|
||||
public.writeFile(plugin_list_file,json.dumps(plugin_list))
|
||||
content = json.dumps(plugin_list)
|
||||
public.writeFile(plugin_list_file,content)
|
||||
|
||||
plugin_bin_file = os.path.join(data_path,'plugin_bin.pl')
|
||||
encode_content = __encode_plugin_list(content)
|
||||
if encode_content:
|
||||
public.writeFile(plugin_bin_file,encode_content)
|
||||
|
||||
return plugin_list
|
||||
|
||||
def __encode_plugin_list(content):
|
||||
try:
|
||||
userInfo = public.get_user_info()
|
||||
if not userInfo or 'serverid' not in userInfo: return None
|
||||
block_size = 51200
|
||||
uid = str(userInfo['uid'])
|
||||
server_id = userInfo['serverid']
|
||||
key = server_id[10:26] + uid + server_id
|
||||
key = hashlib.md5(key.encode()).hexdigest()
|
||||
iv = key + server_id
|
||||
iv = hashlib.md5(iv.encode()).hexdigest()
|
||||
key = key[8:24]
|
||||
iv = iv[8:24]
|
||||
blocks = [content[i:i + block_size] for i in range(0, len(content), block_size)]
|
||||
encrypted_content = ''
|
||||
for block in blocks:
|
||||
encrypted_content += __aes_encrypt(block, key, iv) + '\n'
|
||||
return encrypted_content
|
||||
except:
|
||||
pass
|
||||
return None
|
||||
|
||||
def start_total():
|
||||
'''
|
||||
|
@@ -88,396 +88,23 @@ if("undefined" != typeof bt && bt.hasOwnProperty("input_confirm")){
|
||||
});
|
||||
}
|
||||
}
|
||||
if("undefined" != typeof database && database.hasOwnProperty("del_database")){
|
||||
database.del_database = function (wid, dbname, obj, callback) {
|
||||
var is_db_type = false, del_data = []
|
||||
if (typeof wid === 'object') {
|
||||
del_data = wid
|
||||
is_db_type = wid.some(function (item) {
|
||||
return item.db_type > 0
|
||||
})
|
||||
var ids = [];
|
||||
for (var i = 0; i < wid.length; i++) {
|
||||
ids.push(wid[i].id);
|
||||
}
|
||||
wid = ids
|
||||
}
|
||||
var type = $('.database-pos .tabs-item.active').data('type'),
|
||||
title = '',
|
||||
tips = '';
|
||||
title = typeof dbname === "function" ? '批量删除数据库' : '删除数据库 - [ ' + dbname + ' ]';
|
||||
tips = is_db_type || !recycle_bin_db_open || type !== 'mysql' ? '<span class="color-red">当前列表存在彻底删除后无法恢复的数据库</span>,请仔细查看列表,以防误删,是否继续操作?' : '当前列表数据库将迁移至数据库回收站,如需彻底删除请前往数据库回收站,是否继续操作?'
|
||||
var arrs = wid instanceof Array ? wid : [wid]
|
||||
var ids = JSON.stringify(arrs),
|
||||
countDown = 9;
|
||||
if (arrs.length == 1) countDown = 4
|
||||
var loadT = bt.load('正在检测数据库数据信息,请稍候...'),
|
||||
param = { url: 'database/' + bt.data.db_tab_name + '/check_del_data', data: { data: JSON.stringify({ ids: ids }) } }
|
||||
if (bt.data.db_tab_name == 'mysql') param = { url: 'database?action=check_del_data', data: { ids: ids } }
|
||||
bt_tools.send(param, function (res) {
|
||||
loadT.close()
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: title,
|
||||
area: '740px',
|
||||
skin: 'verify_site_layer_info',
|
||||
closeBtn: 2,
|
||||
shadeClose: true,
|
||||
content: '<div class="check_delete_site_main hint_confirm pd30">' +
|
||||
"<div class='hint_title'>\
|
||||
<i class=\'hint-confirm-icon\'></i>\
|
||||
<div class=\'hint_con\'>"+ tips + "</div>\
|
||||
</div>"+
|
||||
'<div id="check_layer_content" class="ptb15">' +
|
||||
'</div>' +
|
||||
'<div class="check_layer_message">' +
|
||||
(is_db_type ? '<span class="color-red">注意:远程数据库暂不支持数据库回收站,选中的数据库将彻底删除</span><br>' : '') +
|
||||
(!recycle_bin_db_open ? '<span class="color-red">风险操作:当前数据库回收站未开启,删除数据库将永久消失</span><br>' : '')
|
||||
+ '<span class="color-red">请仔细阅读以上要删除信息,防止数据库被误删</span></div>' +
|
||||
'</div>',
|
||||
btn: ['下一步', lan.public.cancel],
|
||||
success: function (layers) {
|
||||
setTimeout(function () { $(layers).css('top', ($(window).height() - $(layers).height()) / 2); }, 50)
|
||||
var rdata = res.data,
|
||||
newTime = parseInt(new Date().getTime() / 1000),
|
||||
t_icon = ' <span class="glyphicon glyphicon-info-sign" style="color: red;width:15px;height: 15px;;vertical-align: middle;"></span>';
|
||||
for (var j = 0; j < rdata.length; j++) {
|
||||
for (var i = 0; i < del_data.length; i++) {
|
||||
if (rdata[j].id == del_data[i].id) {
|
||||
var is_time_rule = (newTime - rdata[j].st_time) > (86400 * 30) && (rdata[j].total > 1024 * 10),
|
||||
is_database_rule = res.db_size <= rdata[j].total,
|
||||
database_time = bt.format_data(rdata[j].st_time, 'yyyy-MM-dd'),
|
||||
database_size = bt.format_size(rdata[j].total);
|
||||
var f_size = database_size
|
||||
var t_size = '注意:此数据库较大,可能为重要数据,请谨慎操作.\n数据库:' + database_size;
|
||||
if (rdata[j].total < 2048) t_size = '注意事项:当前数据库不为空,可能为重要数据,请谨慎操作.\n数据库:' + database_size;
|
||||
if (rdata[j].total === 0) t_size = '';
|
||||
rdata[j]['t_size'] = t_size
|
||||
rdata[j]['f_size'] = f_size
|
||||
rdata[j]['database_time'] = database_time
|
||||
rdata[j]['is_time_rule'] = is_time_rule
|
||||
rdata[j]['is_database_rule'] = is_database_rule
|
||||
rdata[j]['db_type'] = del_data[i].db_type
|
||||
rdata[j]['conn_config'] = del_data[i].conn_config
|
||||
}
|
||||
}
|
||||
}
|
||||
var filterData = rdata.filter(function (el) {
|
||||
return ids.indexOf(el.id) != -1
|
||||
})
|
||||
bt_tools.table({
|
||||
el: '#check_layer_content',
|
||||
data: filterData,
|
||||
height: '300px',
|
||||
column: [
|
||||
{ fid: 'name', title: '数据库名称' },
|
||||
{
|
||||
title: '数据库大小', template: function (row) {
|
||||
return '<span class="' + (row.is_database_rule ? 'warning' : '') + '" style="width: 110px;" title="' + row.t_size + '">' + row.f_size + (row.is_database_rule ? t_icon : '') + '</span>'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '数据库位置', template: function (row) {
|
||||
var type_column = '-'
|
||||
switch (row.db_type) {
|
||||
case 0:
|
||||
type_column = '本地数据库'
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
type_column = '远程数据库'
|
||||
break;
|
||||
}
|
||||
return '<span style="width: 110px;" title="' + type_column + '">' + type_column + '</span>'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '创建时间', template: function (row) {
|
||||
return '<span ' + (is_time_rule && row.total != 0 ? 'class="warning"' : '') + ' title="' + (row.is_time_rule && row.total != 0 ? '重要:此数据库创建时间较早,可能为重要数据,请谨慎操作.' : '') + '时间:' + row.database_time + '">' + row.database_time + '</span>'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '删除结果', align: 'right', template: function (row, index, ev, _that) {
|
||||
var _html = ''
|
||||
switch (row.db_type) {
|
||||
case 0:
|
||||
_html = type !== 'mysql' ? '彻底删除' : (!recycle_bin_db_open ? '彻底删除' : '移至回收站')
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
_html = '彻底删除'
|
||||
break;
|
||||
}
|
||||
return '<span style="width: 110px;" class="' + (_html === '彻底删除' ? 'warning' + (row.db_type > 0 ? ' remote_database' : '') : '') + '">' + _html + '</span>'
|
||||
}
|
||||
}
|
||||
],
|
||||
success: function () {
|
||||
$('#check_layer_content').find('.glyphicon-info-sign').click(function (e) {
|
||||
var msg = $(this).parent().prop('title')
|
||||
msg = msg.replace('数据库:','<br>数据库:')
|
||||
layer.tips(msg, $(this).parent(), { tips: [1, 'red'], time: 3000 })
|
||||
$(document).click(function (ev) {
|
||||
layer.closeAll('tips');
|
||||
$(this).unbind('click');
|
||||
ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
});
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
});
|
||||
if ($('.remote_database').length) {
|
||||
$('.remote_database').each(function (index, el) {
|
||||
var id = $(el).parent().parent().parent().index()
|
||||
$('#check_layer_content tbody tr').eq(id).css('background-color', '#ff00000a')
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
yes: function (indes, layers) {
|
||||
title = typeof dbname === "function" ? '二次验证信息,批量删除数据库' : '二次验证信息,删除数据库 - [ ' + dbname + ' ]';
|
||||
if (type !== 'mysql') {
|
||||
tips = '<span class="color-red">当前数据库暂不支持数据库回收站,删除后将无法恢复</span>,此操作不可逆,是否继续操作?';
|
||||
} else {
|
||||
tips = is_db_type ? '<span class="color-red">远程数据库不支持数据库回收站,删除后将无法恢复</span>,此操作不可逆,是否继续操作?' : recycle_bin_db_open ? '删除后如需彻底删除请前往数据库回收站,是否继续操作?' : '删除后可能会影响业务使用,此操作不可逆,是否继续操作?'
|
||||
}
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: title,
|
||||
icon: 0,
|
||||
skin: 'delete_site_layer',
|
||||
area: "530px",
|
||||
closeBtn: 2,
|
||||
shadeClose: true,
|
||||
content: "<div class=\'bt-form webDelete hint_confirm pd30\' id=\'site_delete_form\'>" +
|
||||
"<div class='hint_title'>\
|
||||
<i class=\'hint-confirm-icon\'></i>\
|
||||
<div class=\'hint_con\'>"+ tips + "</div>\
|
||||
</div>"+
|
||||
"<div style=\'color:red;margin:18px 0 18px 18px;font-size:14px;font-weight: bold;\'>注意:数据无价,请谨慎操作!!!" + (type === 'mysql' && !recycle_bin_db_open ? '<br>风险操作:当前数据库回收站未开启,删除数据库将永久消失!' : '') + "</div>"+
|
||||
"</div>",
|
||||
btn: ['确认删除', '取消删除'],
|
||||
yes: function (indexs) {
|
||||
var data = {
|
||||
id: wid,
|
||||
name: dbname
|
||||
};
|
||||
if (typeof dbname === "function") {
|
||||
delete data.id;
|
||||
delete data.name;
|
||||
}
|
||||
layer.close(indexs)
|
||||
layer.close(indes)
|
||||
if (typeof dbname === "function") {
|
||||
dbname(data)
|
||||
} else {
|
||||
data.id = data.id[0]
|
||||
bt.database.del_database(data, function (rdata) {
|
||||
layer.closeAll()
|
||||
if (callback) callback(rdata);
|
||||
bt.msg(rdata);
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
if("undefined" != typeof site && site.hasOwnProperty("del_site")){
|
||||
site.del_site = function (wid, wname, callback) {
|
||||
title = typeof wname === "function" ? '批量删除站点' : '删除站点 [ ' + wname + ' ]';
|
||||
layer.open({
|
||||
if(window.hasOwnProperty("SafeMessage")){
|
||||
window.SafeMessage = function(j, h, g, f) {
|
||||
if (f == undefined) f = '';
|
||||
var mess = layer.open({
|
||||
type: 1,
|
||||
title: title,
|
||||
icon: 0,
|
||||
skin: 'delete_site_layer',
|
||||
area: "440px",
|
||||
title: j,
|
||||
area: "350px",
|
||||
closeBtn: 2,
|
||||
shadeClose: true,
|
||||
content: "<div class=\'bt-form webDelete pd30\' id=\'site_delete_form\'>" +
|
||||
'<i class="layui-layer-ico layui-layer-ico0"></i>' +
|
||||
"<div class=\'f13 check_title\'>是否要删除关联的FTP、数据库、站点目录!</div>" +
|
||||
"<div class=\"check_type_group\">" +
|
||||
"<label><input type=\"checkbox\" name=\"ftp\"><span>FTP</span></label>" +
|
||||
"<label><input type=\"checkbox\" name=\"database\"><span>数据库</span>" + (!recycle_bin_db_open ? '<span class="glyphicon glyphicon-info-sign" style="color: red"></span>' : '') + "</label>" +
|
||||
"<label><input type=\"checkbox\" name=\"path\"><span>站点目录</span>" + (!recycle_bin_open ? '<span class="glyphicon glyphicon-info-sign" style="color: red"></span>' : '') + "</label>" +
|
||||
"</div>" +
|
||||
"</div>",
|
||||
btn: [lan.public.ok, lan.public.cancel],
|
||||
success: function (layers, indexs) {
|
||||
$(layers).find('.check_type_group label').hover(function () {
|
||||
var name = $(this).find('input').attr('name');
|
||||
if (name === 'database' && !recycle_bin_db_open) {
|
||||
layer.tips('风险操作:当前数据库回收站未开启,删除数据库将永久消失!', this, { tips: [1, 'red'], time: 0 })
|
||||
} else if (name === 'path' && !recycle_bin_open) {
|
||||
layer.tips('风险操作:当前文件回收站未开启,删除站点目录将永久消失!', this, { tips: [1, 'red'], time: 0 })
|
||||
}
|
||||
}, function () {
|
||||
layer.closeAll('tips');
|
||||
});
|
||||
},
|
||||
yes: function (indexs) {
|
||||
var data = { id: wid, webname: wname };
|
||||
$('#site_delete_form input[type=checkbox]').each(function (index, item) {
|
||||
if ($(item).is(':checked')) data[$(item).attr('name')] = 1
|
||||
})
|
||||
var is_database = data.hasOwnProperty('database'), is_path = data.hasOwnProperty('path'), is_ftp = data.hasOwnProperty('ftp');
|
||||
if ((!is_database && !is_path) && (!is_ftp || is_ftp)) {
|
||||
if (typeof wname === "function") {
|
||||
wname(data)
|
||||
return false;
|
||||
}
|
||||
bt.site.del_site(data, function (rdata) {
|
||||
layer.close(indexs);
|
||||
if (callback) callback(rdata);
|
||||
bt.msg(rdata);
|
||||
})
|
||||
return false
|
||||
}
|
||||
if (typeof wname === "function") {
|
||||
delete data.id;
|
||||
delete data.webname;
|
||||
}
|
||||
layer.close(indexs)
|
||||
var ids = JSON.stringify(wid instanceof Array ? wid : [wid]), countDown = typeof wname === 'string' ? 4 : 9;
|
||||
title = typeof wname === "function" ? '二次验证信息,批量删除站点' : '二次验证信息,删除站点 [ ' + wname + ' ]';
|
||||
var loadT = bt.load('正在检测站点数据信息,请稍候...')
|
||||
bt.send('check_del_data', 'site/check_del_data', { ids: ids }, function (res) {
|
||||
loadT.close()
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: title,
|
||||
closeBtn: 2,
|
||||
skin: 'verify_site_layer_info',
|
||||
area: '740px',
|
||||
content: '<div class="check_delete_site_main pd30">' +
|
||||
'<i class="layui-layer-ico layui-layer-ico0"></i>' +
|
||||
'<div class="check_layer_title">堡塔温馨提示您,请冷静几秒钟,确认以下要删除的数据。</div>' +
|
||||
'<div class="check_layer_content">' +
|
||||
'<div class="check_layer_item">' +
|
||||
'<div class="check_layer_site"></div>' +
|
||||
'<div class="check_layer_database"></div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'<div class="check_layer_error ' + (is_database && data['database'] && !recycle_bin_db_open ? '' : 'hide') + '"><span class="glyphicon glyphicon-info-sign"></span>风险事项:当前未开启数据库回收站功能,删除数据库后,数据库将永久消失!</div>' +
|
||||
'<div class="check_layer_error ' + (is_path && data['path'] && !recycle_bin_open ? '' : 'hide') + '"><span class="glyphicon glyphicon-info-sign"></span>风险事项:当前未开启文件回收站功能,删除站点目录后,站点目录将永久消失!</div>' +
|
||||
'<div class="check_layer_message"><span style="color:red">注意:请仔细阅读以上要删除信息,防止网站数据被误删</span></div>' +
|
||||
'</div>',
|
||||
// recycle_bin_db_open &&
|
||||
// recycle_bin_open &&
|
||||
btn: ['确认删除', '取消删除'],
|
||||
success: function (layers) {
|
||||
var html = '', rdata = res.data;
|
||||
for (var i = 0; i < rdata.length; i++) {
|
||||
var item = rdata[i], newTime = parseInt(new Date().getTime() / 1000),
|
||||
t_icon = '<span class="glyphicon glyphicon-info-sign" style="color: red;width:15px;height: 15px;;vertical-align: middle;"></span>';
|
||||
|
||||
site_html = (function (item) {
|
||||
if (!is_path) return ''
|
||||
var is_time_rule = (newTime - item.st_time) > (86400 * 30) && (item.total > 1024 * 10),
|
||||
is_path_rule = res.file_size <= item.total,
|
||||
dir_time = bt.format_data(item.st_time, 'yyyy-MM-dd'),
|
||||
dir_size = bt.format_size(item.total);
|
||||
|
||||
var f_html = '<i ' + (is_path_rule ? 'class="warning"' : '') + ' style = "vertical-align: middle;" > ' + (item.limit ? '大于50MB' : dir_size) + '</i> ' + (is_path_rule ? t_icon : '');
|
||||
var f_title = (is_path_rule ? '注意:此目录较大,可能为重要数据,请谨慎操作.\n' : '') + '目录:' + item.path + '(' + (item.limit ? '大于' : '') + dir_size + ')';
|
||||
|
||||
return '<div class="check_layer_site">' +
|
||||
'<span title="站点:' + item.name + '">站点名:' + item.name + '</span>' +
|
||||
'<span title="' + f_title + '" >目录:<span style="vertical-align: middle;max-width: 160px;width: auto;">' + item.path + '</span> (' + f_html + ')</span>' +
|
||||
'<span title="' + (is_time_rule ? '注意:此站点创建时间较早,可能为重要数据,请谨慎操作.\n' : '') + '时间:' + dir_time + '">创建时间:<i ' + (is_time_rule ? 'class="warning"' : '') + '>' + dir_time + '</i></span>' +
|
||||
'</div>'
|
||||
}(item)),
|
||||
database_html = (function (item) {
|
||||
if (!is_database || !item.database) return '';
|
||||
var is_time_rule = (newTime - item.st_time) > (86400 * 30) && (item.total > 1024 * 10),
|
||||
is_database_rule = res.db_size <= item.database.total,
|
||||
database_time = bt.format_data(item.database.st_time, 'yyyy-MM-dd'),
|
||||
database_size = bt.format_size(item.database.total);
|
||||
|
||||
var f_size = '<i ' + (is_database_rule ? 'class="warning"' : '') + ' style = "vertical-align: middle;" > ' + database_size + '</i> ' + (is_database_rule ? t_icon : '');
|
||||
var t_size = '注意:此数据库较大,可能为重要数据,请谨慎操作.\n数据库:' + database_size;
|
||||
|
||||
return '<div class="check_layer_database">' +
|
||||
'<span title="数据库:' + item.database.name + '">数据库:' + item.database.name + '</span>' +
|
||||
'<span title="' + t_size + '">大小:' + f_size + '</span>' +
|
||||
'<span title="' + (is_time_rule && item.database.total != 0 ? '重要:此数据库创建时间较早,可能为重要数据,请谨慎操作.' : '') + '时间:' + database_time + '">创建时间:<i ' + (is_time_rule && item.database.total != 0 ? 'class="warning"' : '') + '>' + database_time + '</i></span>' +
|
||||
'</div>'
|
||||
}(item))
|
||||
if ((site_html + database_html) !== '') html += '<div class="check_layer_item">' + site_html + database_html + '</div>';
|
||||
}
|
||||
if (html === '') html = '<div style="text-align: center;width: 100%;height: 100%;line-height: 300px;font-size: 15px;">无数据</div>'
|
||||
$('.check_layer_content').html(html)
|
||||
},
|
||||
yes: function (indes, layers) {
|
||||
if (typeof wname === "function") {
|
||||
wname(data)
|
||||
} else {
|
||||
bt.site.del_site(data, function (rdata) {
|
||||
layer.closeAll()
|
||||
if (rdata.status) site.get_list();
|
||||
if (callback) callback(rdata);
|
||||
bt.msg(rdata);
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
content: "<div class='bt-form webDelete pd20 pb70'><p>" + h + "</p>" + f + "<div class='bt-form-submit-btn'><button type='button' class='btn btn-danger btn-sm bt-cancel'>"+lan.public.cancel+"</button> <button type='button' id='toSubmit' class='btn btn-success btn-sm' >"+lan.public.ok+"</button></div></div>"
|
||||
});
|
||||
$(".bt-cancel").click(function(){
|
||||
layer.close(mess);
|
||||
});
|
||||
$("#toSubmit").click(function() {
|
||||
layer.close(mess);
|
||||
g();
|
||||
})
|
||||
}
|
||||
}
|
||||
if("undefined" != typeof bt && bt.hasOwnProperty("firewall") && bt.firewall.hasOwnProperty("add_accept_port")){
|
||||
bt.firewall.add_accept_port = function(type, port, ps, callback) {
|
||||
var action = "AddDropAddress";
|
||||
if (type == 'port') {
|
||||
ports = port.split(':');
|
||||
if (port.indexOf('-') != -1) ports = port.split('-');
|
||||
for (var i = 0; i < ports.length; i++) {
|
||||
if (!bt.check_port(ports[i])) {
|
||||
layer.msg('可用端口范围:1-65535', { icon: 2 });
|
||||
// layer.msg(lan.firewall.port_err, {
|
||||
// icon: 5
|
||||
// });
|
||||
return;
|
||||
}
|
||||
}
|
||||
action = "AddAcceptPort";
|
||||
}
|
||||
|
||||
loading = bt.load();
|
||||
bt.send(action, 'firewall/' + action, { port: port, type: type, ps: ps }, function(rdata) {
|
||||
loading.close();
|
||||
if (callback) callback(rdata);
|
||||
})
|
||||
}
|
||||
}
|
||||
function SafeMessage(j, h, g, f) {
|
||||
if(f == undefined) {
|
||||
f = ""
|
||||
}
|
||||
var mess = layer.open({
|
||||
type: 1,
|
||||
title: j,
|
||||
area: "350px",
|
||||
closeBtn: 2,
|
||||
shadeClose: true,
|
||||
content: "<div class='bt-form webDelete pd20 pb70'><p>" + h + "</p>" + f + "<div class='bt-form-submit-btn'><button type='button' class='btn btn-danger btn-sm bt-cancel'>"+lan.public.cancel+"</button> <button type='button' id='toSubmit' class='btn btn-success btn-sm' >"+lan.public.ok+"</button></div></div>"
|
||||
});
|
||||
$(".bt-cancel").click(function(){
|
||||
layer.close(mess);
|
||||
});
|
||||
$("#toSubmit").click(function() {
|
||||
layer.close(mess);
|
||||
g();
|
||||
})
|
||||
}
|
||||
$(document).ready(function () {
|
||||
if($('#updata_pro_info').length>0){
|
||||
$('#updata_pro_info').html('');
|
||||
bt.set_cookie('productPurchase', 1);
|
||||
}
|
||||
})
|
||||
}
|
@@ -58,7 +58,7 @@
|
||||
|
||||
在login_send_body方法内,free_login_area(login_ip=server_ip_area的server_ip_area改成login_ip
|
||||
|
||||
- class/panelPlugin.py 文件,删除public.total_keyword(get.query)这一行
|
||||
- class/panelPlugin.py 文件
|
||||
|
||||
__set_pyenv方法内,temp_file = public.readFile(filename)这行代码下面加上
|
||||
|
||||
@@ -76,6 +76,12 @@
|
||||
|
||||
plugin_bin.pl 改成 plugin_list.json
|
||||
|
||||
删除 public.total_keyword(get.query)
|
||||
|
||||
删除 public.run_thread(self.get_cloud_list_status, args=(get,))
|
||||
|
||||
删除 public.run_thread(self.is_verify_unbinding, args=(get,))
|
||||
|
||||
- class/plugin_deployment.py 文件,__setup_php_environment方法和GetJarPath方法内替换 public.GetConfigValue('home') => 'https://www.bt.cn'
|
||||
|
||||
- class/config.py 文件,get_nps方法内data['nps'] = False改成True,get_nps_new方法下面加上 return public.returnMsg(False, "获取问卷失败")
|
||||
@@ -95,8 +101,8 @@
|
||||
- install/install_soft.sh 在. 执行之前加入以下代码
|
||||
|
||||
```shell
|
||||
sed -i "s/http:\/\/download.bt.cn\/install\/public.sh/http:\/\/www.example.com\/install\/public.sh/" lib.sh
|
||||
sed -i "s/https:\/\/download.bt.cn\/install\/public.sh/http:\/\/www.example.com\/install\/public.sh/" lib.sh
|
||||
sed -i "s/http:\/\/download.bt.cn\/install\/public.sh/http:\/\/www.example.com\/install\/public.sh/" $name.sh
|
||||
sed -i "s/https:\/\/download.bt.cn\/install\/public.sh/http:\/\/www.example.com\/install\/public.sh/" $name.sh
|
||||
```
|
||||
|
||||
- install/public.sh 用官网最新版的[public.sh](http://download.bt.cn/install/public.sh)替换,并去除最下面bt_check一行
|
||||
@@ -111,20 +117,16 @@
|
||||
|
||||
check_node_status()
|
||||
|
||||
- 去除WebRTC连接:BTPanel/static/js/public.js 删除stun.start();这一行
|
||||
self.upload_send_num()
|
||||
|
||||
- 去除内页广告:BTPanel/templates/default/layout.html 删除两处getPaymentStatus();
|
||||
- script/site_task.py 删除flush_ssh_log()
|
||||
|
||||
- 删除问卷调查:BTPanel/templates/default/layout.html 删除if(window.localStorage.getItem('panelNPS') == null)以及下面的行
|
||||
|
||||
- [可选]去除各种计算题:复制bt.js到 BTPanel/static/ ,在 BTPanel/templates/default/layout.html 的\</body\>前面加入
|
||||
- [可选]去除各种计算题:复制bt.js到 BTPanel/static/ ,在 BTPanel/templates/default/software.html 的 \<script\>window.vite_public_request_token 前面加入
|
||||
|
||||
```javascript
|
||||
<script src="/static/bt.js"></script>
|
||||
```
|
||||
|
||||
在 BTPanel/templates/default/software.html 的 \<script\>window.vite_public_request_token 前面加入
|
||||
|
||||
- [可选]去除创建网站自动创建的垃圾文件:在class/panelSite.py,分别删除
|
||||
|
||||
htaccess = self.sitePath + '/.htaccess'
|
||||
@@ -139,7 +141,7 @@
|
||||
|
||||
- [可选]关闭自动生成访问日志:在 BTPanel/\_\_init\_\_.py 删除public.write_request_log这一行
|
||||
|
||||
- [可选]新版vite页面去除需求反馈、各种广告、计算题等,执行 php think cleanvitejs <面板BTPanel/static/vite/js路径>
|
||||
- [可选]新版vite页面去除需求反馈、各种广告、计算题等,执行 php think cleanvitejs <面板BTPanel/static/js路径>
|
||||
|
||||
|
||||
解压安装包[panel6.zip](http://download.bt.cn/install/src/panel6.zip),将更新包改好的文件覆盖到里面,然后重新打包,即可更新安装包。(
|
||||
|
@@ -42,6 +42,8 @@ Windows版宝塔由于加密文件太多,无法全部解密,因此无法做
|
||||
|
||||
- class/plugin_deployment.py 文件 get_icon 和 SetupPackage 方法内,替换 public.GetConfigValue('home') => 'https://www.bt.cn'
|
||||
|
||||
- script/reload_check.py 文件,在第2行插入sys.exit()
|
||||
|
||||
- 去除无用的定时任务:task.py 文件
|
||||
|
||||
删除 p = threading.Thread(target=check_files_panel) 以及下面2行
|
||||
|
Reference in New Issue
Block a user