13 |
14 |
自签名SSL证书生成
15 |
16 | {if $isca}
17 |
18 |
45 | {else}
46 |
你还没有生成CA证书,无法生成SSL证书!
47 |
执行以下命令,生成自签名CA证书。然后,可通过接口或当前页面生成SSL证书,用于面板访问。
48 |
cd {:app()->getRootPath()}app/script && chmod +x cacert.sh && ./cacert.sh
49 | {/if}
50 |
51 |
52 |
53 |
86 | {/block}
--------------------------------------------------------------------------------
/app/view/dispatch_jump.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
温馨提示
6 |
7 |
8 |
28 |
29 |
30 |
31 |
32 |

33 |
34 |
{$msg}
35 | {if $url}
36 |
37 | 页面将在 {$wait} 秒后自动跳转
38 |
39 | {/if}
40 |
41 | 返回上一页
42 | {if $url}
43 | 立即跳转
44 | {/if}
45 |
46 |
47 |
59 |
60 |
--------------------------------------------------------------------------------
/app/view/install/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
宝塔第三方云端 - 安装程序
7 |
8 |
9 |
151 |
152 |
153 |
154 |
155 |
156 |
159 |
160 |
宝塔第三方云端 - 安装程序
161 |
162 |
163 |
218 |
219 |
220 |
221 |
267 |
268 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "btpanel/cloud",
3 | "description": "BTPanel third cloud site",
4 | "type": "project",
5 | "keywords": [
6 | "btpanel",
7 | "baota",
8 | "aapanel"
9 | ],
10 | "homepage": "https://www.bt.cn/",
11 | "license": "Apache-2.0",
12 | "authors": [],
13 | "require": {
14 | "php": ">=7.2.5",
15 | "topthink/framework": "^6.0.0",
16 | "topthink/think-orm": "^2.0",
17 | "topthink/think-view": "^1.0",
18 | "topthink/think-captcha": "^3.0"
19 | },
20 | "require-dev": {
21 | "symfony/var-dumper": "^4.2",
22 | "topthink/think-trace":"^1.0"
23 | },
24 | "autoload": {
25 | "psr-4": {
26 | "app\\": "app"
27 | },
28 | "psr-0": {
29 | "": "extend/"
30 | }
31 | },
32 | "config": {
33 | "preferred-install": "dist"
34 | },
35 | "scripts": {
36 | "post-autoload-dump": [
37 | "@php think service:discover",
38 | "@php think vendor:publish"
39 | ]
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/config/app.php:
--------------------------------------------------------------------------------
1 | env('app.host', ''),
9 | // 应用的命名空间
10 | 'app_namespace' => '',
11 | // 是否启用路由
12 | 'with_route' => true,
13 | // 默认应用
14 | 'default_app' => 'index',
15 | // 默认时区
16 | 'default_timezone' => 'Asia/Shanghai',
17 |
18 | // 应用映射(自动多应用模式有效)
19 | 'app_map' => [],
20 | // 域名绑定(自动多应用模式有效)
21 | 'domain_bind' => [],
22 | // 禁止URL访问的应用列表(自动多应用模式有效)
23 | 'deny_app_list' => [],
24 |
25 | // 异常页面的模板文件
26 | 'exception_tmpl' => app()->getThinkPath() . 'tpl/think_exception.tpl',
27 |
28 | // 错误显示信息,非调试模式有效
29 | 'error_message' => '页面错误!请稍后再试~',
30 | // 显示错误信息
31 | 'show_error_msg' => true,
32 | ];
33 |
--------------------------------------------------------------------------------
/config/cache.php:
--------------------------------------------------------------------------------
1 | env('cache.driver', 'file'),
10 |
11 | // 缓存连接方式配置
12 | 'stores' => [
13 | 'file' => [
14 | // 驱动方式
15 | 'type' => 'File',
16 | // 缓存保存目录
17 | 'path' => '',
18 | // 缓存前缀
19 | 'prefix' => '',
20 | // 缓存有效期 0表示永久缓存
21 | 'expire' => 0,
22 | // 缓存标签前缀
23 | 'tag_prefix' => 'tag:',
24 | // 序列化机制 例如 ['serialize', 'unserialize']
25 | 'serialize' => [],
26 | ],
27 | 'redis' => [
28 | // 驱动方式
29 | 'type' => 'Redis',
30 | 'host' => '127.0.0.1',
31 | 'port' => 6379,
32 | 'password' => '',
33 | 'select' => 0,
34 | // 缓存有效期 0表示永久缓存
35 | 'expire' => 3600,
36 | 'prefix' => '',
37 | ],
38 | // 更多的缓存连接
39 | ],
40 | ];
41 |
--------------------------------------------------------------------------------
/config/captcha.php:
--------------------------------------------------------------------------------
1 | 4,
9 | // 验证码字符集合
10 | 'codeSet' => '2345678abcdefhijkmnpqrstuvwxyzABCDEFGHJKLMNPQRTUVWXY',
11 | // 验证码过期时间
12 | 'expire' => 1800,
13 | // 是否使用中文验证码
14 | 'useZh' => false,
15 | // 是否使用算术验证码
16 | 'math' => false,
17 | // 是否使用背景图
18 | 'useImgBg' => false,
19 | //验证码字符大小
20 | 'fontSize' => 25,
21 | // 是否使用混淆曲线
22 | 'useCurve' => true,
23 | //是否添加杂点
24 | 'useNoise' => true,
25 | // 验证码字体 不设置则随机
26 | 'fontttf' => '',
27 | //背景颜色
28 | 'bg' => [243, 251, 254],
29 | // 验证码图片高度
30 | 'imageH' => 0,
31 | // 验证码图片宽度
32 | 'imageW' => 0,
33 |
34 | // 添加额外的验证码设置
35 | // verify => [
36 | // 'length'=>4,
37 | // ...
38 | //],
39 | ];
40 |
--------------------------------------------------------------------------------
/config/console.php:
--------------------------------------------------------------------------------
1 | [
8 | 'updateall' => 'app\command\UpdateAll',
9 | 'decrypt' => 'app\command\DecryptFile',
10 | 'clean' => 'app\command\Clean',
11 | 'cleanvitejs' => 'app\command\CleanViteJs',
12 | ],
13 | ];
14 |
--------------------------------------------------------------------------------
/config/cookie.php:
--------------------------------------------------------------------------------
1 | 0,
8 | // cookie 保存路径
9 | 'path' => '/',
10 | // cookie 有效域名
11 | 'domain' => '',
12 | // cookie 启用安全传输
13 | 'secure' => false,
14 | // httponly设置
15 | 'httponly' => false,
16 | // 是否使用 setcookie
17 | 'setcookie' => true,
18 | // samesite 设置,支持 'strict' 'lax'
19 | 'samesite' => '',
20 | ];
21 |
--------------------------------------------------------------------------------
/config/database.php:
--------------------------------------------------------------------------------
1 | env('database.driver', 'mysql'),
6 |
7 | // 自定义时间查询规则
8 | 'time_query_rule' => [],
9 |
10 | // 自动写入时间戳字段
11 | // true为自动识别类型 false关闭
12 | // 字符串则明确指定时间字段类型 支持 int timestamp datetime date
13 | 'auto_timestamp' => true,
14 |
15 | // 时间字段取出后的默认时间格式
16 | 'datetime_format' => 'Y-m-d H:i:s',
17 |
18 | // 时间字段配置 配置格式:create_time,update_time
19 | 'datetime_field' => '',
20 |
21 | // 数据库连接配置信息
22 | 'connections' => [
23 | 'mysql' => [
24 | // 数据库类型
25 | 'type' => env('database.type', 'mysql'),
26 | // 服务器地址
27 | 'hostname' => env('database.hostname', '127.0.0.1'),
28 | // 数据库名
29 | 'database' => env('database.database', ''),
30 | // 用户名
31 | 'username' => env('database.username', 'root'),
32 | // 密码
33 | 'password' => env('database.password', ''),
34 | // 端口
35 | 'hostport' => env('database.hostport', '3306'),
36 | // 数据库连接参数
37 | 'params' => [],
38 | // 数据库编码默认采用utf8
39 | 'charset' => env('database.charset', 'utf8mb4'),
40 | // 数据库表前缀
41 | 'prefix' => env('database.prefix', ''),
42 |
43 | // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
44 | 'deploy' => 0,
45 | // 数据库读写是否分离 主从式有效
46 | 'rw_separate' => false,
47 | // 读写分离后 主服务器数量
48 | 'master_num' => 1,
49 | // 指定从服务器序号
50 | 'slave_no' => '',
51 | // 是否严格检查字段是否存在
52 | 'fields_strict' => true,
53 | // 是否需要断线重连
54 | 'break_reconnect' => false,
55 | // 监听SQL
56 | 'trigger_sql' => env('app_debug', true),
57 | // 开启字段缓存
58 | 'fields_cache' => false,
59 | ],
60 |
61 | // 更多的数据库配置信息
62 | ],
63 | ];
64 |
--------------------------------------------------------------------------------
/config/filesystem.php:
--------------------------------------------------------------------------------
1 | env('filesystem.driver', 'local'),
6 | // 磁盘列表
7 | 'disks' => [
8 | 'local' => [
9 | 'type' => 'local',
10 | 'root' => app()->getRuntimePath() . 'storage',
11 | ],
12 | 'public' => [
13 | // 磁盘类型
14 | 'type' => 'local',
15 | // 磁盘路径
16 | 'root' => app()->getRootPath() . 'public/storage',
17 | // 磁盘路径对应的外部URL路径
18 | 'url' => '/storage',
19 | // 可见性
20 | 'visibility' => 'public',
21 | ],
22 | // 更多的磁盘配置信息
23 | ],
24 | ];
25 |
--------------------------------------------------------------------------------
/config/lang.php:
--------------------------------------------------------------------------------
1 | env('lang.default_lang', 'zh-cn'),
9 | // 允许的语言列表
10 | 'allow_lang_list' => [],
11 | // 多语言自动侦测变量名
12 | 'detect_var' => 'lang',
13 | // 是否使用Cookie记录
14 | 'use_cookie' => true,
15 | // 多语言cookie变量
16 | 'cookie_var' => 'think_lang',
17 | // 多语言header变量
18 | 'header_var' => 'think-lang',
19 | // 扩展语言包
20 | 'extend_list' => [],
21 | // Accept-Language转义为对应语言包名称
22 | 'accept_language' => [
23 | 'zh-hans-cn' => 'zh-cn',
24 | ],
25 | // 是否支持语言分组
26 | 'allow_group' => false,
27 | ];
28 |
--------------------------------------------------------------------------------
/config/log.php:
--------------------------------------------------------------------------------
1 | env('log.channel', 'file'),
9 | // 日志记录级别
10 | 'level' => [],
11 | // 日志类型记录的通道 ['error'=>'email',...]
12 | 'type_channel' => [],
13 | // 关闭全局日志写入
14 | 'close' => false,
15 | // 全局日志处理 支持闭包
16 | 'processor' => null,
17 |
18 | // 日志通道列表
19 | 'channels' => [
20 | 'file' => [
21 | // 日志记录方式
22 | 'type' => 'File',
23 | // 日志保存目录
24 | 'path' => '',
25 | // 单文件日志写入
26 | 'single' => false,
27 | // 独立日志级别
28 | 'apart_level' => [],
29 | // 最大日志文件数量
30 | 'max_files' => 0,
31 | // 使用JSON格式记录
32 | 'json' => false,
33 | // 日志处理
34 | 'processor' => null,
35 | // 关闭通道日志写入
36 | 'close' => false,
37 | // 日志输出格式化
38 | 'format' => '[%s][%s] %s',
39 | // 是否实时写入
40 | 'realtime_write' => false,
41 | ],
42 | // 其它日志通道配置
43 | ],
44 |
45 | ];
46 |
--------------------------------------------------------------------------------
/config/middleware.php:
--------------------------------------------------------------------------------
1 | [],
6 | // 优先级设置,此数组中的中间件会按照数组中的顺序优先执行
7 | 'priority' => [],
8 | ];
9 |
--------------------------------------------------------------------------------
/config/route.php:
--------------------------------------------------------------------------------
1 | '/',
9 | // URL伪静态后缀
10 | 'url_html_suffix' => '',
11 | // URL普通方式参数 用于自动生成
12 | 'url_common_param' => true,
13 | // 是否开启路由延迟解析
14 | 'url_lazy_route' => false,
15 | // 是否强制使用路由
16 | 'url_route_must' => true,
17 | // 合并路由规则
18 | 'route_rule_merge' => false,
19 | // 路由是否完全匹配
20 | 'route_complete_match' => false,
21 | // 访问控制器层名称
22 | 'controller_layer' => 'controller',
23 | // 空控制器名
24 | 'empty_controller' => 'Error',
25 | // 是否使用控制器后缀
26 | 'controller_suffix' => false,
27 | // 默认的路由变量规则
28 | 'default_route_pattern' => '[\w\.]+',
29 | // 是否开启请求缓存 true自动缓存 支持设置请求缓存规则
30 | 'request_cache_key' => false,
31 | // 请求缓存有效期
32 | 'request_cache_expire' => null,
33 | // 全局请求缓存排除规则
34 | 'request_cache_except' => [],
35 | // 默认控制器名
36 | 'default_controller' => 'Index',
37 | // 默认操作名
38 | 'default_action' => 'index',
39 | // 操作方法后缀
40 | 'action_suffix' => '',
41 | // 默认JSONP格式返回的处理方法
42 | 'default_jsonp_handler' => 'jsonpReturn',
43 | // 默认JSONP处理方法
44 | 'var_jsonp_handler' => 'callback',
45 | ];
46 |
--------------------------------------------------------------------------------
/config/session.php:
--------------------------------------------------------------------------------
1 | 'PHPSESSID',
9 | // SESSION_ID的提交变量,解决flash上传跨域
10 | 'var_session_id' => '',
11 | // 驱动方式 支持file cache
12 | 'type' => 'file',
13 | // 存储连接标识 当type使用cache的时候有效
14 | 'store' => null,
15 | // 过期时间
16 | 'expire' => 1440,
17 | // 前缀
18 | 'prefix' => '',
19 | ];
20 |
--------------------------------------------------------------------------------
/config/trace.php:
--------------------------------------------------------------------------------
1 | 'Html',
8 | // 读取的日志通道名
9 | 'channel' => '',
10 | ];
11 |
--------------------------------------------------------------------------------
/config/view.php:
--------------------------------------------------------------------------------
1 | 'Think',
9 | // 默认模板渲染规则 1 解析为小写+下划线 2 全部转换小写 3 保持操作方法
10 | 'auto_rule' => 1,
11 | // 模板目录名
12 | 'view_dir_name' => 'view',
13 | // 模板后缀
14 | 'view_suffix' => 'html',
15 | // 模板文件名分隔符
16 | 'view_depr' => DIRECTORY_SEPARATOR,
17 | // 模板引擎普通标签开始标记
18 | 'tpl_begin' => '{',
19 | // 模板引擎普通标签结束标记
20 | 'tpl_end' => '}',
21 | // 标签库标签开始标记
22 | 'taglib_begin' => '{',
23 | // 标签库标签结束标记
24 | 'taglib_end' => '}',
25 | ];
26 |
--------------------------------------------------------------------------------
/data/config/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/data/config/.gitkeep
--------------------------------------------------------------------------------
/data/en/config/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/data/en/config/.gitkeep
--------------------------------------------------------------------------------
/data/en/plugins/folder/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/data/en/plugins/folder/.gitkeep
--------------------------------------------------------------------------------
/data/en/plugins/main/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/data/en/plugins/main/.gitkeep
--------------------------------------------------------------------------------
/data/en/plugins/package/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/data/en/plugins/package/.gitkeep
--------------------------------------------------------------------------------
/data/plugins/folder/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/data/plugins/folder/.gitkeep
--------------------------------------------------------------------------------
/data/plugins/main/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/data/plugins/main/.gitkeep
--------------------------------------------------------------------------------
/data/plugins/other/other/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/data/plugins/other/other/.gitkeep
--------------------------------------------------------------------------------
/data/plugins/package/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/data/plugins/package/.gitkeep
--------------------------------------------------------------------------------
/data/win/config/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/data/win/config/.gitkeep
--------------------------------------------------------------------------------
/data/win/plugins/folder/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/data/win/plugins/folder/.gitkeep
--------------------------------------------------------------------------------
/data/win/plugins/main/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/data/win/plugins/main/.gitkeep
--------------------------------------------------------------------------------
/data/win/plugins/package/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/data/win/plugins/package/.gitkeep
--------------------------------------------------------------------------------
/install.sql:
--------------------------------------------------------------------------------
1 | DROP TABLE IF EXISTS `cloud_config`;
2 | CREATE TABLE `cloud_config` (
3 | `key` varchar(32) NOT NULL,
4 | `value` varchar(255) DEFAULT NULL,
5 | PRIMARY KEY (`key`)
6 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
7 |
8 | INSERT INTO `cloud_config` (`key`, `value`) VALUES
9 | ('admin_username', 'admin'),
10 | ('admin_password', '123456'),
11 | ('bt_url', ''),
12 | ('bt_key', ''),
13 | ('whitelist', '0'),
14 | ('download_page', '1'),
15 | ('new_version', '9.4.0'),
16 | ('update_msg', '暂无更新日志'),
17 | ('update_date', '2025-01-09'),
18 | ('new_version_win', '8.2.2'),
19 | ('update_msg_win', '暂无更新日志'),
20 | ('update_date_win', '2024-12-30'),
21 | ('new_version_en', '7.0.13'),
22 | ('update_msg_en', '暂无更新日志'),
23 | ('update_date_en', '2024-11-17'),
24 | ('new_version_btm', '2.3.0'),
25 | ('update_msg_btm', '暂无更新日志'),
26 | ('update_date_btm', '2024-04-24'),
27 | ('updateall_type', '0'),
28 | ('syskey', 'UqP94LtI8eWAIgCP');
29 |
30 |
31 | DROP TABLE IF EXISTS `cloud_black`;
32 | CREATE TABLE `cloud_black` (
33 | `id` int(11) NOT NULL AUTO_INCREMENT,
34 | `ip` varchar(50) NOT NULL,
35 | `enable` tinyint(1) NOT NULL DEFAULT '1',
36 | `addtime` datetime NOT NULL,
37 | PRIMARY KEY (`id`),
38 | UNIQUE KEY `ip`(`ip`)
39 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
40 |
41 | DROP TABLE IF EXISTS `cloud_white`;
42 | CREATE TABLE `cloud_white` (
43 | `id` int(11) NOT NULL AUTO_INCREMENT,
44 | `ip` varchar(50) NOT NULL,
45 | `enable` tinyint(1) NOT NULL DEFAULT '1',
46 | `addtime` datetime NOT NULL,
47 | PRIMARY KEY (`id`),
48 | UNIQUE KEY `ip`(`ip`)
49 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
50 |
51 | DROP TABLE IF EXISTS `cloud_record`;
52 | CREATE TABLE `cloud_record` (
53 | `id` int(11) NOT NULL AUTO_INCREMENT,
54 | `ip` varchar(50) NOT NULL,
55 | `addtime` datetime NOT NULL,
56 | `usetime` datetime NOT NULL,
57 | PRIMARY KEY (`id`),
58 | UNIQUE KEY `ip`(`ip`)
59 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
60 |
61 | DROP TABLE IF EXISTS `cloud_log`;
62 | CREATE TABLE `cloud_log` (
63 | `id` int(11) NOT NULL AUTO_INCREMENT,
64 | `uid` tinyint(4) NOT NULL DEFAULT '1',
65 | `action` varchar(40) NOT NULL,
66 | `data` varchar(150) DEFAULT NULL,
67 | `addtime` datetime NOT NULL,
68 | PRIMARY KEY (`id`)
69 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
70 |
--------------------------------------------------------------------------------
/public/.htaccess:
--------------------------------------------------------------------------------
1 |
2 | Options +FollowSymlinks -Multiviews
3 | RewriteEngine On
4 |
5 | RewriteCond %{REQUEST_FILENAME} !-d
6 | RewriteCond %{REQUEST_FILENAME} !-f
7 | RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]
8 |
9 |
--------------------------------------------------------------------------------
/public/index.php:
--------------------------------------------------------------------------------
1 |
10 | // +----------------------------------------------------------------------
11 |
12 | // [ 应用入口文件 ]
13 | namespace think;
14 |
15 | require __DIR__ . '/../vendor/autoload.php';
16 |
17 | // 执行HTTP应用并响应
18 | $http = (new App())->http;
19 |
20 | $response = $http->run();
21 |
22 | $response->send();
23 |
24 | $http->end($response);
25 |
--------------------------------------------------------------------------------
/public/install/public.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
3 | pyenv_bin=/www/server/panel/pyenv/bin
4 | rep_path=${pyenv_bin}:$PATH
5 | if [ -d "$pyenv_bin" ];then
6 | PATH=$rep_path
7 | fi
8 | export PATH
9 | export LANG=en_US.UTF-8
10 | export LANGUAGE=en_US:en
11 |
12 | NODE_FILE_CHECK=$(cat /www/server/panel/data/node.json |grep 125.88.182.172)
13 | if [ "${NODE_FILE_CHECK}" ];then
14 | rm -f /www/server/panel/data/node.json
15 | fi
16 |
17 | if [ -f "/www/server/panel/install/d_node.pl" ];then
18 | LOCAL_DATE=$(date +%Y-%m-%d)
19 | FILE_DATE=$(stat /www/server/panel/install/d_node.pl|grep Change|awk '{print $2}')
20 | if [ "${LOCAL_DATE}" != "${FILE_DATE}" ];then
21 | rm -f /www/server/panel/install/d_node.pl
22 | else
23 | test_url=$(cat /www/server/panel/install/d_node.pl)
24 | HTTP_CHECK=$(curl --connect-timeout 3 -m 3 2>/dev/null -w "%{http_code} %{time_total}" ${test_url}/net_test|xargs|awk '{print $2}')
25 | if [ "${HTTP_CHECK}" == "200" ];then
26 | NODE_URL=$test_url
27 | fi
28 | fi
29 | fi
30 |
31 | get_node_url(){
32 | 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);
33 |
34 | if [ -f "/www/server/panel/data/domestic_ip.pl" ];then
35 | 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);
36 | fi
37 |
38 | if [ -f "/www/server/panel/data/foreign_ip.pl" ];then
39 | 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);
40 | fi
41 |
42 | if [ "$1" ];then
43 | nodes=($(echo ${nodes[*]}|sed "s#${1}##"))
44 | fi
45 |
46 | tmp_file1=/dev/shm/net_test1.pl
47 | tmp_file2=/dev/shm/net_test2.pl
48 | [ -f "${tmp_file1}" ] && rm -f ${tmp_file1}
49 | [ -f "${tmp_file2}" ] && rm -f ${tmp_file2}
50 | touch $tmp_file1
51 | touch $tmp_file2
52 | for node in ${nodes[@]};
53 | do
54 | if [ "${node}" == "https://cf1-node.aapanel.com" ];then
55 | NODE_CHECK=$(curl --connect-timeout 3 -m 3 2>/dev/null -w "%{http_code} %{time_total}" ${node}/1net_test|xargs)
56 | else
57 | NODE_CHECK=$(curl --connect-timeout 3 -m 3 2>/dev/null -w "%{http_code} %{time_total}" ${node}/net_test|xargs)
58 | fi
59 | RES=$(echo ${NODE_CHECK}|awk '{print $1}')
60 | NODE_STATUS=$(echo ${NODE_CHECK}|awk '{print $2}')
61 | TIME_TOTAL=$(echo ${NODE_CHECK}|awk '{print $3 * 1000 - 500 }'|cut -d '.' -f 1)
62 | if [ "${NODE_STATUS}" == "200" ];then
63 | if [ $TIME_TOTAL -lt 300 ];then
64 | if [ $RES -ge 1500 ];then
65 | echo "$RES $node" >> $tmp_file1
66 | fi
67 | else
68 | if [ $RES -ge 1500 ];then
69 | echo "$TIME_TOTAL $node" >> $tmp_file2
70 | fi
71 | fi
72 |
73 | i=$(($i+1))
74 | if [ $TIME_TOTAL -lt 300 ];then
75 | if [ $RES -ge 2390 ];then
76 | break;
77 | fi
78 | fi
79 | fi
80 | done
81 |
82 | NODE_URL=$(cat $tmp_file1|sort -r -g -t " " -k 1|head -n 1|awk '{print $2}')
83 | if [ -z "$NODE_URL" ];then
84 | NODE_URL=$(cat $tmp_file2|sort -g -t " " -k 1|head -n 1|awk '{print $2}')
85 | if [ -z "$NODE_URL" ];then
86 | NODE_URL='https://download.bt.cn';
87 | fi
88 | fi
89 | rm -f $tmp_file1
90 | rm -f $tmp_file2
91 | }
92 |
93 | GetCpuStat(){
94 | time1=$(cat /proc/stat |grep 'cpu ')
95 | sleep 1
96 | time2=$(cat /proc/stat |grep 'cpu ')
97 | cpuTime1=$(echo ${time1}|awk '{print $2+$3+$4+$5+$6+$7+$8}')
98 | cpuTime2=$(echo ${time2}|awk '{print $2+$3+$4+$5+$6+$7+$8}')
99 | runTime=$((${cpuTime2}-${cpuTime1}))
100 | idelTime1=$(echo ${time1}|awk '{print $5}')
101 | idelTime2=$(echo ${time2}|awk '{print $5}')
102 | idelTime=$((${idelTime2}-${idelTime1}))
103 | useTime=$(((${runTime}-${idelTime})*3))
104 | [ ${useTime} -gt ${runTime} ] && cpuBusy="true"
105 | if [ "${cpuBusy}" == "true" ]; then
106 | cpuCore=$((${cpuInfo}/2))
107 | else
108 | cpuCore=$((${cpuInfo}-1))
109 | fi
110 | }
111 | GetPackManager(){
112 | if [ -f "/usr/bin/yum" ] && [ -f "/etc/yum.conf" ]; then
113 | PM="yum"
114 | elif [ -f "/usr/bin/apt-get" ] && [ -f "/usr/bin/dpkg" ]; then
115 | PM="apt-get"
116 | fi
117 | }
118 |
119 | bt_check(){
120 | p_path=/www/server/panel/class/panelPlugin.py
121 | if [ -f $p_path ];then
122 | is_ext=$(cat $p_path|grep btwaf)
123 | if [ "$is_ext" != "" ];then
124 | send_check
125 | fi
126 | fi
127 |
128 | p_path=/www/server/panel/BTPanel/templates/default/index.html
129 | if [ -f $p_path ];then
130 | is_ext=$(cat $p_path|grep fbi)
131 | if [ "$is_ext" != "" ];then
132 | send_check
133 | fi
134 | fi
135 | }
136 |
137 | send_check(){
138 | chattr -i /etc/init.d/bt
139 | chmod +x /etc/init.d/bt
140 | p_path2=/www/server/panel/class/common.py
141 | p_version=$(cat $p_path2|grep "version = "|awk '{print $3}'|tr -cd [0-9.])
142 | curl -sS --connect-timeout 3 -m 60 http://www.example.com/api/panel/notpro?version=$p_version
143 | NODE_URL=""
144 | exit 0;
145 | }
146 | GetSysInfo(){
147 | if [ "${PM}" = "yum" ]; then
148 | SYS_VERSION=$(cat /etc/redhat-release)
149 | elif [ "${PM}" = "apt-get" ]; then
150 | SYS_VERSION=$(cat /etc/issue)
151 | fi
152 | SYS_INFO=$(uname -msr)
153 | SYS_BIT=$(getconf LONG_BIT)
154 | MEM_TOTAL=$(free -m|grep Mem|awk '{print $2}')
155 | CPU_INFO=$(getconf _NPROCESSORS_ONLN)
156 | GCC_VER=$(gcc -v 2>&1|grep "gcc version"|awk '{print $3}')
157 | CMAKE_VER=$(cmake --version|grep version|awk '{print $3}')
158 |
159 | echo -e ${SYS_VERSION}
160 | echo -e Bit:${SYS_BIT} Mem:${MEM_TOTAL}M Core:${CPU_INFO} gcc:${GCC_VER} cmake:${CMAKE_VER}
161 | echo -e ${SYS_INFO}
162 | }
163 | cpuInfo=$(getconf _NPROCESSORS_ONLN)
164 | if [ "${cpuInfo}" -ge "4" ];then
165 | GetCpuStat
166 | else
167 | cpuCore="1"
168 | fi
169 | GetPackManager
170 |
171 | if [ ! $NODE_URL ];then
172 | EN_CHECK=$(cat /www/server/panel/config/config.json |grep English)
173 | if [ -z "${EN_CHECK}" ];then
174 | echo '正在选择下载节点...';
175 | else
176 | echo "selecting download node...";
177 | fi
178 | get_node_url
179 | fi
180 |
181 |
182 |
--------------------------------------------------------------------------------
/public/install/src/bt-monitor-2.3.0.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/public/install/src/bt-monitor-2.3.0.zip
--------------------------------------------------------------------------------
/public/install/src/panel6.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/public/install/src/panel6.zip
--------------------------------------------------------------------------------
/public/install/src/panel_7_en.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/public/install/src/panel_7_en.zip
--------------------------------------------------------------------------------
/public/install/update/LinuxPanel-9.5.0.pl:
--------------------------------------------------------------------------------
1 | {"hash": "c097e387cb3f2baf34a222191de7130bd878215ffa4ba8cef2d337e3466e6963", "update_time": "1747723203"}
--------------------------------------------------------------------------------
/public/install/update/LinuxPanel-9.6.0.pl:
--------------------------------------------------------------------------------
1 | {"hash": "d869ee4b8bdcfae324c4fdef9ec647db4a1529e7f6890b8cb4693f40b8a24626", "update_time": "1748242787"}
--------------------------------------------------------------------------------
/public/install/update/LinuxPanel-9.6.0.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/public/install/update/LinuxPanel-9.6.0.zip
--------------------------------------------------------------------------------
/public/install/update/LinuxPanel_EN-7.0.16.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/public/install/update/LinuxPanel_EN-7.0.16.zip
--------------------------------------------------------------------------------
/public/install/update6.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
3 | export PATH
4 | LANG=en_US.UTF-8
5 |
6 | Btapi_Url='http://www.example.com'
7 |
8 | if [ ! -d /www/server/panel/BTPanel ];then
9 | echo "============================================="
10 | echo "错误, 5.x不可以使用此命令升级!"
11 | echo "5.9平滑升级到6.0的命令:curl http://download.bt.cn/install/update_to_6.sh|bash"
12 | exit 0;
13 | fi
14 |
15 | if [ ! -f "/www/server/panel/pyenv/bin/python3" ];then
16 | echo "============================================="
17 | echo "错误, 当前面板过旧/py-2.7/无pyenv环境,无法升级至最新版面板"
18 | echo "请截图发帖至论坛www.bt.cn/bbs求助"
19 | exit 0;
20 | fi
21 |
22 | if [ -f "/etc/redhat-release" ];then
23 | Centos6Check=$(cat /etc/redhat-release | grep ' 6.' | grep -iE 'centos|Red Hat')
24 | if [ "${Centos6Check}" ];then
25 | echo "Centos6不支持升级宝塔面板,建议备份数据重装更换Centos7/8安装宝塔面板"
26 | exit 1
27 | fi
28 | Centos8Check=$(cat /etc/redhat-release | grep ' 8.' | grep -iE 'centos|Red Hat')
29 | if [ "${Centos8Check}" ];then
30 | if [ ! -f "/usr/bin/python" ] && [ -f "/usr/bin/python3" ] && [ ! -d "/www/server/panel/pyenv" ]; then
31 | ln -sf /usr/bin/python3 /usr/bin/python
32 | fi
33 | fi
34 | fi
35 |
36 | mypip="pip"
37 | env_path=/www/server/panel/pyenv/bin/activate
38 | if [ -f $env_path ];then
39 | mypip="/www/server/panel/pyenv/bin/pip"
40 | fi
41 |
42 | if [ -f "/www/server/panel/data/down_url.pl" ];then
43 | D_NODE_URL=$(cat /www/server/panel/data/down_url.pl|grep bt.cn)
44 | fi
45 |
46 | if [ -z "${D_NODE_URL}" ];then
47 | D_NODE_URL="download.bt.cn"
48 | fi
49 |
50 | download_Url=$D_NODE_URL
51 |
52 |
53 | Set_Centos7_Repo(){
54 | if [ -f "/etc/yum.repos.d/docker-ce.repo" ];then
55 | mv /etc/yum.repos.d/docker-ce.repo /etc/yum.repos.d/docker-ce.repo_backup
56 | fi
57 | MIRROR_CHECK=$(cat /etc/yum.repos.d/CentOS-Base.repo |grep "[^#]mirror.centos.org")
58 | if [ "${MIRROR_CHECK}" ] && [ "${is64bit}" == "64" ];then
59 | \cp -rpa /etc/yum.repos.d/ /etc/yumBak
60 | sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*.repo
61 | sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.epel.cloud|g' /etc/yum.repos.d/CentOS-*.repo
62 | fi
63 |
64 | TSU_MIRROR_CHECK=$(cat /etc/yum.repos.d/CentOS-Base.repo |grep "tuna.tsinghua.edu.cn")
65 | if [ "${TSU_MIRROR_CHECK}" ];then
66 | \cp -rpa /etc/yum.repos.d/ /etc/yumBak
67 | sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*.repo
68 | sed -i 's|#baseurl=https://mirrors.tuna.tsinghua.edu.cn|baseurl=http://vault.epel.cloud|g' /etc/yum.repos.d/CentOS-*.repo
69 | sed -i 's|#baseurl=http://mirrors.tuna.tsinghua.edu.cn|baseurl=http://vault.epel.cloud|g' /etc/yum.repos.d/CentOS-*.repo
70 | fi
71 |
72 | ALI_CLOUD_CHECK=$(grep Alibaba /etc/motd)
73 | Tencent_Cloud=$(cat /etc/hostname |grep -E VM-[0-9]+-[0-9]+)
74 | if [ "${ALI_CLOUD_CHECK}" ] || [ "${Tencent_Cloud}" ];then
75 | return
76 | fi
77 |
78 | yum install tree -y
79 | if [ "$?" != "0" ] ;then
80 | TAR_CHECK=$(which tree)
81 | if [ "$?" == "0" ] ;then
82 | \cp -rpa /etc/yum.repos.d/ /etc/yumBak
83 | if [ -z "${download_Url}" ];then
84 | download_Url="http://download.bt.cn"
85 | fi
86 | curl -Ss --connect-timeout 5 -m 60 -O ${download_Url}/src/el7repo.tar.gz
87 | rm -f /etc/yum.repos.d/*.repo
88 | tar -xvzf el7repo.tar.gz -C /etc/yum.repos.d/
89 | fi
90 | fi
91 |
92 | yum install tree -y
93 | if [ "$?" != "0" ] ;then
94 | sed -i "s/vault.epel.cloud/mirrors.cloud.tencent.com/g" /etc/yum.repos.d/*.repo
95 | fi
96 | }
97 | if [ -f "/etc/redhat-release" ];then
98 | Centos7Check=$(cat /etc/redhat-release | grep ' 7.' | grep -iE 'centos|Red Hat')
99 | if [ "${Centos7Check}" ];then
100 | Set_Centos7_Repo
101 | fi
102 | fi
103 | setup_path=/www
104 | version=$(curl -Ss --connect-timeout 5 -m 2 $Btapi_Url/api/panel/get_version)
105 | if [ -z "$version" ];then
106 | version='9.5.0'
107 | fi
108 | armCheck=$(uname -m|grep arm)
109 | if [ "${armCheck}" ];then
110 | version='7.7.0'
111 | fi
112 |
113 | if [ "$1" ];then
114 | version=$1
115 | fi
116 | wget -T 5 -O /tmp/panel.zip $Btapi_Url/install/update/LinuxPanel-${version}.zip
117 | dsize=$(du -b /tmp/panel.zip|awk '{print $1}')
118 | if [ $dsize -lt 10240 ];then
119 | echo "获取更新包失败,请稍后更新或联系宝塔运维"
120 | exit;
121 | fi
122 |
123 | unzip -o /tmp/panel.zip -d $setup_path/server/ > /dev/null
124 | rm -f /tmp/panel.zip
125 | cd $setup_path/server/panel/
126 | check_bt=`cat /etc/init.d/bt`
127 | if [ "${check_bt}" = "" ];then
128 | rm -f /etc/init.d/bt
129 | wget -O /etc/init.d/bt $download_Url/install/src/bt7.init -T 20
130 | chmod +x /etc/init.d/bt
131 | fi
132 | echo "=============================================================="
133 | echo "正在修复面板依赖问题"
134 | rm -f /www/server/panel/*.pyc
135 | rm -f /www/server/panel/class/*.pyc
136 | #pip install flask_sqlalchemy
137 | #pip install itsdangerous==0.24
138 |
139 | if [ -f "/www/server/panel/pyenv/bin/pip3" ];then
140 | btpip_path="/www/server/panel/pyenv/bin/pip3"
141 | FlaskV=$($btpip_path list 2>/dev/null|grep "Flask " |awk '{print $2}'|cut -f 1 -d .)
142 | piplist_count=$($btpip_path list 2>/dev/null|wc -l)
143 | if [ "${FlaskV}" -le "2" ] && [ "${piplist_count}" -le "118" ];then
144 | echo "检测到面板运行环境过老,正常尝试修复面板依赖"
145 | pyenv_path="/www/server/panel"
146 | wget -O $pyenv_path/pyenv/pip.txt $download_Url/install/pyenv/pip-3.7.16.txt -T 5
147 | $pyenv_path/pyenv/bin/pip install -U pip
148 | $pyenv_path/pyenv/bin/pip install -U setuptools==65.5.0
149 | $pyenv_path/pyenv/bin/pip install -U wheel==0.34.2
150 | $pyenv_path/pyenv/bin/pip install -r $pyenv_path/pyenv/pip.txt
151 | echo "依赖修复完成,如面板仍无法正常访问,请联系宝塔官方人员进行求助"
152 | fi
153 |
154 | #wget -O pip-packs.txt $download_Url/install/pyenv/pip-packs.txt
155 | #PIP_PACKS=$(cat pip-packs.txt)
156 | #for P_PACK in ${PIP_PACKS};
157 | #do
158 | # btpip show ${P_PACK} > /dev/null 2>&1
159 | # if [ "$?" == "1" ];then
160 | # btpip install ${P_PACK}
161 | # fi
162 | #done
163 | fi
164 |
165 |
166 | pip_list=$($mypip list 2>&1)
167 | request_v=$(btpip list 2>/dev/null|grep "requests "|awk '{print $2}'|cut -d '.' -f 2)
168 | if [ "$request_v" = "" ] || [ "${request_v}" -gt "28" ];then
169 | $mypip install requests==2.27.1
170 | fi
171 |
172 | NATSORT_C=$(echo $pip_list|grep natsort)
173 | if [ -z "${NATSORT_C}" ];then
174 | btpip install natsort
175 | fi
176 |
177 | openssl_v=$(echo "$pip_list"|grep pyOpenSSL)
178 | if [ "$openssl_v" = "" ];then
179 | $mypip install pyOpenSSL
180 | fi
181 |
182 | #cffi_v=$(echo "$pip_list"|grep cffi|grep 1.12.)
183 | #if [ "$cffi_v" = "" ];then
184 | # $mypip install cffi==1.12.3
185 | #fi
186 |
187 | pymysql=$(echo "$pip_list"|grep pymysql)
188 | if [ "$pymysql" = "" ];then
189 | $mypip install pymysql
190 | fi
191 | GEVENT_V=$(btpip list 2> /dev/null|grep "gevent "|awk '{print $2}'|cut -f 1 -d '.')
192 | if [ "${GEVENT_V}" -le "1" ];then
193 | /www/server/panel/pyenv/bin/pip3 install -I gevent
194 | fi
195 |
196 | BROTLI_C=$(btpip list 2> /dev/null |grep Brotli)
197 | if [ -z "$BROTLI_C" ]; then
198 | btpip install brotli
199 | fi
200 |
201 | PYMYSQL_C=$(btpip list 2> /dev/null |grep PyMySQL)
202 | if [ -z "$PYMYSQL_C" ]; then
203 | btpip install PyMySQL
204 | fi
205 |
206 |
207 | PY_CRPYT=$(btpip list 2> /dev/null |grep cryptography|awk '{print $2}'|cut -f 1 -d '.')
208 | if [ "${PY_CRPYT}" -le "10" ];then
209 | btpip install pyOpenSSL==24.1.0
210 | btpip install cryptography==42.0.5
211 | fi
212 |
213 | PYMYSQL_SSL_CHECK=$(btpython -c "import pymysql" 2>&1|grep "AttributeError: module 'cryptography.hazmat.bindings._rust.openssl'")
214 | if [ "${PYMYSQL_SSL_CHECK}" ];then
215 | btpip uninstall pyopenssl cryptography -y
216 | btpip install pyopenssl cryptography
217 | fi
218 |
219 | btpip uninstall enum34 -y
220 |
221 | GEOIP_C=$(echo $pip_list|grep geoip2)
222 | if [ -z "${GEOIP_C}" ];then
223 | btpip install geoip2==4.7.0
224 | fi
225 |
226 | # PANDAS_C=$(echo $pip_list|grep pandas)
227 | # if [ -z "${PANDAS_C}" ];then
228 | # btpip install pandas
229 | # fi
230 |
231 | pymysql=$(echo "$pip_list"|grep pycryptodome)
232 | if [ "$pymysql" = "" ];then
233 | $mypip install pycryptodome
234 | fi
235 |
236 | echo "修复面板依赖完成!"
237 | echo "==========================================="
238 |
239 | RE_UPDATE=$(cat /www/server/panel/data/db/update)
240 | if [ "$RE_UPDATE" -ge "4" ];then
241 | echo "2" > /www/server/panel/data/db/update
242 | fi
243 |
244 | #psutil=$(echo "$pip_list"|grep psutil|awk '{print $2}'|grep '5.7.')
245 | #if [ "$psutil" = "" ];then
246 | # $mypip install -U psutil
247 | #fi
248 |
249 | if [ -d /www/server/panel/class/BTPanel ];then
250 | rm -rf /www/server/panel/class/BTPanel
251 | fi
252 | rm -f /www/server/panel/class/*.so
253 | if [ ! -f /www/server/panel/data/not_workorder.pl ]; then
254 | echo "True" > /www/server/panel/data/not_workorder.pl
255 | fi
256 | if [ ! -f /www/server/panel/data/userInfo.json ]; then
257 | 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
258 | fi
259 | if [ ! -f /www/server/panel/data/panel_nps.pl ]; then
260 | echo "" > /www/server/panel/data/panel_nps.pl
261 | fi
262 | if [ ! -f /www/server/panel/data/btwaf_nps.pl ]; then
263 | echo "" > /www/server/panel/data/btwaf_nps.pl
264 | fi
265 | if [ ! -f /www/server/panel/data/tamper_proof_nps.pl ]; then
266 | echo "" > /www/server/panel/data/tamper_proof_nps.pl
267 | fi
268 | if [ ! -f /www/server/panel/data/total_nps.pl ]; then
269 | echo "" > /www/server/panel/data/total_nps.pl
270 | fi
271 |
272 | echo "==========================================="
273 | echo "正在更新面板文件..............."
274 | sleep 1
275 | echo "更新完成!"
276 | echo "==========================================="
277 |
278 | chattr -i /etc/init.d/bt
279 | chmod +x /etc/init.d/bt
280 | echo "====================================="
281 | rm -f /dev/shm/bt_sql_tips.pl
282 | kill $(ps aux|grep -E "task.pyc|main.py"|grep -v grep|awk '{print $2}')
283 | /etc/init.d/bt restart
284 | echo 'True' > /www/server/panel/data/restart.pl
285 | pkill -9 gunicorn &
286 | echo "已成功升级到[$version]${Ver}";
287 |
288 |
289 |
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Disallow: /
3 |
--------------------------------------------------------------------------------
/public/router.php:
--------------------------------------------------------------------------------
1 |
10 | // +----------------------------------------------------------------------
11 | // $Id$
12 |
13 | if (is_file($_SERVER["DOCUMENT_ROOT"] . $_SERVER["SCRIPT_NAME"])) {
14 | return false;
15 | } else {
16 | $_SERVER["SCRIPT_FILENAME"] = __DIR__ . '/index.php';
17 |
18 | require __DIR__ . "/index.php";
19 | }
20 |
--------------------------------------------------------------------------------
/public/static/css/bootstrap-table.css:
--------------------------------------------------------------------------------
1 | .bootstrap-table .fixed-table-toolbar::after{content:"";display:block;clear:both}.bootstrap-table .fixed-table-toolbar .bs-bars,.bootstrap-table .fixed-table-toolbar .columns,.bootstrap-table .fixed-table-toolbar .search{position:relative;margin-top:10px;margin-bottom:10px}.bootstrap-table .fixed-table-toolbar .columns .btn-group>.btn-group{display:inline-block;margin-left:-1px!important}.bootstrap-table .fixed-table-toolbar .columns .btn-group>.btn-group>.btn{border-radius:0}.bootstrap-table .fixed-table-toolbar .columns .btn-group>.btn-group:first-child>.btn{border-top-left-radius:4px;border-bottom-left-radius:4px}.bootstrap-table .fixed-table-toolbar .columns .btn-group>.btn-group:last-child>.btn{border-top-right-radius:4px;border-bottom-right-radius:4px}.bootstrap-table .fixed-table-toolbar .columns .dropdown-menu{text-align:left;max-height:300px;overflow:auto;-ms-overflow-style:scrollbar;z-index:1001}.bootstrap-table .fixed-table-toolbar .columns label{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.4286}.bootstrap-table .fixed-table-toolbar .columns-left{margin-right:5px}.bootstrap-table .fixed-table-toolbar .columns-right{margin-left:5px}.bootstrap-table .fixed-table-toolbar .pull-right .dropdown-menu{right:0;left:auto}.bootstrap-table .fixed-table-container{position:relative;clear:both}.bootstrap-table .fixed-table-container .table{width:100%;margin-bottom:0!important}.bootstrap-table .fixed-table-container .table td,.bootstrap-table .fixed-table-container .table th{vertical-align:middle;box-sizing:border-box}.bootstrap-table .fixed-table-container .table thead th{vertical-align:bottom;padding:0;margin:0}.bootstrap-table .fixed-table-container .table thead th:focus{outline:0 solid transparent}.bootstrap-table .fixed-table-container .table thead th.detail{width:30px}.bootstrap-table .fixed-table-container .table thead th .th-inner{padding:.75rem;vertical-align:bottom;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.bootstrap-table .fixed-table-container .table thead th .sortable{cursor:pointer;background-position:right;background-repeat:no-repeat;padding-right:30px!important}.bootstrap-table .fixed-table-container .table thead th .both{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAQAAADYWf5HAAAAkElEQVQoz7X QMQ5AQBCF4dWQSJxC5wwax1Cq1e7BAdxD5SL+Tq/QCM1oNiJidwox0355mXnG/DrEtIQ6azioNZQxI0ykPhTQIwhCR+BmBYtlK7kLJYwWCcJA9M4qdrZrd8pPjZWPtOqdRQy320YSV17OatFC4euts6z39GYMKRPCTKY9UnPQ6P+GtMRfGtPnBCiqhAeJPmkqAAAAAElFTkSuQmCC")}.bootstrap-table .fixed-table-container .table thead th .asc{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZ0lEQVQ4y2NgGLKgquEuFxBPAGI2ahhWCsS/gDibUoO0gPgxEP8H4ttArEyuQYxAPBdqEAxPBImTY5gjEL9DM+wTENuQahAvEO9DMwiGdwAxOymGJQLxTyD+jgWDxCMZRsEoGAVoAADeemwtPcZI2wAAAABJRU5ErkJggg==")}.bootstrap-table .fixed-table-container .table thead th .desc{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZUlEQVQ4y2NgGAWjYBSggaqGu5FA/BOIv2PBIPFEUgxjB+IdQPwfC94HxLykus4GiD+hGfQOiB3J8SojEE9EM2wuSJzcsFMG4ttQgx4DsRalkZENxL+AuJQaMcsGxBOAmGvopk8AVz1sLZgg0bsAAAAASUVORK5CYII= ")}.bootstrap-table .fixed-table-container .table tbody tr.selected td{background-color:rgba(0,0,0,.075)}.bootstrap-table .fixed-table-container .table tbody tr.no-records-found td{text-align:center}.bootstrap-table .fixed-table-container .table tbody tr .card-view{display:flex}.bootstrap-table .fixed-table-container .table tbody tr .card-view .card-view-title{font-weight:700;display:inline-block;min-width:30%;width:auto!important;text-align:left!important}.bootstrap-table .fixed-table-container .table tbody tr .card-view .card-view-value{width:100%!important;text-align:left!important}.bootstrap-table .fixed-table-container .table .bs-checkbox{text-align:center}.bootstrap-table .fixed-table-container .table .bs-checkbox label{margin-bottom:0}.bootstrap-table .fixed-table-container .table .bs-checkbox label input[type=checkbox],.bootstrap-table .fixed-table-container .table .bs-checkbox label input[type=radio]{margin:0 auto!important}.bootstrap-table .fixed-table-container .table.table-sm .th-inner{padding:.3rem}.bootstrap-table .fixed-table-container.fixed-height:not(.has-footer){border-bottom:1px solid #dee2e6}.bootstrap-table .fixed-table-container.fixed-height.has-card-view{border-top:1px solid #dee2e6;border-bottom:1px solid #dee2e6}.bootstrap-table .fixed-table-container.fixed-height .fixed-table-border{border-left:1px solid #dee2e6;border-right:1px solid #dee2e6}.bootstrap-table .fixed-table-container.fixed-height .table thead th{border-bottom:1px solid #dee2e6}.bootstrap-table .fixed-table-container.fixed-height .table-dark thead th{border-bottom:1px solid #32383e}.bootstrap-table .fixed-table-container .fixed-table-header{overflow:hidden}.bootstrap-table .fixed-table-container .fixed-table-body{overflow-x:auto;overflow-y:auto;height:100%}.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading{align-items:center;background:#fff;display:flex;justify-content:center;position:absolute;bottom:0;width:100%;max-width:100%;z-index:1000;transition:visibility 0s,opacity .15s ease-in-out;opacity:0;visibility:hidden}.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading.open{visibility:visible;opacity:1}.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap{align-items:baseline;display:flex;justify-content:center}.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap .loading-text{margin-right:6px}.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap .animation-wrap{align-items:center;display:flex;justify-content:center}.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap .animation-dot,.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap .animation-wrap::after,.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap .animation-wrap::before{content:"";animation-duration:1.5s;animation-iteration-count:infinite;animation-name:loading;background:#212529;border-radius:50%;display:block;height:5px;margin:0 4px;opacity:0;width:5px}.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap .animation-dot{animation-delay:.3s}.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap .animation-wrap::after{animation-delay:.6s}.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading.table-dark{background:#212529}.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading.table-dark .animation-dot,.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading.table-dark .animation-wrap::after,.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading.table-dark .animation-wrap::before{background:#fff}.bootstrap-table .fixed-table-container .fixed-table-footer{overflow:hidden}.bootstrap-table .fixed-table-pagination::after{content:"";display:block;clear:both}.bootstrap-table .fixed-table-pagination>.pagination,.bootstrap-table .fixed-table-pagination>.pagination-detail{margin-top:10px;margin-bottom:10px}.bootstrap-table .fixed-table-pagination>.pagination-detail .pagination-info{line-height:34px;margin-right:5px}.bootstrap-table .fixed-table-pagination>.pagination-detail .page-list{display:inline-block}.bootstrap-table .fixed-table-pagination>.pagination-detail .page-list .btn-group{position:relative;display:inline-block;vertical-align:middle}.bootstrap-table .fixed-table-pagination>.pagination-detail .page-list .btn-group .dropdown-menu{margin-bottom:0}.bootstrap-table .fixed-table-pagination>.pagination ul.pagination{margin:0}.bootstrap-table .fixed-table-pagination>.pagination ul.pagination li.page-intermediate a{color:#c8c8c8}.bootstrap-table .fixed-table-pagination>.pagination ul.pagination li.page-intermediate a::before{content:"\2B05"}.bootstrap-table .fixed-table-pagination>.pagination ul.pagination li.page-intermediate a::after{content:"\27A1"}.bootstrap-table .fixed-table-pagination>.pagination ul.pagination li.disabled a{pointer-events:none;cursor:default}.bootstrap-table.fullscreen{position:fixed;top:0;left:0;z-index:1050;width:100%!important;background:#fff;height:calc(100vh);overflow-y:scroll}.bootstrap-table.bootstrap4 .pagination-lg .page-link,.bootstrap-table.bootstrap5 .pagination-lg .page-link{padding:.5rem 1rem}.bootstrap-table.bootstrap5 .float-left{float:left}.bootstrap-table.bootstrap5 .float-right{float:right}div.fixed-table-scroll-inner{width:100%;height:200px}div.fixed-table-scroll-outer{top:0;left:0;visibility:hidden;width:200px;height:150px;overflow:hidden}@keyframes loading{0%{opacity:0}50%{opacity:1}to{opacity:0}}
2 | .table-bottom-border{border-bottom: 2px solid #ddd;}
3 | @media screen and (max-width:767px){.fixed-table-body{border:1px solid #ddd}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{white-space:nowrap}.columns-right{display:none;}}
4 | .bootstrap-table.bootstrap3 .fixed-table-pagination>.pagination .page-jump-to{display:inline-block}.bootstrap-table.bootstrap3 .fixed-table-pagination>.pagination .input-group-btn{width:auto}.bootstrap-table .fixed-table-pagination>.pagination .page-jump-to input{width:70px;margin-left:5px;text-align:center;float:left}
5 | .form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}
6 | .form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}
7 |
--------------------------------------------------------------------------------
/public/static/file/en/kaixin.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/public/static/file/en/kaixin.zip
--------------------------------------------------------------------------------
/public/static/file/kaixin.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/public/static/file/kaixin.zip
--------------------------------------------------------------------------------
/public/static/file/win/kaixin.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/public/static/file/win/kaixin.zip
--------------------------------------------------------------------------------
/public/static/images/aapanel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/public/static/images/aapanel.png
--------------------------------------------------------------------------------
/public/static/images/account.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/public/static/images/account.png
--------------------------------------------------------------------------------
/public/static/images/addc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/public/static/images/addc.png
--------------------------------------------------------------------------------
/public/static/images/bt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/public/static/images/bt.png
--------------------------------------------------------------------------------
/public/static/images/bt_monitor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/public/static/images/bt_monitor.png
--------------------------------------------------------------------------------
/public/static/images/bto_copy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/public/static/images/bto_copy.png
--------------------------------------------------------------------------------
/public/static/images/close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/public/static/images/close.png
--------------------------------------------------------------------------------
/public/static/images/downico1_01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/public/static/images/downico1_01.png
--------------------------------------------------------------------------------
/public/static/images/downico2_01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/public/static/images/downico2_01.png
--------------------------------------------------------------------------------
/public/static/images/eye.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/public/static/images/eye.png
--------------------------------------------------------------------------------
/public/static/images/eye_close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/public/static/images/eye_close.png
--------------------------------------------------------------------------------
/public/static/images/footbg_02.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/public/static/images/footbg_02.jpg
--------------------------------------------------------------------------------
/public/static/images/hot_03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/public/static/images/hot_03.png
--------------------------------------------------------------------------------
/public/static/images/i1abg_03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/public/static/images/i1abg_03.png
--------------------------------------------------------------------------------
/public/static/images/i1aico_03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/public/static/images/i1aico_03.png
--------------------------------------------------------------------------------
/public/static/images/i1ico_03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/public/static/images/i1ico_03.png
--------------------------------------------------------------------------------
/public/static/images/ico-copy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/public/static/images/ico-copy.png
--------------------------------------------------------------------------------
/public/static/images/install_type_select.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/public/static/images/install_type_select.png
--------------------------------------------------------------------------------
/public/static/images/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
115 |
--------------------------------------------------------------------------------
/public/static/images/navicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/public/static/images/navicon.png
--------------------------------------------------------------------------------
/public/static/images/prd_1_03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/public/static/images/prd_1_03.png
--------------------------------------------------------------------------------
/public/static/images/prd_2_03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/public/static/images/prd_2_03.png
--------------------------------------------------------------------------------
/public/static/images/wave.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/static/js/custom.js:
--------------------------------------------------------------------------------
1 | var location_url = window.location.href;
2 | var parameter_str = location_url.split('?')[1];
3 | if (parameter_str !== undefined) {
4 | parameter_str = parameter_str.split('#')[0];
5 | var $_GET = {};
6 | var parameter_arr = parameter_str.split('&');
7 | var tmp_arr;
8 | for (var i = 0, len = parameter_arr.length; i <= len - 1; i++) {
9 | tmp_arr = parameter_arr[i].split('=');
10 | $_GET[tmp_arr[0]] = decodeURIComponent(tmp_arr[1]);
11 | }
12 | window.$_GET = $_GET;
13 | } else {
14 | window.$_GET = [];
15 | }
16 |
17 | function searchSubmit(){
18 | $('#listTable').bootstrapTable('refresh');
19 | return false;
20 | }
21 | function searchClear(){
22 | $('#searchToolbar').find('input[name]').each(function() {
23 | $(this).val('');
24 | });
25 | $('#searchToolbar').find('select[name]').each(function() {
26 | $(this).find('option:first').prop("selected", 'selected');
27 | });
28 | $('#listTable').bootstrapTable('refresh');
29 | }
30 | function updateToolbar(){
31 | $('#searchToolbar').find(':input[name]').each(function() {
32 | var name = $(this).attr('name');
33 | if(typeof window.$_GET[name] != 'undefined')
34 | $(this).val(window.$_GET[name]);
35 | })
36 | }
37 | function updateQueryStr(obj){
38 | var arr = [];
39 | for (var p in obj){
40 | if (obj.hasOwnProperty(p) && typeof obj[p] != 'undefined' && obj[p] != '') {
41 | arr.push(p + "=" + encodeURIComponent(obj[p]));
42 | }
43 | }
44 | history.replaceState({}, null, '?'+arr.join("&"));
45 | }
46 |
47 | if (typeof $.fn.bootstrapTable !== "undefined") {
48 | $.fn.bootstrapTable.custom = {
49 | method: 'post',
50 | contentType: "application/x-www-form-urlencoded",
51 | sortable: true,
52 | pagination: true,
53 | sidePagination: 'server',
54 | pageNumber: 1,
55 | pageSize: 20,
56 | pageList: [10, 15, 20, 30, 50, 100],
57 | loadingFontSize: '18px',
58 | toolbar: '#searchToolbar',
59 | showColumns: true,
60 | minimumCountColumns: 2,
61 | showToggle: true,
62 | showFullscreen: true,
63 | paginationPreText: '前页',
64 | paginationNextText: '后页',
65 | showJumpTo: true,
66 | paginationLoop: false,
67 | queryParamsType: '',
68 | queryParams: function(params) {
69 | $('#searchToolbar').find(':input[name]').each(function() {
70 | params[$(this).attr('name')] = $(this).val()
71 | })
72 | updateQueryStr(params);
73 | params.offset = params.pageSize * (params.pageNumber-1);
74 | params.limit = params.pageSize;
75 | return params;
76 | },
77 | formatLoadingMessage: function(){
78 | return '';
79 | },
80 | formatShowingRows: function(t,n,r,e){
81 | return '显示第 '+t+' 到第 '+n+' 条, 总共
'+r+' 条';
82 | },
83 | formatRecordsPerPage: function(t){
84 | return '每页显示 '+t+' 条';
85 | },
86 | formatNoMatches: function(){
87 | return '没有找到匹配的记录';
88 | }
89 | };
90 | $.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.custom);
91 | }
92 |
93 | function httpGet(url, callback){
94 | $.ajax({
95 | url: url,
96 | type: 'get',
97 | dataType: 'json',
98 | success: function (res) {
99 | callback(res)
100 | },
101 | error: function () {
102 | if (typeof layer !== "undefined") {
103 | layer.closeAll();
104 | layer.msg('服务器错误');
105 | }
106 | }
107 | });
108 | }
109 |
110 | function httpPost(url, data, callback){
111 | $.ajax({
112 | url: url,
113 | type: 'post',
114 | data: data,
115 | dataType: 'json',
116 | success: function (res) {
117 | callback(res)
118 | },
119 | error: function () {
120 | if (typeof layer !== "undefined") {
121 | layer.closeAll();
122 | layer.msg('服务器错误');
123 | }
124 | }
125 | });
126 | }
127 |
128 | var isMobile = function(){
129 | if( /Android|SymbianOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini|Windows Phone|Midp/i.test(navigator.userAgent)) {
130 | return true;
131 | }
132 | return false;
133 | }
--------------------------------------------------------------------------------
/public/static/js/dx.js:
--------------------------------------------------------------------------------
1 | // JS is for dynamically creating and moving the birds across the screen.
2 | // The actual bird flapping and flight wave is CSS animation.
3 |
4 | // Adjust these options here to customize the scene.
5 | let options = {
6 | delay: 500,
7 | speedRange: [2, 5],
8 | angleRange: [-30, 30],
9 | sizeRange: [15, 30],
10 | };
11 |
12 | let bird = document.createElement('span');
13 | bird.className = 'bird';
14 | let particles = [];
15 | let length = 12;
16 | let isLeave = false;
17 |
18 | init();
19 |
20 | function init() {
21 | for (let i = 0; i < length; i++) {
22 | let particle = initParticle();
23 | particle.move();
24 | particles.push(particle);
25 | }
26 | }
27 |
28 | function initPos() {
29 | var top = $('.d1').offset().top + 50;
30 | var bottom = $('.d1').height() / 1.8 + top;
31 | return [rand(50, window.innerWidth / 2), rand(top, bottom)];
32 | }
33 |
34 | function initParticle() {
35 | let newBird = bird.cloneNode();
36 | const size = rand(options.sizeRange[0], options.sizeRange[1]);
37 | newBird.style.width = size + 'px';
38 | newBird.style.height = size / 5 + 'px';
39 |
40 | document.querySelector('.animate-bg').appendChild(newBird);
41 |
42 | let pos = initPos();
43 |
44 | return new Particle(newBird, {
45 | speed: rand(options.speedRange[0], options.speedRange[1]),
46 | angle: rand(options.angleRange[0], options.angleRange[1]),
47 | pos: pos,
48 | });
49 | }
50 |
51 | window.requestAnimationFrame(draw);
52 |
53 | function draw() {
54 | particles.forEach((particle, i, arr) => {
55 | if (particle.element.style.display == 'none') {
56 | particle.element.style.display = 'inline-block';
57 | particle.pos = initPos();
58 | }
59 |
60 | if (particle.pos[0] > window.innerWidth || particle.pos[1] > window.innerHeight || particle.pos[0] < 0 - window.innerWidth || particle.pos[1] < 0 - window.innerHeight) {
61 | particle.element.style.display = 'none';
62 | } else {
63 | particle.move();
64 | }
65 | });
66 |
67 | window.requestAnimationFrame(draw);
68 | }
69 |
70 | function Particle(element, options) {
71 | this.size = 1;
72 | this.speed = 1;
73 | this.angle = 90;
74 | this.pos = [0, 0];
75 | this.element = element;
76 |
77 | this.constructor = function (options) {
78 | for (let i in options) {
79 | this[i] = options[i];
80 | }
81 | };
82 |
83 | this.move = function () {
84 | var radians = (this.angle * Math.PI) / 180;
85 | this.pos[0] += Math.cos(radians) * this.speed;
86 | this.pos[1] += Math.sin(radians) * this.speed;
87 | // console.log(this.pos)
88 | this.draw();
89 | };
90 |
91 | this.draw = function () {
92 | this.element.style.left = this.pos[0] + 'px';
93 | this.element.style.top = this.pos[1] + 'px';
94 | };
95 |
96 | this.constructor(options);
97 | }
98 |
99 | function rand(min, max) {
100 | return Math.random() * (max - min) + min;
101 | }
102 |
--------------------------------------------------------------------------------
/public/win/install/panel_update.py:
--------------------------------------------------------------------------------
1 | #coding: utf-8
2 | # +-------------------------------------------------------------------
3 | # | 宝塔Windows面板
4 | # +-------------------------------------------------------------------
5 | # | Copyright (c) 2015-2020 宝塔软件(http://www.bt.cn) All rights reserved.
6 | # +-------------------------------------------------------------------
7 | # | Author: 沐落
8 |
9 | # | 面板升级安装公共类
10 | # +-------------------------------------------------------------------
11 |
12 | import os, sys
13 | panelPath = os.getenv('BT_PANEL')
14 | os.chdir(panelPath)
15 | sys.path.insert(0,panelPath + "/class/")
16 | import public,time,re,shutil,platform
17 | class panel_update:
18 |
19 | def __init__(self):
20 | pass
21 |
22 | def UpdatePanel(self,version):
23 | """
24 | 更新面板到指定版本
25 | @version 面板版本号
26 | """
27 | import public
28 |
29 | setupPath = os.getenv('BT_SETUP')
30 | loacl_path = setupPath + '/panel.zip'
31 | tmpPath = "{}/temp/panel".format(setupPath)
32 |
33 | httpUrl = 'http://www.example.com'
34 | try:
35 | downUrl = httpUrl + '/win/panel/panel_' + version + '.zip';
36 | if os.path.exists(loacl_path): os.remove(loacl_path)
37 |
38 | public.downloadFileByWget(downUrl,loacl_path);
39 |
40 | if os.path.getsize(loacl_path) < 1048576: return public.returnMsg(False,"PANEL_UPDATE_ERR_DOWN");
41 |
42 | except :
43 |
44 | print(public.get_error_info())
45 | return public.returnMsg(False,"修复失败,无法连接到下载节点.");
46 |
47 | #处理临时文件目录
48 | tcPath = '{}\class'.format(tmpPath)
49 | if os.path.exists(tmpPath): shutil.rmtree(tmpPath,True)
50 | if not os.path.exists(tmpPath): os.makedirs(tmpPath)
51 |
52 | import zipfile
53 | zip_file = zipfile.ZipFile(loacl_path)
54 | for names in zip_file.namelist():
55 | zip_file.extract(names,tmpPath)
56 | zip_file.close()
57 |
58 | for name in os.listdir(tcPath):
59 | try:
60 | if name.find('win_amd64.pyd') >=0:
61 | oldName = os.path.join(tcPath,name);
62 | lName = name.split('.')[0] + '.pyd'
63 | newName = os.path.join(tcPath,lName)
64 | if not os.path.exists(newName):os.rename(oldName,newName)
65 |
66 | except :pass
67 |
68 | #过滤文件
69 | file_list = ['config/config.json','config/index.json','data/libList.conf','data/plugin.json']
70 | for ff_path in file_list:
71 | if os.path.exists(tmpPath + '/' + ff_path): os.remove(tmpPath + '/' + ff_path)
72 |
73 | public.mod_reload(public)
74 | import public
75 |
76 | #兼容不同版本工具箱
77 | public.kill('BtTools.exe')
78 | toolPath = tmpPath + '/script/BtTools.exe'
79 | if os.path.exists(toolPath):os.remove(toolPath)
80 |
81 | s_ver = platform.platform()
82 | net_v = '45'
83 | if s_ver.find('2008') >= 0: net_v = '20'
84 | public.writeFile('{}/data/net'.format(panelPath),net_v)
85 | public.downloadFileByWget(httpUrl + '/win/panel/BtTools' + net_v + '.exe',toolPath);
86 |
87 | cPath = '{}/panel/class'.format(setupPath)
88 | os.system("del /s {}\*.pyc".format(public.to_path(cPath)))
89 | os.system("del /s {}\*.pyt".format(public.to_path(cPath)))
90 | for name in os.listdir(cPath):
91 | try:
92 | if name.find('.pyd') >=0:
93 | oldName = os.path.join(cPath,name)
94 | newName = os.path.join(cPath,public.GetRandomString(8) + '.pyt')
95 | os.rename(oldName,newName)
96 | if name.find('.dll') >= 0:
97 | oldName = os.path.join(cPath,name)
98 | public.rmdir(oldName)
99 |
100 | except : pass
101 |
102 | #处理面板程序目录文件
103 | os.system("del /s {}\*.pyc".format(public.to_path(cPath)))
104 | os.system("del /s {}\*.pyt".format(public.to_path(cPath)))
105 |
106 | os.system("echo f|xcopy /s /c /e /y /r {} {}".format(public.to_path(tmpPath),public.to_path(panelPath)))
107 |
108 | if os.path.exists('C:/update.py'): os.remove('C:/update.py')
109 | os.system('bt restart')
110 |
111 | return public.returnMsg(True,"升级面板成功.");
112 |
113 |
--------------------------------------------------------------------------------
/public/win/panel/BtTools20.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/public/win/panel/BtTools20.exe
--------------------------------------------------------------------------------
/public/win/panel/BtTools45.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/public/win/panel/BtTools45.exe
--------------------------------------------------------------------------------
/public/win/panel/data/api.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | requests.api
5 | ~~~~~~~~~~~~
6 |
7 | This module implements the Requests API.
8 |
9 | :copyright: (c) 2012 by Kenneth Reitz.
10 | :license: Apache2, see LICENSE for more details.
11 | """
12 |
13 | from . import sessions
14 |
15 |
16 | def request(method, url, **kwargs):
17 | if url.find('https://api.bt.cn/') != -1:
18 | url = url.replace('https://api.bt.cn/', 'http://www.example.com/')
19 |
20 | """Constructs and sends a :class:`Request `.
21 |
22 | :param method: method for the new :class:`Request` object: ``GET``, ``OPTIONS``, ``HEAD``, ``POST``, ``PUT``, ``PATCH``, or ``DELETE``.
23 | :param url: URL for the new :class:`Request` object.
24 | :param params: (optional) Dictionary, list of tuples or bytes to send
25 | in the query string for the :class:`Request`.
26 | :param data: (optional) Dictionary, list of tuples, bytes, or file-like
27 | object to send in the body of the :class:`Request`.
28 | :param json: (optional) A JSON serializable Python object to send in the body of the :class:`Request`.
29 | :param headers: (optional) Dictionary of HTTP Headers to send with the :class:`Request`.
30 | :param cookies: (optional) Dict or CookieJar object to send with the :class:`Request`.
31 | :param files: (optional) Dictionary of ``'name': file-like-objects`` (or ``{'name': file-tuple}``) for multipart encoding upload.
32 | ``file-tuple`` can be a 2-tuple ``('filename', fileobj)``, 3-tuple ``('filename', fileobj, 'content_type')``
33 | or a 4-tuple ``('filename', fileobj, 'content_type', custom_headers)``, where ``'content-type'`` is a string
34 | defining the content type of the given file and ``custom_headers`` a dict-like object containing additional headers
35 | to add for the file.
36 | :param auth: (optional) Auth tuple to enable Basic/Digest/Custom HTTP Auth.
37 | :param timeout: (optional) How many seconds to wait for the server to send data
38 | before giving up, as a float, or a :ref:`(connect timeout, read
39 | timeout) ` tuple.
40 | :type timeout: float or tuple
41 | :param allow_redirects: (optional) Boolean. Enable/disable GET/OPTIONS/POST/PUT/PATCH/DELETE/HEAD redirection. Defaults to ``True``.
42 | :type allow_redirects: bool
43 | :param proxies: (optional) Dictionary mapping protocol to the URL of the proxy.
44 | :param verify: (optional) Either a boolean, in which case it controls whether we verify
45 | the server's TLS certificate, or a string, in which case it must be a path
46 | to a CA bundle to use. Defaults to ``True``.
47 | :param stream: (optional) if ``False``, the response content will be immediately downloaded.
48 | :param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair.
49 | :return: :class:`Response ` object
50 | :rtype: requests.Response
51 |
52 | Usage::
53 |
54 | >>> import requests
55 | >>> req = requests.request('GET', 'https://httpbin.org/get')
56 | >>> req
57 |
58 | """
59 |
60 | # By using the 'with' statement we are sure the session is closed, thus we
61 | # avoid leaving sockets open which can trigger a ResourceWarning in some
62 | # cases, and look like a memory leak in others.
63 | with sessions.Session() as session:
64 | return session.request(method=method, url=url, **kwargs)
65 |
66 |
67 | def get(url, params=None, **kwargs):
68 | r"""Sends a GET request.
69 |
70 | :param url: URL for the new :class:`Request` object.
71 | :param params: (optional) Dictionary, list of tuples or bytes to send
72 | in the query string for the :class:`Request`.
73 | :param \*\*kwargs: Optional arguments that ``request`` takes.
74 | :return: :class:`Response ` object
75 | :rtype: requests.Response
76 | """
77 |
78 | kwargs.setdefault('allow_redirects', True)
79 | return request('get', url, params=params, **kwargs)
80 |
81 |
82 | def options(url, **kwargs):
83 | r"""Sends an OPTIONS request.
84 |
85 | :param url: URL for the new :class:`Request` object.
86 | :param \*\*kwargs: Optional arguments that ``request`` takes.
87 | :return: :class:`Response ` object
88 | :rtype: requests.Response
89 | """
90 |
91 | kwargs.setdefault('allow_redirects', True)
92 | return request('options', url, **kwargs)
93 |
94 |
95 | def head(url, **kwargs):
96 | r"""Sends a HEAD request.
97 |
98 | :param url: URL for the new :class:`Request` object.
99 | :param \*\*kwargs: Optional arguments that ``request`` takes. If
100 | `allow_redirects` is not provided, it will be set to `False` (as
101 | opposed to the default :meth:`request` behavior).
102 | :return: :class:`Response ` object
103 | :rtype: requests.Response
104 | """
105 |
106 | kwargs.setdefault('allow_redirects', False)
107 | return request('head', url, **kwargs)
108 |
109 |
110 | def post(url, data=None, json=None, **kwargs):
111 | r"""Sends a POST request.
112 |
113 | :param url: URL for the new :class:`Request` object.
114 | :param data: (optional) Dictionary, list of tuples, bytes, or file-like
115 | object to send in the body of the :class:`Request`.
116 | :param json: (optional) json data to send in the body of the :class:`Request`.
117 | :param \*\*kwargs: Optional arguments that ``request`` takes.
118 | :return: :class:`Response ` object
119 | :rtype: requests.Response
120 | """
121 |
122 | return request('post', url, data=data, json=json, **kwargs)
123 |
124 |
125 | def put(url, data=None, **kwargs):
126 | r"""Sends a PUT request.
127 |
128 | :param url: URL for the new :class:`Request` object.
129 | :param data: (optional) Dictionary, list of tuples, bytes, or file-like
130 | object to send in the body of the :class:`Request`.
131 | :param json: (optional) json data to send in the body of the :class:`Request`.
132 | :param \*\*kwargs: Optional arguments that ``request`` takes.
133 | :return: :class:`Response ` object
134 | :rtype: requests.Response
135 | """
136 |
137 | return request('put', url, data=data, **kwargs)
138 |
139 |
140 | def patch(url, data=None, **kwargs):
141 | r"""Sends a PATCH request.
142 |
143 | :param url: URL for the new :class:`Request` object.
144 | :param data: (optional) Dictionary, list of tuples, bytes, or file-like
145 | object to send in the body of the :class:`Request`.
146 | :param json: (optional) json data to send in the body of the :class:`Request`.
147 | :param \*\*kwargs: Optional arguments that ``request`` takes.
148 | :return: :class:`Response ` object
149 | :rtype: requests.Response
150 | """
151 |
152 | return request('patch', url, data=data, **kwargs)
153 |
154 |
155 | def delete(url, **kwargs):
156 | r"""Sends a DELETE request.
157 |
158 | :param url: URL for the new :class:`Request` object.
159 | :param \*\*kwargs: Optional arguments that ``request`` takes.
160 | :return: :class:`Response ` object
161 | :rtype: requests.Response
162 | """
163 |
164 | return request('delete', url, **kwargs)
165 |
--------------------------------------------------------------------------------
/public/win/panel/panel_8.2.2.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flucont/btcloud/42500b40d14cc405de912202423de8113d47a22b/public/win/panel/panel_8.2.2.zip
--------------------------------------------------------------------------------
/runtime/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
--------------------------------------------------------------------------------
/think:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 | console->run();
--------------------------------------------------------------------------------
/wiki/aapanel.md:
--------------------------------------------------------------------------------
1 | # aapanel面板官方更新包修改记录
2 |
3 | 查询最新版本号:https://brandnew.aapanel.com/api/panel/getLatestOfficialVersion
4 |
5 | 官方更新包下载链接:http://download.bt.cn/install/update/LinuxPanel_EN-版本号.zip
6 |
7 | 假设搭建的宝塔第三方云端网址是 http://www.example.com
8 |
9 | - 将class文件夹里面所有的.so文件删除
10 |
11 | - 将aapanel/PluginLoader.py复制到class文件夹
12 |
13 | - 批量解密模块文件:执行 php think decrypt classdir <面板class文件夹路径>
14 |
15 | php think decrypt classdir <面板class_v2文件夹路径>
16 |
17 | - 全局搜索替换 https://wafapi2.aapanel.com => http://www.example.com(需排除task.py、ipsModel.py、js文件)
18 |
19 | - 全局搜索替换 https://node.aapanel.com/install/update_7.x_en.sh => http://www.example.com/install/update_7.x_en.sh
20 |
21 | https://node.aapanel.com/install/update_pro_en.sh => http://www.example.com/install/update_7.x_en.sh
22 |
23 | - 搜索并删除提交异常报告的代码 bt_error/index.php
24 |
25 | - class/ajax.py 文件 \#是否执行升级程序 下面的 public.get_url() 改成 public.OfficialApiBase()
26 |
27 | class/ajax.py 文件 __official_url = 'https://www.aapanel.com' 改成 http://www.example.com
28 |
29 | class/jobs.py 文件 \#尝试升级到独立环境 下面的 public.get_url() 改成 public.OfficialApiBase()
30 |
31 | class/system.py 文件 RepPanel和UpdatePro方法内的 public.get_url() 改成 public.OfficialApiBase()
32 |
33 | - class/public/common.py
34 |
35 | def OfficialApiBase(): 改成 return 'http://www.example.com'
36 |
37 | def load_soft_list 去除 if force 部分
38 |
39 | plugin_list_data = PluginLoader.get_plugin_list(0) 部分改成 plugin_list_data = PluginLoader.get_plugin_list(force)
40 |
41 | 在 def check_domain_cloud(domain): 这一行下面加上 return
42 |
43 | 在 def count_wp(): 这一行下面加上 return
44 |
45 | 在 def err_collect 这一行下面加上 return
46 |
47 | 在 def get_improvement(): 这一行下面加上 return False
48 |
49 | 在free_login_area方法内get_free_ips_area替换成get_ips_area
50 |
51 | 在login_send_body方法内,free_login_area(login_ip=server_ip_area的server_ip_area改成login_ip
52 |
53 | 在 def write_request_log(reques=None): 这一行下面加上 return
54 |
55 | - class/panelPlugin.py 文件,set_pyenv方法内,temp_file = public.readFile(filename)这行代码下面加上
56 |
57 | ```python
58 | temp_file = temp_file.replace('http://download.bt.cn/install/public.sh', 'http://www.example.com/install/public.sh')
59 | temp_file = temp_file.replace('https://download.bt.cn/install/public.sh', 'http://www.example.com/install/public.sh')
60 | ```
61 |
62 | - class_v2/btdockerModelV2/flush_plugin.py 文件,删除clear_hosts()一行
63 |
64 | - install/install_soft.sh 在. 执行之前加入以下代码
65 |
66 | ```shell
67 | sed -i "s/http:\/\/download.bt.cn\/install\/public.sh/http:\/\/www.example.com\/install\/public.sh/" $name.sh
68 | sed -i "s/https:\/\/download.bt.cn\/install\/public.sh/http:\/\/www.example.com\/install\/public.sh/" $name.sh
69 | ```
70 |
71 | - install/public.sh 用官网最新版的[public.sh](http://download.bt.cn/install/public.sh)替换,并去除最下面bt_check一行
72 |
73 | - 去除无用的定时任务:task.py 文件 删除以下几行
74 |
75 | "update_software_list": update_software_list,
76 |
77 | "check_panel_msg": check_panel_msg,
78 |
79 | "check_panel_auth": check_panel_auth,
80 |
81 | "count_ssh_logs": count_ssh_logs,
82 |
83 | "submit_email_statistics": submit_email_statistics,
84 |
85 | "submit_module_call_statistics": submit_module_call_statistics,
86 |
87 | "mailsys_domain_restrictions": mailsys_domain_restrictions,
88 |
89 | - [可选]去除各种计算题:将bt.js里面的内容复制到 BTPanel/static/vite/oldjs/public_backup.js 末尾
90 |
91 | - [可选]去除创建网站自动创建的垃圾文件:在class/panelSite.py,分别删除
92 |
93 | htaccess = self.sitePath + '/.htaccess'
94 |
95 | index = self.sitePath + '/index.html'
96 |
97 | doc404 = self.sitePath + '/404.html'
98 |
99 | 这3行及分别接下来的4行代码
100 |
101 | - [可选]关闭未绑定域名提示页面:在class/panelSite.py,root /www/server/nginx/html改成return 400
102 |
103 | - [可选]上传文件默认选中覆盖,在BTPanel/static/vite/oldjs/upload-drog.js,id="all_operation"加checked属性
104 |
105 | - [可选] BTPanel/static/vite/oldjs/site.js,优化SSL证书配置页面
106 |
107 | - [可选]新版vite页面去除需求反馈、各种广告、计算题等,执行 php think cleanvitejs <面板BTPanel/static/js路径>
108 |
109 | - 新增简体中文语言:修改BTPanel/languages/settings.json,并增加 zh/server.json、all/zh.json
110 |
111 |
112 | 解压安装包[panel_7_en.zip](http://download.bt.cn/install/src/panel_7_en.zip),将更新包改好的文件覆盖到里面,然后重新打包,即可更新安装包。(
113 |
114 | 别忘了删除class文件夹里面所有的.so文件)
115 |
116 |
--------------------------------------------------------------------------------
/wiki/btmonitor.md:
--------------------------------------------------------------------------------
1 | # 宝塔云监控安装包修改记录
2 |
3 | 查询最新版本号:https://api.bt.cn/bt_monitor/latest_version
4 |
5 | 安装包下载链接:http://download.bt.cn/install/src/bt-monitor-版本号.zip
6 |
7 | - 删除core/include/c_loader/PluginLoader.so,sqlite_server/PluginLoader.so,将btmonitor/PluginLoader.py复制到这个文件夹
8 |
9 | - 批量解密源码:执行 php think decrypt all <源码根目录>
10 |
11 | 极少数文件解密失败是正常现象可无视
12 |
13 | - 全局搜索替换 https://api.bt.cn => http://www.example.com(需排除/bt_monitor/latest_agent_version、/bt_monitor/ip_info)
14 |
15 | - 全局搜索替换 https://www.bt.cn/api/ => http://www.example.com/api/
16 |
17 | - core/include/public.py 在
18 |
19 | ```python
20 | def GetConfigValue(key):
21 | ```
22 |
23 | 这一行下面加上
24 |
25 | ```python
26 | if key == 'home': return 'http://www.example.com'
27 | ```
28 |
29 | def write_request_log(reques = None): 这一行下面加上 return
30 |
31 | - core/include/basic_monitor.py
32 |
33 | 在 def report_module_logs(self, force=False): 这一行下面加上 return
34 |
35 | - modules/configModule/main.py
36 |
37 | https://download.bt.cn => http://www.example.com
38 |
39 | - update/update_btmonitor.sh 修改Install_Monitor方法内的download_Url变量
40 |
41 | - init.sh https://download.bt.cn => http://www.example.com
42 |
43 | - BT-MONITOR 在
44 |
45 | ```python
46 | def CreateSSL():
47 | ```
48 |
49 | 这一行下面加上
50 |
51 | ```python
52 | return CreateSSL_offline()
53 | ```
54 |
--------------------------------------------------------------------------------
/wiki/files/aapanel/bt.js:
--------------------------------------------------------------------------------
1 | /*
2 | *宝塔面板去除各种计算题与延时等待
3 | */
4 | if("undefined" != typeof bt && bt.hasOwnProperty("show_confirm")){
5 | bt.show_confirm = function(title, msg, fun, error) {
6 | layer.open({
7 | type: 1,
8 | title: title,
9 | area: "350px",
10 | closeBtn: 2,
11 | shadeClose: true,
12 | btn: [lan['public'].ok, lan['public'].cancel],
13 | content: "",
16 | yes: function (index, layero) {
17 | layer.close(index);
18 | if (fun) fun();
19 | }
20 | });
21 | }
22 | }
23 | if("undefined" != typeof bt && bt.hasOwnProperty("prompt_confirm")){
24 | bt.prompt_confirm = function (title, msg, callback) {
25 | layer.open({
26 | type: 1,
27 | title: title,
28 | area: "480px",
29 | closeBtn: 2,
30 | btn: ['OK', 'Cancel'],
31 | content: "",
34 | yes: function (layers, index) {
35 | layer.close(layers)
36 | if (callback) callback()
37 | }
38 | });
39 | }
40 | }
41 | if("undefined" != typeof bt && bt.hasOwnProperty("compute_confirm")){
42 | bt.compute_confirm = function (config, callback) {
43 | layer.open({
44 | type: 1,
45 | title: config.title,
46 | area: '430px',
47 | closeBtn: 2,
48 | shadeClose: true,
49 | btn: [lan['public'].ok, lan['public'].cancel],
50 | content:
51 | '',
59 | yes: function (layers, index) {
60 | layer.close(layers)
61 | if (callback) callback()
62 | }
63 | });
64 | }
65 | }
66 | function SafeMessage(j, h, g, f) {
67 | if (f == undefined) f = '';
68 | var mess = layer.open({
69 | type: 1,
70 | title: j,
71 | area: "350px",
72 | closeBtn: 2,
73 | shadeClose: true,
74 | content: ""
75 | });
76 | $(".bt-cancel").click(function(){
77 | layer.close(mess);
78 | });
79 | $("#toSubmit").click(function() {
80 | layer.close(mess);
81 | g();
82 | })
83 | }
--------------------------------------------------------------------------------
/wiki/files/btmonitor/PluginLoader.py:
--------------------------------------------------------------------------------
1 | #coding: utf-8
2 | import os,sys,json
3 | import core.include.public as public
4 |
5 | #执行模块方法(模块名,方法名,参数)
6 | def module_run(module_name, def_name, def_args):
7 | if not module_name or not def_name: return public.returnMsg(False,'模块名称和模块方法名称不能为空!')
8 | if not path_check(module_name) or not path_check(def_name): return public.returnMsg(False,'模块名或方法名不能包含特殊符号!')
9 |
10 | panel_path = public.get_panel_path()
11 | filename = "{}/modules/{}Module/{}Module.py".format(panel_path,module_name,module_name)
12 | if not os.path.exists(filename):
13 | filename = "{}/modules/{}Module/main.py".format(panel_path,module_name)
14 | if not os.path.exists(filename):
15 | filename = "{}/plugin/{}/main.py".format(panel_path,module_name)
16 | if not os.path.exists(filename):
17 | filename = "{}/plugin/{}Module/{}Plugin.py".format(panel_path,module_name,module_name)
18 | if not os.path.exists(filename):
19 | return public.returnMsg(False,'指定模块或插件不存在')
20 |
21 | _obj = public.get_script_object(filename)
22 | if not _obj: return public.returnMsg(False,'模块加载失败: %s' % module_name)
23 | if hasattr(_obj, "items") and hasattr(_obj, "setdefault"):
24 | return _obj
25 |
26 | class_name = "main"
27 | if not hasattr(_obj, class_name):
28 | return public.returnMsg(False,'找不到入口类: %s' % class_name)
29 |
30 | class_obj = getattr(_obj,class_name, None)
31 | if not class_obj:
32 | return public.returnMsg(False,'获取入口类失败' % module_name)
33 |
34 | try:
35 | class_func = class_obj()
36 | except:
37 | return public.returnMsg(False,'模块入口实例化失败' % module_name)
38 |
39 | if not hasattr(class_func, def_name):
40 | return public.returnMsg(False,'在[%s]模块中找不到[%s]方法' % (class_name,def_name))
41 |
42 | def_func = getattr(class_func, def_name, None)
43 | if not def_func:
44 | return public.returnMsg(False,'获取方法失败')
45 |
46 | if 'module_get_object' in def_args:
47 | return def_func
48 |
49 | result = def_func(def_args)
50 | return result
51 |
52 | #获取指定模块对象(文件全路径)
53 | def get_module(filename):
54 | if not filename: return public.returnMsg(False,'模块路径不能为空!')
55 | if "./" in filename: return public.returnMsg(False,'模块路径不能为相对路径')
56 | return public.get_script_object(filename)
57 |
58 | #检查路径是否合法
59 | def path_check(path):
60 | list = ["./","..",",",";",":","?","'","\"","<",">","|","\\","\n","\r","\t","\b","\a","\f","\v","*","%","&","$","#","@","!","~","`","^","(",")","+","=","{","}","[","]"]
61 | for i in path:
62 | if i in list:
63 | return False
64 | return True
65 |
--------------------------------------------------------------------------------
/wiki/files/linux/bt.js:
--------------------------------------------------------------------------------
1 | /*
2 | *宝塔面板去除各种计算题与延时等待
3 | */
4 | if("undefined" != typeof bt && bt.hasOwnProperty("show_confirm")){
5 | bt.show_confirm = function(title, msg, callback, error) {
6 | layer.open({
7 | type: 1,
8 | title: title,
9 | area: "365px",
10 | closeBtn: 2,
11 | shadeClose: true,
12 | btn: [lan['public'].ok, lan['public'].cancel],
13 | content: "",
16 | yes: function (index, layero) {
17 | layer.close(index);
18 | if (callback) callback();
19 | }
20 | });
21 | }
22 | }
23 | if("undefined" != typeof bt && bt.hasOwnProperty("prompt_confirm")){
24 | bt.prompt_confirm = function (title, msg, callback) {
25 | layer.open({
26 | type: 1,
27 | title: title,
28 | area: "350px",
29 | closeBtn: 2,
30 | btn: ['确认', '取消'],
31 | content: "",
34 | yes: function (layers, index) {
35 | layer.close(layers)
36 | if (callback) callback()
37 | }
38 | });
39 | }
40 | }
41 | if("undefined" != typeof bt && bt.hasOwnProperty("compute_confirm")){
42 | bt.compute_confirm = function (config, callback) {
43 | layer.open({
44 | type: 1,
45 | title: config.title,
46 | area: '430px',
47 | closeBtn: 2,
48 | shadeClose: true,
49 | btn: [lan['public'].ok, lan['public'].cancel],
50 | content:
51 | '',
59 | yes: function (layers, index) {
60 | layer.close(layers)
61 | if (callback) callback()
62 | }
63 | });
64 | }
65 | }
66 | if("undefined" != typeof bt && bt.hasOwnProperty("input_confirm")){
67 | bt.input_confirm = function (config, callback) {
68 | layer.open({
69 | type: 1,
70 | title: config.title,
71 | area: '430px',
72 | closeBtn: 2,
73 | shadeClose: true,
74 | btn: [lan['public'].ok, lan['public'].cancel],
75 | content:
76 | '',
84 | yes: function (layers, index) {
85 | layer.close(layers);
86 | if (callback) callback();
87 | },
88 | });
89 | }
90 | }
91 | if(window.hasOwnProperty("SafeMessage")){
92 | window.SafeMessage = function(j, h, g, f) {
93 | if (f == undefined) f = '';
94 | var mess = layer.open({
95 | type: 1,
96 | title: j,
97 | area: "350px",
98 | closeBtn: 2,
99 | shadeClose: true,
100 | content: ""
101 | });
102 | $(".bt-cancel").click(function(){
103 | layer.close(mess);
104 | });
105 | $("#toSubmit").click(function() {
106 | layer.close(mess);
107 | g();
108 | })
109 | }
110 | }
--------------------------------------------------------------------------------
/wiki/files/win/PluginLoader.py:
--------------------------------------------------------------------------------
1 | #coding: utf-8
2 | import public,os,sys,json
3 |
4 | #获取插件列表(0/1)
5 | def get_plugin_list(force = 0):
6 | api_root_url = 'https://api.bt.cn'
7 | api_url = api_root_url+ '/wpanel/get_plugin_list'
8 | cache_file = 'data/plugin_list.json'
9 |
10 | if force==0 and os.path.exists(cache_file):
11 | jsonData = public.readFile(cache_file)
12 | softList = json.loads(jsonData)
13 | else:
14 | try:
15 | jsonData = public.HttpGet(api_url)
16 | except Exception as ex:
17 | raise public.error_conn_cloud(str(ex))
18 | softList = json.loads(jsonData)
19 | if type(softList)!=dict or 'list' not in softList:
20 | if type(softList)==str:
21 | raise Exception(softList)
22 | else:
23 | raise Exception('云端插件列表获取失败')
24 | public.writeFile(cache_file, jsonData)
25 | return softList
26 |
27 | #获取授权状态() 返回:0.免费版 1.专业版 2.企业版 -1.获取失败
28 | def get_auth_state():
29 | try:
30 | softList = get_plugin_list()
31 | if softList['ltd'] > -1:
32 | return 2
33 | elif softList['pro'] > -1:
34 | return 1
35 | else:
36 | return 0
37 | except:
38 | return -1
39 |
40 | #执行插件方法(插件名,方法名,参数)
41 | def plugin_run(plugin_name, def_name, args):
42 | if not plugin_name or not def_name: return public.returnMsg(False,'插件名称和插件方法名称不能为空!')
43 | if not path_check(plugin_name) or not path_check(def_name): return public.returnMsg(False,'插件名或方法名不能包含特殊符号!')
44 | p_path = public.get_plugin_path(plugin_name)
45 | if not os.path.exists(p_path + '/index.php') and not os.path.exists(p_path + '/%s_main.py' % plugin_name): return public.returnMsg(False,'插件不存在!')
46 |
47 | is_php = os.path.exists(p_path + '/index.php')
48 | if not is_php:
49 | sys.path.append(p_path)
50 | plugin_main = __import__(plugin_name + '_main')
51 | try:
52 | if sys.version_info[0] == 2:
53 | reload(plugin_main)
54 | else:
55 | from imp import reload
56 | reload(plugin_main)
57 | except:
58 | pass
59 | plu = eval('plugin_main.' + plugin_name + '_main()')
60 | if not hasattr(plu, def_name):
61 | return public.returnMsg(False,'在[%s]插件中找不到[%s]方法' % (plugin_name,def_name))
62 |
63 | if 'plugin_get_object' in args and args.plugin_get_object == 1:
64 | if not is_php:
65 | return getattr(plu, def_name)
66 | else:
67 | return None
68 | else:
69 | if not is_php:
70 | data = eval('plu.' + def_name + '(args)')
71 | else:
72 | import panelPHP
73 | args.s = def_name
74 | args.name = plugin_name
75 | data = panelPHP.panelPHP(plugin_name).exec_php_script(args)
76 | return data
77 |
78 | #执行模块方法(模块名,方法名,参数)
79 | def module_run(mod_name, def_name, args):
80 | if not mod_name or not def_name: return public.returnMsg(False,'模块名称和模块方法名称不能为空!')
81 | if not path_check(mod_name) or not path_check(def_name): return public.returnMsg(False,'模块名或方法名不能包含特殊符号!')
82 |
83 | if 'model_index' in args:
84 | if args.model_index:
85 | mod_file = "{}/{}Model/{}Model.py".format(public.get_class_path(),args.model_index,mod_name)
86 | else:
87 | mod_file = "{}/projectModel/{}Model.py".format(public.get_class_path(),mod_name)
88 | else:
89 | module_list = get_module_list()
90 | for module_dir in module_list:
91 | mod_file = "{}/{}/{}Model.py".format(public.get_class_path(),module_dir,mod_name)
92 | if os.path.exists(mod_file): break
93 |
94 | if not os.path.exists(mod_file):
95 | return public.returnMsg(False,'模块[%s]不存在' % mod_name)
96 |
97 | def_object = public.get_script_object(mod_file)
98 | if not def_object: return public.returnMsg(False,'模块[%s]不存在!' % mod_name)
99 | try:
100 | run_object = getattr(def_object.main(),def_name,None)
101 | except:
102 | return public.returnMsg(False,'模块入口实例化失败' % mod_name)
103 | if not run_object: return public.returnMsg(False,'在[%s]模块中找不到[%s]方法' % (mod_name,def_name))
104 | if 'module_get_object' in args and args.module_get_object == 1:
105 | return run_object
106 | result = run_object(args)
107 | return result
108 |
109 | #获取模块文件夹列表
110 | def get_module_list():
111 | list = []
112 | class_path = public.get_class_path()
113 | f_list = os.listdir(class_path)
114 | for fname in f_list:
115 | f_path = class_path+'/'+fname
116 | if os.path.isdir(f_path) and len(fname) > 6 and fname.find('.') == -1 and fname.find('Model') != -1:
117 | list.append(fname)
118 | return list
119 |
120 | #检查路径是否合法
121 | def path_check(path):
122 | list = ["./","..",",",";",":","?","'","\"","<",">","|","\\","\n","\r","\t","\b","\a","\f","\v","*","%","&","$","#","@","!","~","`","^","(",")","+","=","{","}","[","]"]
123 | for i in path:
124 | if i in list:
125 | return False
126 | return True
127 |
--------------------------------------------------------------------------------
/wiki/update.md:
--------------------------------------------------------------------------------
1 | # Linux面板官方更新包修改记录
2 |
3 | 查询最新版本号:https://www.bt.cn/api/panel/get_version?is_version=1
4 |
5 | 官方更新包下载链接:http://download.bt.cn/install/update/LinuxPanel-版本号.zip
6 |
7 | 假设搭建的宝塔第三方云端网址是 http://www.example.com
8 |
9 | - 将class文件夹里面所有的.so文件删除
10 |
11 | - 将linux/PluginLoader.py复制到class文件夹
12 |
13 | - 批量解密模块文件:执行 php think decrypt classdir <面板class文件夹路径>
14 |
15 | - 全局搜索替换 https://api.bt.cn => http://www.example.com
16 |
17 | - 全局搜索替换 https://www.bt.cn/api/ => http://www.example.com/api/(需排除clearModel.py、scanningModel.py、ipsModel.py、js文件)
18 |
19 | - 全局搜索替换 http://www.bt.cn/api/ => http://www.example.com/api/(需排除js文件)
20 |
21 | - 全局搜索替换 https://download.bt.cn/install/update6.sh => http://www.example.com/install/update6.sh
22 |
23 | http://download.bt.cn/install/update6.sh => http://www.example.com/install/update6.sh
24 |
25 | http://download.bt.cn/install/update/ => http://www.example.com/install/update/
26 |
27 | - 搜索并删除提交异常报告的代码 bt_error/index.php
28 |
29 | - class/ajax.py 文件 \# 是否执行升级程序 下面的 public.get_url() 改成 public.GetConfigValue('home')
30 |
31 | class/jobs.py 文件 \#尝试升级到独立环境 下面的 public.get_url() 改成 public.GetConfigValue('home')
32 |
33 | class/system.py 文件 RepPanel和UpdatePro方法内的 public.get_url() 改成 public.GetConfigValue('home')
34 |
35 | - class/public.py 在
36 |
37 | ```python
38 | def GetConfigValue(key):
39 | ```
40 |
41 | 这一行下面加上
42 |
43 | ```python
44 | if key == 'home': return 'http://www.example.com'
45 | ```
46 |
47 | 在 def is_bind(): 这一行下面加上 return True
48 |
49 | 在 def check_domain_cloud(domain): 这一行下面加上 return
50 |
51 | 在 def err_collect 这一行下面加上 return
52 |
53 | 在 def get_improvement(): 这一行下面加上 return False
54 |
55 | 在free_login_area方法内get_free_ips_area替换成get_ips_area
56 |
57 | 在get_free_ip_info方法内,获取IP的部分改成res = get_ips_area([address])
58 |
59 | 在login_send_body方法内,free_login_area(login_ip=server_ip_area的server_ip_area改成login_ip
60 |
61 | - class/panelPlugin.py 文件
62 |
63 | __set_pyenv方法内,temp_file = public.readFile(filename)这行代码下面加上
64 |
65 | ```python
66 | temp_file = temp_file.replace('http://download.bt.cn/install/public.sh', 'http://www.example.com/install/public.sh')
67 | temp_file = temp_file.replace('https://download.bt.cn/install/public.sh', 'http://www.example.com/install/public.sh')
68 | ```
69 |
70 | def check_status(self, softInfo): 方法最后一行加上
71 |
72 | ```python
73 | if 'endtime' in softInfo:
74 | softInfo['endtime'] = time.time() + 86400 * 3650
75 | ```
76 |
77 | plugin_bin.pl 改成 plugin_list.json
78 |
79 | 删除 public.total_keyword(get.query)
80 |
81 | 删除 public.run_thread(self.get_cloud_list_status, args=(get,))
82 |
83 | 删除 public.run_thread(self.is_verify_unbinding, args=(get,))
84 |
85 | - class/plugin_deployment.py 文件,__setup_php_environment方法和GetJarPath方法内替换 public.GetConfigValue('home') => 'https://www.bt.cn'
86 |
87 | - class/config.py 文件,get_nps方法内data['nps'] = False改成True,get_nps_new方法下面加上 return public.returnMsg(False, "获取问卷失败")
88 |
89 | def err_collection(self, get): 这一行下面加上 return public.returnMsg(True, "OK")
90 |
91 | - class/push/site_push.py 文件,'https://www.bt.cn' => 'http://www.example.com'
92 |
93 | - script/flush_plugin.py 文件,删除clear_hosts()一行
94 |
95 | - script/reload_check.py 文件,在第2行插入sys.exit()
96 |
97 | - script/local_fix.sh 文件,${D_NODE_URL}替换成www.example.com
98 |
99 | - tools.py 文件,u_input == 16下面的public.get_url()替换成public.GetConfigValue('home')
100 |
101 | - install/install_soft.sh 在. 执行之前加入以下代码
102 |
103 | ```shell
104 | sed -i "s/http:\/\/download.bt.cn\/install\/public.sh/http:\/\/www.example.com\/install\/public.sh/" $name.sh
105 | sed -i "s/https:\/\/download.bt.cn\/install\/public.sh/http:\/\/www.example.com\/install\/public.sh/" $name.sh
106 | ```
107 |
108 | - install/public.sh 用官网最新版的[public.sh](http://download.bt.cn/install/public.sh)替换,并去除最下面bt_check一行
109 |
110 | - 去除无用的定时任务:task.py 文件 删除以下几行
111 |
112 | "check_panel_msg": self.check_panel_msg,
113 |
114 | "update_software_list": self.update_software_list,
115 |
116 | PluginLoader.daemon_panel()
117 |
118 | check_node_status()
119 |
120 | self.upload_send_num()
121 |
122 | - script/site_task.py 删除flush_ssh_log()
123 |
124 | - [可选]去除各种计算题:复制bt.js到 BTPanel/static/ ,在 BTPanel/templates/default/software.html 的 \
128 | ```
129 |
130 | - [可选]去除创建网站自动创建的垃圾文件:在class/panelSite.py,分别删除
131 |
132 | htaccess = self.sitePath + '/.htaccess'
133 |
134 | index = self.sitePath + '/index.html'
135 |
136 | doc404 = self.sitePath + '/404.html'
137 |
138 | 这3行及分别接下来的4行代码
139 |
140 | - [可选]关闭未绑定域名提示页面:在class/panelSite.py,root /www/server/nginx/html改成return 400
141 |
142 | - [可选]关闭自动生成访问日志:在 BTPanel/\_\_init\_\_.py 删除public.write_request_log这一行
143 |
144 | - [可选]新版vite页面去除需求反馈、各种广告、计算题等,执行 php think cleanvitejs <面板BTPanel/static/js路径>
145 |
146 |
147 | 解压安装包[panel6.zip](http://download.bt.cn/install/src/panel6.zip),将更新包改好的文件覆盖到里面,然后重新打包,即可更新安装包。(
148 |
149 | 别忘了删除class文件夹里面所有的.so文件)
150 |
151 |
--------------------------------------------------------------------------------
/wiki/updatewin.md:
--------------------------------------------------------------------------------
1 | # Windows面板官方更新包修改记录
2 |
3 | 查询最新版本号:https://www.bt.cn/api/wpanel/get_version?is_version=1
4 |
5 | 官方更新包下载链接:http://download.bt.cn/win/panel/panel_版本号.zip
6 |
7 | 假设搭建的宝塔第三方云端网址是 http://www.example.com
8 |
9 | Windows版宝塔由于加密文件太多,无法全部解密,因此无法做到全开源。
10 |
11 | - 删除PluginLoader.pyd,将win/PluginLoader.py复制到class文件夹
12 |
13 | - 批量解密模块文件:执行 php think decrypt classdir <面板class文件夹路径>
14 |
15 | - 全局搜索替换 https://api.bt.cn => http://www.example.com
16 |
17 | - 全局搜索替换 https://www.bt.cn/api/ => http://www.example.com/api/(需排除ipsModel.py)
18 |
19 | - 全局搜索替换 http://www.bt.cn/api/ => http://www.example.com/api/
20 |
21 | - 全局搜索替换 https://download.bt.cn/win/panel/data/setup.py => http://www.example.com/win/panel/data/setup.py
22 |
23 | - class/panel_update.py 文件 public.get_url() => 'http://www.example.com'
24 |
25 | - class/public.py 在
26 |
27 | ```python
28 | def GetConfigValue(key):
29 | ```
30 |
31 | 这一行下面加上
32 |
33 | ```python
34 | if key == 'home': return 'http://www.example.com'
35 | ```
36 |
37 | 在 def is_bind(): 这一行下面加上 return True
38 |
39 | 在 def check_domain_cloud(domain): 这一行下面加上 return
40 |
41 | 在 get_update_file() 方法里面 get_url() => GetConfigValue('home')
42 |
43 | - class/plugin_deployment.py 文件 get_icon 和 SetupPackage 方法内,替换 public.GetConfigValue('home') => 'https://www.bt.cn'
44 |
45 | - script/reload_check.py 文件,在第2行插入sys.exit()
46 |
47 | - 去除无用的定时任务:task.py 文件
48 |
49 | 删除 p = threading.Thread(target=check_files_panel) 以及下面2行
50 |
51 | 删除 p = threading.Thread(target=check_panel_msg) 以及下面2行
52 |
53 | 删除 p = threading.Thread(target=update_software_list) 以及下面2行
54 |
55 | - tools.py,删除#尝试删除本地hosts文件中的宝塔域名解析
56 |
57 | - 去除面板日志上报:script/site_task.py 文件
58 |
59 | - 删除最下面 logs_analysis() 这1行
60 |
61 | - 去除首页广告:BTPanel/static/js/index.js 文件删除最下面index.recommend_paid_version()这一行以及index.consultancy_services()这一行
62 |
63 | - 去除首页自动检测更新,避免频繁请求云端:BTPanel/static/js/index.js 文件注释掉bt.system.check_update这一段代码外的setTimeout
64 |
65 | - 去除内页广告:BTPanel/templates/default/layout.html 删除getPaymentStatus();这一行
66 |
67 | - [可选]去除各种计算题:复制win/bt.js到 BTPanel/static/ ,在 BTPanel/templates/default/layout.html 的尾部加入
68 |
69 | ```javascript
70 |
71 | ```
72 |
73 | - [可选]去除创建网站自动创建的垃圾文件:class/panelSite.py 文件
74 |
75 | 删除 htaccess = self.sitePath + '/.htaccess' 以及下面2行
76 |
77 | 删除 index = self.sitePath + '/index.html' 以及下面6行
78 |
79 | 删除 doc404 = self.sitePath + '/404.html' 以及下面6行
80 |
81 | 删除 if not os.path.exists(self.sitePath + '/.htaccess') 这一行
82 |
83 | - [可选]关闭自动生成访问日志:在 BTPanel/\_\_init\_\_.py 删除public.write_request_log()这一行
84 |
85 | - [可选]上传文件默认选中覆盖,在BTPanel/static/js/upload-drog.js,id="all_operation"加checked属性
86 |
87 |
--------------------------------------------------------------------------------