diff --git a/app/command/UpdateAll.php b/app/command/UpdateAll.php index f6df2f1..c87459a 100644 --- a/app/command/UpdateAll.php +++ b/app/command/UpdateAll.php @@ -25,10 +25,10 @@ class UpdateAll extends Command $res = Db::name('config')->cache('configs',0)->column('value','key'); Config::set($res, 'sys'); - if(config_get('bt_url')){ + if(!config_get('bt_type') && config_get('bt_url') || config_get('bt_type')==1 && config_get('bt_surl')){ $this->process_plugins($input, $output, 'Linux'); } - if(config_get('wbt_url')){ + if(!config_get('wbt_type') && config_get('wbt_url') || config_get('wbt_type')==1 && config_get('wbt_surl')){ $this->process_plugins($input, $output, 'Windows'); } @@ -103,16 +103,4 @@ class UpdateAll extends Command return false; } } - - private function download_plugin_image(Input $input, Output $output, $fname){ - try{ - Plugins::download_plugin_other($fname); - $output->writeln('下载图片: '.$fname.' 成功'); - return true; - }catch(\Exception $e){ - $output->writeln($fname.' '.$e->getMessage()); - errorlog($fname.' '.$e->getMessage()); - return false; - } - } } diff --git a/app/controller/Admin.php b/app/controller/Admin.php index 1474da9..de74655 100644 --- a/app/controller/Admin.php +++ b/app/controller/Admin.php @@ -1,388 +1,403 @@ -islogin){ - return redirect('/admin'); - } - if(request()->isAjax()){ - $username = input('post.username',null,'trim'); - $password = input('post.password',null,'trim'); - $code = input('post.code',null,'trim'); - - if(empty($username) || empty($password)){ - return json(['code'=>-1, 'msg'=>'用户名或密码不能为空']); - } - if(!captcha_check($code)){ - return json(['code'=>-1, 'msg'=>'验证码错误']); - } - if($username == config_get('admin_username') && $password == config_get('admin_password')){ - Db::name('log')->insert(['uid' => 0, 'action' => '登录后台', 'data' => 'IP:'.$this->clientip, 'addtime' => date("Y-m-d H:i:s")]); - $session = md5($username.config_get('admin_password')); - $expiretime = time()+2562000; - $token = authcode("{$username}\t{$session}\t{$expiretime}", 'ENCODE', config_get('syskey')); - cookie('admin_token', $token, ['expire' => $expiretime, 'httponly' => true]); - config_set('admin_lastlogin', date('Y-m-d H:i:s')); - return json(['code'=>0]); - }else{ - return json(['code'=>-1, 'msg'=>'用户名或密码错误']); - } - } - return view(); - } - - public function logout() - { - cookie('admin_token', null); - return redirect('/admin/login'); - } - - public function index() - { - $stat = ['total'=>0, 'free'=>0, 'pro'=>0, 'ltd'=>0, 'third'=>0]; - $json_arr = Plugins::get_plugin_list(); - if($json_arr){ - foreach($json_arr['list'] as $plugin){ - $stat['total']++; - if($plugin['type']==10) $stat['third']++; - elseif($plugin['type']==12) $stat['ltd']++; - elseif($plugin['type']==8) $stat['pro']++; - elseif($plugin['type']==5 || $plugin['type']==6 || $plugin['type']==7) $stat['free']++; - } - } - $stat['runtime'] = Db::name('config')->where('key','runtime')->value('value') ?? '未运行'; - $stat['record_total'] = Db::name('record')->count(); - $stat['record_isuse'] = Db::name('record')->whereTime('usetime', '>=', strtotime('-7 days'))->count(); - View::assign('stat', $stat); - - $tmp = 'version()'; - $mysqlVersion = Db::query("select version()")[0][$tmp]; - $info = [ - 'framework_version' => app()::VERSION, - 'php_version' => PHP_VERSION, - 'mysql_version' => $mysqlVersion, - 'software' => $_SERVER['SERVER_SOFTWARE'], - 'os' => php_uname(), - 'date' => date("Y-m-d H:i:s"), - ]; - View::assign('info', $info); - return view(); - } - - public function set(){ - if(request()->isAjax()){ - $params = Request::param(); - - foreach ($params as $key => $value) { - config_set($key, $value); - } - cache('configs', NULL); - return json(['code'=>0]); - } - $mod = input('param.mod', 'sys'); - View::assign('mod', $mod); - View::assign('conf', config('sys')); - $runtime = Db::name('config')->where('key','runtime')->value('value') ?? '未运行'; - View::assign('runtime', $runtime); - return view(); - } - - public function setaccount(){ - $params = Request::param(); - if(isset($params['username']))$params['username']=trim($params['username']); - if(isset($params['oldpwd']))$params['oldpwd']=trim($params['oldpwd']); - if(isset($params['newpwd']))$params['newpwd']=trim($params['newpwd']); - if(isset($params['newpwd2']))$params['newpwd2']=trim($params['newpwd2']); - - if(empty($params['username'])) return json(['code'=>-1, 'msg'=>'用户名不能为空']); - - config_set('admin_username', $params['username']); - - if(!empty($params['oldpwd']) && !empty($params['newpwd']) && !empty($params['newpwd2'])){ - if(config_get('admin_password') != $params['oldpwd']){ - return json(['code'=>-1, 'msg'=>'旧密码不正确']); - } - if($params['newpwd'] != $params['newpwd2']){ - return json(['code'=>-1, 'msg'=>'两次新密码输入不一致']); - } - config_set('admin_password', $params['newpwd']); - } - cache('configs', NULL); - cookie('admin_token', null); - return json(['code'=>0]); - } - - public function testbturl(){ - $bt_url = input('post.bt_url'); - $bt_key = input('post.bt_key'); - if(!$bt_url || !$bt_key)return json(['code'=>-1, 'msg'=>'参数不能为空']); - $btapi = new Btapi($bt_url, $bt_key); - $result = $btapi->get_config(); - if($result && isset($result['status']) && ($result['status']==1 || isset($result['sites_path']))){ - $result = $btapi->get_user_info(); - if($result && isset($result['username'])){ - return json(['code'=>0, 'msg'=>'面板连接测试成功!']); - }else{ - return json(['code'=>-1, 'msg'=>'面板连接测试成功,但未安装专用插件']); - } - }else{ - return json(['code'=>-1, 'msg'=>isset($result['msg'])?$result['msg']:'面板地址无法连接']); - } - } - - public function plugins(){ - $typelist = []; - $json_arr = Plugins::get_plugin_list(); - if($json_arr){ - foreach($json_arr['type'] as $type){ - $typelist[$type['id']] = $type['title']; - } - } - View::assign('typelist', $typelist); - return view(); - } - - public function pluginswin(){ - $typelist = []; - $json_arr = Plugins::get_plugin_list('Windows'); - if($json_arr){ - foreach($json_arr['type'] as $type){ - $typelist[$type['id']] = $type['title']; - } - } - View::assign('typelist', $typelist); - return view(); - } - - public function plugins_data(){ - $type = input('post.type/d'); - $keyword = input('post.keyword', null, 'trim'); - $os = input('get.os'); - if(!$os) $os = 'Linux'; - - $json_arr = Plugins::get_plugin_list($os); - if(!$json_arr) return json([]); - - $typelist = []; - foreach($json_arr['type'] as $row){ - $typelist[$row['id']] = $row['title']; - } - - $list = []; - foreach($json_arr['list'] as $plugin){ - if($type > 0 && $plugin['type']!=$type) continue; - if(!empty($keyword) && $keyword != $plugin['name'] && stripos($plugin['title'], $keyword)===false) continue; - $versions = []; - foreach($plugin['versions'] as $version){ - $ver = $version['m_version'].'.'.$version['version']; - if(isset($version['download'])){ - $status = false; - if(file_exists(get_data_dir().'plugins/other/'.$version['download'])){ - $status = true; - } - $versions[] = ['status'=>$status, 'type'=>1, 'version'=>$ver, 'download'=>$version['download'], 'md5'=>$version['md5']]; - }else{ - $status = false; - if(file_exists(get_data_dir($os).'plugins/package/'.$plugin['name'].'-'.$ver.'.zip')){ - $status = true; - } - $versions[] = ['status'=>$status, 'type'=>0, 'version'=>$ver]; - } - } - if($plugin['name'] == 'obs') $plugin['ps'] = substr($plugin['ps'],0,strpos($plugin['ps'],' $plugin['id'], - 'name' => $plugin['name'], - 'title' => $plugin['title'], - 'type' => $plugin['type'], - 'typename' => $typelist[$plugin['type']], - 'desc' => str_replace('target="_blank"','target="_blank" rel="noopener noreferrer"',$plugin['ps']), - 'price' => $plugin['price'], - 'author' => isset($plugin['author']) ? $plugin['author'] : '官方', - 'versions' => $versions - ]; - } - return json($list); - } - - public function download_plugin(){ - $name = input('post.name', null, 'trim'); - $version = input('post.version', null, 'trim'); - $os = input('post.os'); - if(!$os) $os = 'Linux'; - if(!$name || !$version) return json(['code'=>-1, 'msg'=>'参数不能为空']); - try{ - Plugins::download_plugin($name, $version, $os); - Db::name('log')->insert(['uid' => 0, 'action' => '下载插件', 'data' => $name.'-'.$version.' os:'.$os, 'addtime' => date("Y-m-d H:i:s")]); - return json(['code'=>0,'msg'=>'下载成功']); - }catch(\Exception $e){ - return json(['code'=>-1, 'msg'=>$e->getMessage()]); - } - } - - public function refresh_plugins(){ - $os = input('get.os'); - if(!$os) $os = 'Linux'; - try{ - Plugins::refresh_plugin_list($os); - Db::name('log')->insert(['uid' => 0, 'action' => '刷新插件列表', 'data' => '刷新'.$os.'插件列表成功', 'addtime' => date("Y-m-d H:i:s")]); - return json(['code'=>0,'msg'=>'获取最新插件列表成功!']); - }catch(\Exception $e){ - return json(['code'=>-1, 'msg'=>$e->getMessage()]); - } - } - - public function record(){ - return view(); - } - - public function record_data(){ - $ip = input('post.ip', null, 'trim'); - $offset = input('post.offset/d'); - $limit = input('post.limit/d'); - - $select = Db::name('record'); - if(!empty($ip)){ - $select->where('ip', $ip); - } - $total = $select->count(); - $rows = $select->order('id','desc')->limit($offset, $limit)->select(); - - return json(['total'=>$total, 'rows'=>$rows]); - } - - public function log(){ - return view(); - } - - public function log_data(){ - $action = input('post.action', null, 'trim'); - $offset = input('post.offset/d'); - $limit = input('post.limit/d'); - - $select = Db::name('log'); - if(!empty($action)){ - $select->where('action', $action); - } - $total = $select->count(); - $rows = $select->order('id','desc')->limit($offset, $limit)->select(); - - return json(['total'=>$total, 'rows'=>$rows]); - } - - public function list(){ - $type = input('param.type', 'black'); - View::assign('type', $type); - View::assign('typename', $type=='white'?'白名单':'黑名单'); - return view(); - } - - public function list_data(){ - $type = input('param.type', 'black'); - $ip = input('post.ip', null, 'trim'); - $offset = input('post.offset/d'); - $limit = input('post.limit/d'); - - $tablename = $type == 'black' ? 'black' : 'white'; - $select = Db::name($tablename); - if(!empty($ip)){ - $select->where('ip', $ip); - } - $total = $select->count(); - $rows = $select->order('id','desc')->limit($offset, $limit)->select(); - - return json(['total'=>$total, 'rows'=>$rows]); - } - - public function list_op(){ - $type = input('param.type', 'black'); - $tablename = $type == 'black' ? 'black' : 'white'; - $act = input('post.act', null); - if($act == 'get'){ - $id = input('post.id/d'); - if(!$id) return json(['code'=>-1, 'msg'=>'no id']); - $data = Db::name($tablename)->where('id', $id)->find(); - return json(['code'=>0, 'data'=>$data]); - }elseif($act == 'add'){ - $ip = input('post.ip', null, 'trim'); - if(!$ip) return json(['code'=>-1, 'msg'=>'IP不能为空']); - if(Db::name($tablename)->where('ip', $ip)->find()){ - return json(['code'=>-1, 'msg'=>'该IP已存在']); - } - Db::name($tablename)->insert([ - 'ip' => $ip, - 'enable' => 1, - 'addtime' => date("Y-m-d H:i:s") - ]); - return json(['code'=>0, 'msg'=>'succ']); - }elseif($act == 'edit'){ - $id = input('post.id/d'); - $ip = input('post.ip', null, 'trim'); - if(!$id || !$ip) return json(['code'=>-1, 'msg'=>'IP不能为空']); - if(Db::name($tablename)->where('ip', $ip)->where('id', '<>', $id)->find()){ - return json(['code'=>-1, 'msg'=>'该IP已存在']); - } - Db::name($tablename)->where('id', $id)->update([ - 'ip' => $ip - ]); - return json(['code'=>0, 'msg'=>'succ']); - }elseif($act == 'enable'){ - $id = input('post.id/d'); - $enable = input('post.enable/d'); - if(!$id) return json(['code'=>-1, 'msg'=>'no id']); - Db::name($tablename)->where('id', $id)->update([ - 'enable' => $enable - ]); - return json(['code'=>0, 'msg'=>'succ']); - }elseif($act == 'del'){ - $id = input('post.id/d'); - if(!$id) return json(['code'=>-1, 'msg'=>'no id']); - Db::name($tablename)->where('id', $id)->delete(); - return json(['code'=>0, 'msg'=>'succ']); - } - return json(['code'=>-1, 'msg'=>'no act']); - } - - public function deplist(){ - $deplist_linux = get_data_dir().'config/deployment_list.json'; - $deplist_win = get_data_dir('Windows').'config/deployment_list.json'; - $deplist_linux_time = file_exists($deplist_linux) ? date("Y-m-d H:i:s", filemtime($deplist_linux)) : '不存在'; - $deplist_win_time = file_exists($deplist_win) ? date("Y-m-d H:i:s", filemtime($deplist_win)) : '不存在'; - View::assign('deplist_linux_time', $deplist_linux_time); - View::assign('deplist_win_time', $deplist_win_time); - return view(); - } - - public function refresh_deplist(){ - $os = input('get.os'); - if(!$os) $os = 'Linux'; - try{ - Plugins::refresh_deplist($os); - Db::name('log')->insert(['uid' => 0, 'action' => '刷新一键部署列表', 'data' => '刷新'.$os.'一键部署列表成功', 'addtime' => date("Y-m-d H:i:s")]); - return json(['code'=>0,'msg'=>'获取最新一键部署列表成功!']); - }catch(\Exception $e){ - return json(['code'=>-1, 'msg'=>$e->getMessage()]); - } - } - - public function cleancache(){ - Cache::clear(); - return json(['code'=>0,'msg'=>'succ']); - } +islogin){ + return redirect('/admin'); + } + if(request()->isAjax()){ + $username = input('post.username',null,'trim'); + $password = input('post.password',null,'trim'); + $code = input('post.code',null,'trim'); + + if(empty($username) || empty($password)){ + return json(['code'=>-1, 'msg'=>'用户名或密码不能为空']); + } + if(!captcha_check($code)){ + return json(['code'=>-1, 'msg'=>'验证码错误']); + } + if($username == config_get('admin_username') && $password == config_get('admin_password')){ + Db::name('log')->insert(['uid' => 0, 'action' => '登录后台', 'data' => 'IP:'.$this->clientip, 'addtime' => date("Y-m-d H:i:s")]); + $session = md5($username.config_get('admin_password')); + $expiretime = time()+2562000; + $token = authcode("{$username}\t{$session}\t{$expiretime}", 'ENCODE', config_get('syskey')); + cookie('admin_token', $token, ['expire' => $expiretime, 'httponly' => true]); + config_set('admin_lastlogin', date('Y-m-d H:i:s')); + return json(['code'=>0]); + }else{ + return json(['code'=>-1, 'msg'=>'用户名或密码错误']); + } + } + return view(); + } + + public function logout() + { + cookie('admin_token', null); + return redirect('/admin/login'); + } + + public function index() + { + $stat = ['total'=>0, 'free'=>0, 'pro'=>0, 'ltd'=>0, 'third'=>0]; + $json_arr = Plugins::get_plugin_list(); + if($json_arr){ + foreach($json_arr['list'] as $plugin){ + $stat['total']++; + if($plugin['type']==10) $stat['third']++; + elseif($plugin['type']==12) $stat['ltd']++; + elseif($plugin['type']==8) $stat['pro']++; + elseif($plugin['type']==5 || $plugin['type']==6 || $plugin['type']==7) $stat['free']++; + } + } + $stat['runtime'] = Db::name('config')->where('key','runtime')->value('value') ?? '未运行'; + $stat['record_total'] = Db::name('record')->count(); + $stat['record_isuse'] = Db::name('record')->whereTime('usetime', '>=', strtotime('-7 days'))->count(); + View::assign('stat', $stat); + + $tmp = 'version()'; + $mysqlVersion = Db::query("select version()")[0][$tmp]; + $info = [ + 'framework_version' => app()::VERSION, + 'php_version' => PHP_VERSION, + 'mysql_version' => $mysqlVersion, + 'software' => $_SERVER['SERVER_SOFTWARE'], + 'os' => php_uname(), + 'date' => date("Y-m-d H:i:s"), + ]; + View::assign('info', $info); + return view(); + } + + public function set(){ + if(request()->isAjax()){ + $params = Request::param(); + + foreach ($params as $key => $value) { + config_set($key, $value); + } + cache('configs', NULL); + return json(['code'=>0]); + } + $mod = input('param.mod', 'sys'); + View::assign('mod', $mod); + View::assign('conf', config('sys')); + $runtime = Db::name('config')->where('key','runtime')->value('value') ?? '未运行'; + View::assign('runtime', $runtime); + return view(); + } + + public function setaccount(){ + $params = Request::param(); + if(isset($params['username']))$params['username']=trim($params['username']); + if(isset($params['oldpwd']))$params['oldpwd']=trim($params['oldpwd']); + if(isset($params['newpwd']))$params['newpwd']=trim($params['newpwd']); + if(isset($params['newpwd2']))$params['newpwd2']=trim($params['newpwd2']); + + if(empty($params['username'])) return json(['code'=>-1, 'msg'=>'用户名不能为空']); + + config_set('admin_username', $params['username']); + + if(!empty($params['oldpwd']) && !empty($params['newpwd']) && !empty($params['newpwd2'])){ + if(config_get('admin_password') != $params['oldpwd']){ + return json(['code'=>-1, 'msg'=>'旧密码不正确']); + } + if($params['newpwd'] != $params['newpwd2']){ + return json(['code'=>-1, 'msg'=>'两次新密码输入不一致']); + } + config_set('admin_password', $params['newpwd']); + } + cache('configs', NULL); + cookie('admin_token', null); + return json(['code'=>0]); + } + + public function testbturl(){ + $bt_type = input('post.bt_type/d'); + + if($bt_type == 1){ + $bt_surl = input('post.bt_surl'); + if(!$bt_surl)return json(['code'=>-1, 'msg'=>'参数不能为空']); + $res = get_curl($bt_surl . 'api/SetupCount'); + if(strpos($res, 'ok')!==false){ + return json(['code'=>0, 'msg'=>'第三方云端连接测试成功!']); + }else{ + return json(['code'=>-1, 'msg'=>'第三方云端连接测试失败']); + } + }else{ + $bt_url = input('post.bt_url'); + $bt_key = input('post.bt_key'); + if(!$bt_url || !$bt_key)return json(['code'=>-1, 'msg'=>'参数不能为空']); + $btapi = new Btapi($bt_url, $bt_key); + $result = $btapi->get_config(); + if($result && isset($result['status']) && ($result['status']==1 || isset($result['sites_path']))){ + $result = $btapi->get_user_info(); + if($result && isset($result['username'])){ + return json(['code'=>0, 'msg'=>'面板连接测试成功!']); + }else{ + return json(['code'=>-1, 'msg'=>'面板连接测试成功,但未安装专用插件']); + } + }else{ + return json(['code'=>-1, 'msg'=>isset($result['msg'])?$result['msg']:'面板地址无法连接']); + } + } + } + + public function plugins(){ + $typelist = []; + $json_arr = Plugins::get_plugin_list(); + if($json_arr){ + foreach($json_arr['type'] as $type){ + if($type['title'] == '一键部署') continue; + $typelist[$type['id']] = $type['title']; + } + } + View::assign('typelist', $typelist); + return view(); + } + + public function pluginswin(){ + $typelist = []; + $json_arr = Plugins::get_plugin_list('Windows'); + if($json_arr){ + foreach($json_arr['type'] as $type){ + if($type['title'] == '一键部署') continue; + $typelist[$type['id']] = $type['title']; + } + } + View::assign('typelist', $typelist); + return view(); + } + + public function plugins_data(){ + $type = input('post.type/d'); + $keyword = input('post.keyword', null, 'trim'); + $os = input('get.os'); + if(!$os) $os = 'Linux'; + + $json_arr = Plugins::get_plugin_list($os); + if(!$json_arr) return json([]); + + $typelist = []; + foreach($json_arr['type'] as $row){ + $typelist[$row['id']] = $row['title']; + } + + $list = []; + foreach($json_arr['list'] as $plugin){ + if($type > 0 && $plugin['type']!=$type) continue; + if(!empty($keyword) && $keyword != $plugin['name'] && stripos($plugin['title'], $keyword)===false) continue; + $versions = []; + foreach($plugin['versions'] as $version){ + $ver = $version['m_version'].'.'.$version['version']; + if(isset($version['download'])){ + $status = false; + if(file_exists(get_data_dir().'plugins/other/'.$version['download'])){ + $status = true; + } + $versions[] = ['status'=>$status, 'type'=>1, 'version'=>$ver, 'download'=>$version['download'], 'md5'=>$version['md5']]; + }else{ + $status = false; + if(file_exists(get_data_dir($os).'plugins/package/'.$plugin['name'].'-'.$ver.'.zip')){ + $status = true; + } + $versions[] = ['status'=>$status, 'type'=>0, 'version'=>$ver]; + } + } + if($plugin['name'] == 'obs') $plugin['ps'] = substr($plugin['ps'],0,strpos($plugin['ps'],' $plugin['id'], + 'name' => $plugin['name'], + 'title' => $plugin['title'], + 'type' => $plugin['type'], + 'typename' => $typelist[$plugin['type']], + 'desc' => str_replace('target="_blank"','target="_blank" rel="noopener noreferrer"',$plugin['ps']), + 'price' => $plugin['price'], + 'author' => isset($plugin['author']) ? $plugin['author'] : '官方', + 'versions' => $versions + ]; + } + return json($list); + } + + public function download_plugin(){ + $name = input('post.name', null, 'trim'); + $version = input('post.version', null, 'trim'); + $os = input('post.os'); + if(!$os) $os = 'Linux'; + if(!$name || !$version) return json(['code'=>-1, 'msg'=>'参数不能为空']); + try{ + Plugins::download_plugin($name, $version, $os); + Db::name('log')->insert(['uid' => 0, 'action' => '下载插件', 'data' => $name.'-'.$version.' os:'.$os, 'addtime' => date("Y-m-d H:i:s")]); + return json(['code'=>0,'msg'=>'下载成功']); + }catch(\Exception $e){ + return json(['code'=>-1, 'msg'=>$e->getMessage()]); + } + } + + public function refresh_plugins(){ + $os = input('get.os'); + if(!$os) $os = 'Linux'; + try{ + Plugins::refresh_plugin_list($os); + Db::name('log')->insert(['uid' => 0, 'action' => '刷新插件列表', 'data' => '刷新'.$os.'插件列表成功', 'addtime' => date("Y-m-d H:i:s")]); + return json(['code'=>0,'msg'=>'获取最新插件列表成功!']); + }catch(\Exception $e){ + return json(['code'=>-1, 'msg'=>$e->getMessage()]); + } + } + + public function record(){ + return view(); + } + + public function record_data(){ + $ip = input('post.ip', null, 'trim'); + $offset = input('post.offset/d'); + $limit = input('post.limit/d'); + + $select = Db::name('record'); + if(!empty($ip)){ + $select->where('ip', $ip); + } + $total = $select->count(); + $rows = $select->order('id','desc')->limit($offset, $limit)->select(); + + return json(['total'=>$total, 'rows'=>$rows]); + } + + public function log(){ + return view(); + } + + public function log_data(){ + $action = input('post.action', null, 'trim'); + $offset = input('post.offset/d'); + $limit = input('post.limit/d'); + + $select = Db::name('log'); + if(!empty($action)){ + $select->where('action', $action); + } + $total = $select->count(); + $rows = $select->order('id','desc')->limit($offset, $limit)->select(); + + return json(['total'=>$total, 'rows'=>$rows]); + } + + public function list(){ + $type = input('param.type', 'black'); + View::assign('type', $type); + View::assign('typename', $type=='white'?'白名单':'黑名单'); + return view(); + } + + public function list_data(){ + $type = input('param.type', 'black'); + $ip = input('post.ip', null, 'trim'); + $offset = input('post.offset/d'); + $limit = input('post.limit/d'); + + $tablename = $type == 'black' ? 'black' : 'white'; + $select = Db::name($tablename); + if(!empty($ip)){ + $select->where('ip', $ip); + } + $total = $select->count(); + $rows = $select->order('id','desc')->limit($offset, $limit)->select(); + + return json(['total'=>$total, 'rows'=>$rows]); + } + + public function list_op(){ + $type = input('param.type', 'black'); + $tablename = $type == 'black' ? 'black' : 'white'; + $act = input('post.act', null); + if($act == 'get'){ + $id = input('post.id/d'); + if(!$id) return json(['code'=>-1, 'msg'=>'no id']); + $data = Db::name($tablename)->where('id', $id)->find(); + return json(['code'=>0, 'data'=>$data]); + }elseif($act == 'add'){ + $ip = input('post.ip', null, 'trim'); + if(!$ip) return json(['code'=>-1, 'msg'=>'IP不能为空']); + if(Db::name($tablename)->where('ip', $ip)->find()){ + return json(['code'=>-1, 'msg'=>'该IP已存在']); + } + Db::name($tablename)->insert([ + 'ip' => $ip, + 'enable' => 1, + 'addtime' => date("Y-m-d H:i:s") + ]); + return json(['code'=>0, 'msg'=>'succ']); + }elseif($act == 'edit'){ + $id = input('post.id/d'); + $ip = input('post.ip', null, 'trim'); + if(!$id || !$ip) return json(['code'=>-1, 'msg'=>'IP不能为空']); + if(Db::name($tablename)->where('ip', $ip)->where('id', '<>', $id)->find()){ + return json(['code'=>-1, 'msg'=>'该IP已存在']); + } + Db::name($tablename)->where('id', $id)->update([ + 'ip' => $ip + ]); + return json(['code'=>0, 'msg'=>'succ']); + }elseif($act == 'enable'){ + $id = input('post.id/d'); + $enable = input('post.enable/d'); + if(!$id) return json(['code'=>-1, 'msg'=>'no id']); + Db::name($tablename)->where('id', $id)->update([ + 'enable' => $enable + ]); + return json(['code'=>0, 'msg'=>'succ']); + }elseif($act == 'del'){ + $id = input('post.id/d'); + if(!$id) return json(['code'=>-1, 'msg'=>'no id']); + Db::name($tablename)->where('id', $id)->delete(); + return json(['code'=>0, 'msg'=>'succ']); + } + return json(['code'=>-1, 'msg'=>'no act']); + } + + public function deplist(){ + $deplist_linux = get_data_dir().'config/deployment_list.json'; + $deplist_win = get_data_dir('Windows').'config/deployment_list.json'; + $deplist_linux_time = file_exists($deplist_linux) ? date("Y-m-d H:i:s", filemtime($deplist_linux)) : '不存在'; + $deplist_win_time = file_exists($deplist_win) ? date("Y-m-d H:i:s", filemtime($deplist_win)) : '不存在'; + View::assign('deplist_linux_time', $deplist_linux_time); + View::assign('deplist_win_time', $deplist_win_time); + return view(); + } + + public function refresh_deplist(){ + $os = input('get.os'); + if(!$os) $os = 'Linux'; + try{ + Plugins::refresh_deplist($os); + Db::name('log')->insert(['uid' => 0, 'action' => '刷新一键部署列表', 'data' => '刷新'.$os.'一键部署列表成功', 'addtime' => date("Y-m-d H:i:s")]); + return json(['code'=>0,'msg'=>'获取最新一键部署列表成功!']); + }catch(\Exception $e){ + return json(['code'=>-1, 'msg'=>$e->getMessage()]); + } + } + + public function cleancache(){ + Cache::clear(); + return json(['code'=>0,'msg'=>'succ']); + } } \ No newline at end of file diff --git a/app/controller/Api.php b/app/controller/Api.php index 0a6d88e..a523b8b 100644 --- a/app/controller/Api.php +++ b/app/controller/Api.php @@ -1,408 +1,394 @@ -checklist()) return ''; - $record = Db::name('record')->where('ip',$this->clientip)->find(); - if($record){ - Db::name('record')->where('id',$record['id'])->update(['usetime'=>date("Y-m-d H:i:s")]); - }else{ - Db::name('record')->insert(['ip'=>$this->clientip, 'addtime'=>date("Y-m-d H:i:s"), 'usetime'=>date("Y-m-d H:i:s")]); - } - $json_arr = Plugins::get_plugin_list(); - if(!$json_arr) return json((object)[]); - return json($json_arr); - } - - //获取插件列表(win) - public function get_plugin_list_win(){ - if(!$this->checklist()) return ''; - $record = Db::name('record')->where('ip',$this->clientip)->find(); - if($record){ - Db::name('record')->where('id',$record['id'])->update(['usetime'=>date("Y-m-d H:i:s")]); - }else{ - Db::name('record')->insert(['ip'=>$this->clientip, 'addtime'=>date("Y-m-d H:i:s"), 'usetime'=>date("Y-m-d H:i:s")]); - } - $json_file = get_data_dir('Windows').'config/plugin_list.json'; - if(file_exists($json_file)){ - $data = file_get_contents($json_file); - $json_arr = json_decode($data, true); - if($json_arr){ - return json($json_arr); - } - } - return json((object)[]); - } - - //下载插件包 - public function download_plugin(){ - $plugin_name = input('post.name'); - $version = input('post.version'); - $os = input('post.os'); - if(!$plugin_name || !$version){ - return '参数不能为空'; - } - if(!in_array($os,['Windows','Linux'])) $os = 'Linux'; - if(!preg_match('/^[a-zA-Z0-9_]+$/', $plugin_name) || !preg_match('/^[0-9.]+$/', $version)){ - return '参数不正确'; - } - if(!$this->checklist()) '你的服务器被禁止使用此云端'; - $filepath = get_data_dir($os).'plugins/package/'.$plugin_name.'-'.$version.'.zip'; - if(file_exists($filepath)){ - $filename = $plugin_name.'.zip'; - $this->output_file($filepath, $filename); - }else{ - return '云端不存在该插件包'; - } - } - - //下载插件主文件 - public function download_plugin_main(){ - $plugin_name = input('post.name'); - $version = input('post.version'); - $os = input('post.os'); - if(!$plugin_name || !$version){ - return '参数不能为空'; - } - if(!in_array($os,['Windows','Linux'])) $os = 'Linux'; - if(!preg_match('/^[a-zA-Z0-9_]+$/', $plugin_name) || !preg_match('/^[0-9.]+$/', $version)){ - return '参数不正确'; - } - if(!$this->checklist()) '你的服务器被禁止使用此云端'; - $filepath = get_data_dir($os).'plugins/main/'.$plugin_name.'-'.$version.'.dat'; - if(file_exists($filepath)){ - $filename = $plugin_name.'_main.py'; - $this->output_file($filepath, $filename); - }else{ - $filepath = get_data_dir($os).'plugins/folder/'.$plugin_name.'-'.$version.'/'.$plugin_name.'/'.$plugin_name.'_main.py'; - if(file_exists($filepath)){ - $filename = $plugin_name.'_main.py'; - $this->output_file($filepath, $filename); - }else{ - return '云端不存在该插件主文件'; - } - } - } - - //下载插件其他文件 - public function download_plugin_other(){ - $fname = input('get.fname'); - if(!$fname){ - return json(['status'=>false, 'msg'=>'参数不能为空']); - } - if(strpos(dirname($fname),'.')!==false)return json(['status'=>false, 'msg'=>'参数不正确']); - if(!$this->checklist()) return json(['status'=>false, 'msg'=>'你的服务器被禁止使用此云端']); - $filepath = get_data_dir().'plugins/other/'.$fname; - if(file_exists($filepath)){ - $filename = basename($fname); - $this->output_file($filepath, $filename); - }else{ - return json(['status'=>false, 'msg'=>'云端不存在该插件文件']); - } - } - - public function get_update_logs(){ - $type = input('get.type'); - if($type == 'Windows'){ - $version = config_get('new_version_win'); - $data = [ - [ - 'title' => 'Linux面板'.$version, - 'body' => config_get('update_msg_win'), - 'addtime' => config_get('update_date_win') - ] - ]; - }else{ - $version = config_get('new_version'); - $data = [ - [ - 'title' => 'Linux面板'.$version, - 'body' => config_get('update_msg'), - 'addtime' => config_get('update_date') - ] - ]; - } - return jsonp($data); - } - - public function get_version(){ - $version = config_get('new_version'); - return $version; - } - - public function get_version_win(){ - $version = config_get('new_version_win'); - return $version; - } - - //安装统计 - public function setup_count(){ - return 'ok'; - } - - //检测更新 - public function check_update(){ - $version = config_get('new_version'); - $down_url = request()->root(true).'/install/update/LinuxPanel-'.$version.'.zip'; - $data = [ - 'force' => false, - 'version' => $version, - 'downUrl' => $down_url, - 'updateMsg' => config_get('update_msg'), - 'uptime' => config_get('update_date'), - 'is_beta' => 0, - 'adviser' => -1, - 'btb' => '', - 'beta' => [ - 'version' => $version, - 'downUrl' => $down_url, - 'updateMsg' => config_get('update_msg'), - 'uptime' => config_get('update_date'), - ] - ]; - return json($data); - } - - //检测更新(win) - public function check_update_win(){ - $version = config_get('new_version_win'); - $down_url = request()->root(true).'/win/panel/panel_'.$version.'.zip'; - $data = [ - 'force' => false, - 'version' => $version, - 'downUrl' => $down_url, - 'updateMsg' => config_get('update_msg_win'), - 'uptime' => config_get('update_date_win'), - 'is_beta' => 0, - 'py_version' => '3.8.6', - 'adviser' => -1, - 'is_rec' => -1, - 'btb' => '', - 'beta' => [ - 'py_version' => '3.8.6', - 'version' => $version, - 'downUrl' => $down_url, - 'updateMsg' => config_get('update_msg_win'), - 'uptime' => config_get('update_date_win'), - ] - ]; - return json($data); - } - - //宝塔云监控获取最新版本 - public function btm_latest_version(){ - $data = [ - 'version' => config_get('new_version_btm'), - 'description' => config_get('update_msg_btm'), - 'create_time' => config_get('update_date_btm') - ]; - return json($data); - } - - //宝塔云监控更新日志 - public function btm_update_history(){ - $data = [ - [ - 'version' => config_get('new_version_btm'), - 'description' => config_get('update_msg_btm'), - 'create_time' => config_get('update_date_btm') - ] - ]; - return json($data); - } - - //获取内测版更新日志 - public function get_beta_logs(){ - return json(['beta_ps'=>'当前暂无内测版', 'list'=>[]]); - } - - //检查用户绑定是否正确 - public function check_auth_key(){ - return '1'; - } - - //从云端验证域名是否可访问 - public function check_domain(){ - $domain = input('post.domain',null,'trim'); - $ssl = input('post.ssl/d'); - if(!$domain) return json(['status'=>false, 'msg'=>'域名不能为空']); - if(!strpos($domain,'.')) return json(['status'=>false, 'msg'=>'域名格式不正确']); - $domain = str_replace('*.','',$domain); - $ip = gethostbyname($domain); - if(!$ip || $ip == $domain){ - return json(['status'=>false, 'msg'=>'无法访问']); - }else{ - return json(['status'=>true, 'msg'=>'访问正常']); - } - } - - //同步时间 - public function get_time(){ - return time(); - } - - //同步时间 - public function get_win_date(){ - return date("Y-m-d H:i:s"); - } - - //查询是否专业版(废弃) - public function is_pro(){ - return json(['endtime'=>true, 'code'=>1]); - } - - //获取产品推荐信息 - public function get_plugin_remarks(){ - return json(['list'=>[], 'pro_list'=>[], 'kfqq'=>'', 'kf'=>'', 'qun'=>'']); - } - - //获取指定插件评分 - public function get_plugin_socre(){ - return json(['total'=>0, 'split'=>[0,0,0,0,0],'page'=>"
1共计0条数据
",'data'=>[]]); - } - - //提交插件评分 - public function plugin_score(){ - return json(['status'=>true, 'msg'=>'您的评分已成功提交,感谢您的支持!']); - } - - //获取IP地址 - public function get_ip_address(){ - return $this->clientip; - } - - //绑定账号 - public function get_auth_token(){ - if(!$_POST['data']) return json(['status'=>false, 'msg'=>'参数不能为空']); - $reqData = hex2bin($_POST['data']); - parse_str($reqData, $arr); - $serverid = $arr['serverid']; - $userinfo = ['uid'=>1, 'username'=>'Administrator', 'address'=>'127.0.0.1', 'serverid'=>$serverid, 'access_key'=>random(32), 'secret_key'=>random(48), 'ukey'=>md5(time()), 'state'=>1]; - $data = bin2hex(urlencode(json_encode($userinfo))); - return json(['status'=>true, 'msg'=>'登录成功!', 'data'=>$data]); - } - - //绑定账号新 - public function authorization_login(){ - if(!$_POST['data']) return json(['status'=>false, 'msg'=>'参数不能为空']); - $reqData = hex2bin($_POST['data']); - parse_str($reqData, $arr); - $serverid = $arr['serverid']; - $userinfo = ['uid'=>1, 'username'=>'Administrator', 'ip'=>'127.0.0.1', 'server_id'=>$serverid, 'access_key'=>random(32), 'secret_key'=>random(48)]; - $data = bin2hex(urlencode(json_encode($userinfo))); - return json(['status'=>true, 'msg'=>'登录成功!', 'data'=>$data]); - } - - //刷新授权信息 - public function authorization_info(){ - if(!$_POST['data']) return json(['status'=>false, 'msg'=>'参数不能为空']); - $reqData = hex2bin($_POST['data']); - parse_str($reqData, $arr); - $id = isset($arr['id'])&&$arr['id']>0?$arr['id']:1; - $userinfo = ['id'=>$id, 'product'=>$arr['product'], 'status'=>2, 'clients'=>9999, 'durations'=>0, 'end_time'=>strtotime('+10 year')]; - $data = bin2hex(urlencode(json_encode($userinfo))); - return json(['status'=>true, 'data'=>$data]); - } - - //一键部署列表 - public function get_deplist(){ - $os = input('post.os'); - $json_arr = Plugins::get_deplist($os); - if(!$json_arr) return json([]); - return json($json_arr); - } - - //获取宝塔SSL列表 - public function get_ssl_list(){ - $data = bin2hex('[]'); - return json(['status'=>true, 'msg'=>'', 'data'=>$data]); - } - - public function return_success(){ - return json(['status'=>true, 'msg'=>1, 'data'=>(object)[]]); - } - - public function return_error(){ - return json(['status'=>false, 'msg'=>'不支持当前操作']); - } - - public function return_error2(){ - return json(['success'=>false, 'res'=>'不支持当前操作']); - } - - public function return_empty(){ - return ''; - } - - public function return_empty_array(){ - return json([]); - } - - public function return_page_data(){ - return json(['page'=>"
11/0从1-1000条共计0条数据
", 'data'=>[]]); - } - - public function btwaf_getspiders(){ - $result = cache('btwaf_getspiders'); - if($result){ - return json($result); - } - $bt_url = config_get('bt_url'); - $bt_key = config_get('bt_key'); - if(!$bt_url || !$bt_key) return json([]); - $btapi = new \app\lib\Btapi($bt_url, $bt_key); - $result = $btapi->btwaf_getspiders(); - if(isset($result['status']) && $result['status']){ - cache('btwaf_getspiders', $result['data'], 3600 * 24 * 3); - return json($result['data']); - } - return json($result); - } - - //检查黑白名单 - private function checklist(){ - if(config_get('whitelist') == 1){ - if(Db::name('white')->where('ip', $this->clientip)->where('enable', 1)->find()){ - return true; - } - return false; - }else{ - if(Db::name('black')->where('ip', $this->clientip)->where('enable', 1)->find()){ - return false; - } - return true; - } - } - - //下载大文件 - private function output_file($filepath, $filename){ - $filesize = filesize($filepath); - $filemd5 = md5_file($filepath); - - ob_clean(); - header("Content-Type: application/octet-stream"); - header("Content-Disposition: attachment; filename={$filename}.zip"); - header("Content-Length: {$filesize}"); - header("File-size: {$filesize}"); - header("Content-md5: {$filemd5}"); - - $read_buffer = 1024 * 100; - $handle = fopen($filepath, 'rb'); - $sum_buffer = 0; - while(!feof($handle) && $sum_buffer<$filesize) { - echo fread($handle, min($read_buffer, ($filesize - $sum_buffer) + 1)); - $sum_buffer += $read_buffer; - flush(); - } - fclose($handle); - exit; - } +checklist()) return ''; + $record = Db::name('record')->where('ip',$this->clientip)->find(); + if($record){ + Db::name('record')->where('id',$record['id'])->update(['usetime'=>date("Y-m-d H:i:s")]); + }else{ + Db::name('record')->insert(['ip'=>$this->clientip, 'addtime'=>date("Y-m-d H:i:s"), 'usetime'=>date("Y-m-d H:i:s")]); + } + $json_arr = Plugins::get_plugin_list(); + if(!$json_arr) return json((object)[]); + return json($json_arr); + } + + //获取插件列表(win) + public function get_plugin_list_win(){ + if(!$this->checklist()) return ''; + $record = Db::name('record')->where('ip',$this->clientip)->find(); + if($record){ + Db::name('record')->where('id',$record['id'])->update(['usetime'=>date("Y-m-d H:i:s")]); + }else{ + Db::name('record')->insert(['ip'=>$this->clientip, 'addtime'=>date("Y-m-d H:i:s"), 'usetime'=>date("Y-m-d H:i:s")]); + } + $json_arr = Plugins::get_plugin_list('Windows'); + if(!$json_arr) return json((object)[]); + return json($json_arr); + } + + //下载插件包 + public function download_plugin(){ + $plugin_name = input('post.name'); + $version = input('post.version'); + $os = input('post.os'); + if(!$plugin_name || !$version){ + return '参数不能为空'; + } + if(!in_array($os,['Windows','Linux'])) $os = 'Linux'; + if(!preg_match('/^[a-zA-Z0-9_]+$/', $plugin_name) || !preg_match('/^[0-9.]+$/', $version)){ + return '参数不正确'; + } + if(!$this->checklist()) '你的服务器被禁止使用此云端'; + $filepath = get_data_dir($os).'plugins/package/'.$plugin_name.'-'.$version.'.zip'; + if(file_exists($filepath)){ + $filename = $plugin_name.'.zip'; + $this->output_file($filepath, $filename); + }else{ + return '云端不存在该插件包'; + } + } + + //下载插件主文件 + public function download_plugin_main(){ + $plugin_name = input('post.name'); + $version = input('post.version'); + $os = input('post.os'); + if(!$plugin_name || !$version){ + return '参数不能为空'; + } + if(!in_array($os,['Windows','Linux'])) $os = 'Linux'; + if(!preg_match('/^[a-zA-Z0-9_]+$/', $plugin_name) || !preg_match('/^[0-9.]+$/', $version)){ + return '参数不正确'; + } + if(!$this->checklist()) '你的服务器被禁止使用此云端'; + $filepath = get_data_dir($os).'plugins/main/'.$plugin_name.'-'.$version.'.dat'; + if(file_exists($filepath)){ + $filename = $plugin_name.'_main.py'; + $this->output_file($filepath, $filename); + }else{ + $filepath = get_data_dir($os).'plugins/folder/'.$plugin_name.'-'.$version.'/'.$plugin_name.'/'.$plugin_name.'_main.py'; + if(file_exists($filepath)){ + $filename = $plugin_name.'_main.py'; + $this->output_file($filepath, $filename); + }else{ + return '云端不存在该插件主文件'; + } + } + } + + //下载插件其他文件 + public function download_plugin_other(){ + $fname = input('get.fname'); + if(!$fname){ + return json(['status'=>false, 'msg'=>'参数不能为空']); + } + if(strpos(dirname($fname),'.')!==false)return json(['status'=>false, 'msg'=>'参数不正确']); + if(!$this->checklist()) return json(['status'=>false, 'msg'=>'你的服务器被禁止使用此云端']); + $filepath = get_data_dir().'plugins/other/'.$fname; + if(file_exists($filepath)){ + $filename = basename($fname); + $this->output_file($filepath, $filename); + }else{ + return json(['status'=>false, 'msg'=>'云端不存在该插件文件']); + } + } + + public function get_update_logs(){ + $type = input('get.type'); + if($type == 'Windows'){ + $version = config_get('new_version_win'); + $data = [ + [ + 'title' => 'Linux面板'.$version, + 'body' => config_get('update_msg_win'), + 'addtime' => config_get('update_date_win') + ] + ]; + }else{ + $version = config_get('new_version'); + $data = [ + [ + 'title' => 'Linux面板'.$version, + 'body' => config_get('update_msg'), + 'addtime' => config_get('update_date') + ] + ]; + } + return jsonp($data); + } + + public function get_version(){ + $version = config_get('new_version'); + return $version; + } + + public function get_version_win(){ + $version = config_get('new_version_win'); + return $version; + } + + //安装统计 + public function setup_count(){ + return 'ok'; + } + + //检测更新 + public function check_update(){ + $version = config_get('new_version'); + $down_url = request()->root(true).'/install/update/LinuxPanel-'.$version.'.zip'; + $data = [ + 'force' => false, + 'version' => $version, + 'downUrl' => $down_url, + 'updateMsg' => config_get('update_msg'), + 'uptime' => config_get('update_date'), + 'is_beta' => 0, + 'adviser' => -1, + 'btb' => '', + 'beta' => [ + 'version' => $version, + 'downUrl' => $down_url, + 'updateMsg' => config_get('update_msg'), + 'uptime' => config_get('update_date'), + ] + ]; + return json($data); + } + + //检测更新(win) + public function check_update_win(){ + $version = config_get('new_version_win'); + $down_url = request()->root(true).'/win/panel/panel_'.$version.'.zip'; + $data = [ + 'force' => false, + 'version' => $version, + 'downUrl' => $down_url, + 'updateMsg' => config_get('update_msg_win'), + 'uptime' => config_get('update_date_win'), + 'is_beta' => 0, + 'py_version' => '3.8.6', + 'adviser' => -1, + 'is_rec' => -1, + 'btb' => '', + 'beta' => [ + 'py_version' => '3.8.6', + 'version' => $version, + 'downUrl' => $down_url, + 'updateMsg' => config_get('update_msg_win'), + 'uptime' => config_get('update_date_win'), + ] + ]; + return json($data); + } + + //宝塔云监控获取最新版本 + public function btm_latest_version(){ + $data = [ + 'version' => config_get('new_version_btm'), + 'description' => config_get('update_msg_btm'), + 'create_time' => config_get('update_date_btm') + ]; + return json($data); + } + + //宝塔云监控更新日志 + public function btm_update_history(){ + $data = [ + [ + 'version' => config_get('new_version_btm'), + 'description' => config_get('update_msg_btm'), + 'create_time' => config_get('update_date_btm') + ] + ]; + return json($data); + } + + //获取内测版更新日志 + public function get_beta_logs(){ + return json(['beta_ps'=>'当前暂无内测版', 'list'=>[]]); + } + + //检查用户绑定是否正确 + public function check_auth_key(){ + return '1'; + } + + //从云端验证域名是否可访问 + public function check_domain(){ + $domain = input('post.domain',null,'trim'); + $ssl = input('post.ssl/d'); + if(!$domain) return json(['status'=>false, 'msg'=>'域名不能为空']); + if(!strpos($domain,'.')) return json(['status'=>false, 'msg'=>'域名格式不正确']); + $domain = str_replace('*.','',$domain); + $ip = gethostbyname($domain); + if(!$ip || $ip == $domain){ + return json(['status'=>false, 'msg'=>'无法访问']); + }else{ + return json(['status'=>true, 'msg'=>'访问正常']); + } + } + + //同步时间 + public function get_time(){ + return time(); + } + + //同步时间 + public function get_win_date(){ + return date("Y-m-d H:i:s"); + } + + //查询是否专业版(废弃) + public function is_pro(){ + return json(['endtime'=>true, 'code'=>1]); + } + + //获取产品推荐信息 + public function get_plugin_remarks(){ + return json(['list'=>[], 'pro_list'=>[], 'kfqq'=>'', 'kf'=>'', 'qun'=>'']); + } + + //获取指定插件评分 + public function get_plugin_socre(){ + return json(['total'=>0, 'split'=>[0,0,0,0,0],'page'=>"
1共计0条数据
",'data'=>[]]); + } + + //提交插件评分 + public function plugin_score(){ + return json(['status'=>true, 'msg'=>'您的评分已成功提交,感谢您的支持!']); + } + + //获取IP地址 + public function get_ip_address(){ + return $this->clientip; + } + + //绑定账号 + public function get_auth_token(){ + if(!$_POST['data']) return json(['status'=>false, 'msg'=>'参数不能为空']); + $reqData = hex2bin($_POST['data']); + parse_str($reqData, $arr); + $serverid = $arr['serverid']; + $userinfo = ['uid'=>1, 'username'=>'Administrator', 'address'=>'127.0.0.1', 'serverid'=>$serverid, 'access_key'=>random(32), 'secret_key'=>random(48), 'ukey'=>md5(time()), 'state'=>1]; + $data = bin2hex(urlencode(json_encode($userinfo))); + return json(['status'=>true, 'msg'=>'登录成功!', 'data'=>$data]); + } + + //绑定账号新 + public function authorization_login(){ + if(!$_POST['data']) return json(['status'=>false, 'msg'=>'参数不能为空']); + $reqData = hex2bin($_POST['data']); + parse_str($reqData, $arr); + $serverid = $arr['serverid']; + $userinfo = ['uid'=>1, 'username'=>'Administrator', 'ip'=>'127.0.0.1', 'server_id'=>$serverid, 'access_key'=>random(32), 'secret_key'=>random(48)]; + $data = bin2hex(urlencode(json_encode($userinfo))); + return json(['status'=>true, 'msg'=>'登录成功!', 'data'=>$data]); + } + + //刷新授权信息 + public function authorization_info(){ + if(!$_POST['data']) return json(['status'=>false, 'msg'=>'参数不能为空']); + $reqData = hex2bin($_POST['data']); + parse_str($reqData, $arr); + $id = isset($arr['id'])&&$arr['id']>0?$arr['id']:1; + $userinfo = ['id'=>$id, 'product'=>$arr['product'], 'status'=>2, 'clients'=>9999, 'durations'=>0, 'end_time'=>strtotime('+10 year')]; + $data = bin2hex(urlencode(json_encode($userinfo))); + return json(['status'=>true, 'data'=>$data]); + } + + //一键部署列表 + public function get_deplist(){ + $os = input('post.os'); + $json_arr = Plugins::get_deplist($os); + if(!$json_arr) return json([]); + return json($json_arr); + } + + //获取宝塔SSL列表 + public function get_ssl_list(){ + $data = bin2hex('[]'); + return json(['status'=>true, 'msg'=>'', 'data'=>$data]); + } + + public function return_success(){ + return json(['status'=>true, 'msg'=>1, 'data'=>(object)[]]); + } + + public function return_error(){ + return json(['status'=>false, 'msg'=>'不支持当前操作']); + } + + public function return_error2(){ + return json(['success'=>false, 'res'=>'不支持当前操作']); + } + + public function return_empty(){ + return ''; + } + + public function return_empty_array(){ + return json([]); + } + + public function return_page_data(){ + return json(['page'=>"
11/0从1-1000条共计0条数据
", 'data'=>[]]); + } + + public function btwaf_getspiders(){ + try{ + $result = Plugins::btwaf_getspiders(); + return json($result); + }catch(\Exception $e){ + return json(['status'=>false, 'msg'=>$e->getMessage()]); + } + } + + //检查黑白名单 + private function checklist(){ + if(config_get('whitelist') == 1){ + if(Db::name('white')->where('ip', $this->clientip)->where('enable', 1)->find()){ + return true; + } + return false; + }else{ + if(Db::name('black')->where('ip', $this->clientip)->where('enable', 1)->find()){ + return false; + } + return true; + } + } + + //下载大文件 + private function output_file($filepath, $filename){ + $filesize = filesize($filepath); + $filemd5 = md5_file($filepath); + + ob_clean(); + header("Content-Type: application/octet-stream"); + header("Content-Disposition: attachment; filename={$filename}.zip"); + header("Content-Length: {$filesize}"); + header("File-size: {$filesize}"); + header("Content-md5: {$filemd5}"); + + $read_buffer = 1024 * 100; + $handle = fopen($filepath, 'rb'); + $sum_buffer = 0; + while(!feof($handle) && $sum_buffer<$filesize) { + echo fread($handle, min($read_buffer, ($filesize - $sum_buffer) + 1)); + $sum_buffer += $read_buffer; + flush(); + } + fclose($handle); + exit; + } } \ No newline at end of file diff --git a/app/lib/BtPlugins.php b/app/lib/BtPlugins.php new file mode 100644 index 0000000..513be18 --- /dev/null +++ b/app/lib/BtPlugins.php @@ -0,0 +1,282 @@ +os = $os; + if($os == 'Windows'){ + $bt_url = config_get('wbt_url'); + $bt_key = config_get('wbt_key'); + }else{ + $bt_url = config_get('bt_url'); + $bt_key = config_get('bt_key'); + } + if(!$bt_url || !$bt_key) throw new Exception('请先配置好宝塔面板接口信息'); + $this->btapi = new Btapi($bt_url, $bt_key); + } + + //获取插件列表 + public function get_plugin_list(){ + $result = $this->btapi->get_plugin_list(); + if($result && isset($result['list']) && isset($result['type'])){ + if(empty($result['list']) || empty($result['type'])){ + throw new Exception('获取插件列表失败:插件列表为空'); + } + foreach($result['list'] as $k=>$v){ + if(in_array($v['name'], self::$block_plugins)) unset($result['list'][$k]); + } + return $result; + }else{ + throw new Exception('获取插件列表失败:'.(isset($result['msg'])?$result['msg']:'面板连接失败')); + } + } + + //下载插件(自动判断是否第三方) + public function download_plugin($plugin_name, $version, $plugin_info){ + if($plugin_info['type'] == 10 && isset($plugin_info['versions'][0]['download'])){ + if($plugin_info['price'] == 0){ + $this->btapi->create_plugin_other_order($plugin_info['id']); + } + $fname = $plugin_info['versions'][0]['download']; + $filemd5 = $plugin_info['versions'][0]['md5']; + $this->download_plugin_other($fname, $filemd5); + if(isset($plugin_info['min_image']) && strpos($plugin_info['min_image'], 'fname=')){ + $fname = substr($plugin_info['min_image'], strpos($plugin_info['min_image'], '?fname=')+7); + $this->download_plugin_other($fname); + } + }else{ + $this->download_plugin_package($plugin_name, $version); + } + } + + //下载插件包 + private function download_plugin_package($plugin_name, $version){ + $filepath = get_data_dir($this->os).'plugins/package/'.$plugin_name.'-'.$version.'.zip'; + $result = $this->btapi->get_plugin_filename($plugin_name, $version); + if($result && isset($result['status'])){ + if($result['status'] == true){ + $filename = $result['filename']; + $this->download_file($filename, $filepath); + if(file_exists($filepath)){ + $zip = new ZipArchive; + if ($zip->open($filepath) === true) + { + $zip->extractTo(get_data_dir($this->os).'plugins/folder/'.$plugin_name.'-'.$version); + $zip->close(); + $main_filepath = get_data_dir($this->os).'plugins/folder/'.$plugin_name.'-'.$version.'/'.$plugin_name.'/'.$plugin_name.'_main.py'; + if(file_exists($main_filepath) && filesize($main_filepath)>10){ + if(!strpos(file_get_contents($main_filepath), 'import ')){ //加密py文件,需要解密 + $this->decode_plugin_main($plugin_name, $version, $main_filepath); + $this->noauth_plugin_main($main_filepath); + $zip->open($filepath, ZipArchive::CREATE); + $zip->addFile($main_filepath, $plugin_name.'/'.$plugin_name.'_main.py'); + $zip->close(); + } + } + }else{ + unlink($filepath); + throw new Exception('插件包解压缩失败'); + } + return true; + }else{ + throw new Exception('下载插件包失败,本地文件不存在'); + } + }else{ + throw new Exception('下载插件包失败:'.($result['msg']?$result['msg']:'未知错误')); + } + }else{ + throw new Exception('下载插件包失败,接口返回错误'); + } + } + + //下载插件主程序文件 + public function download_plugin_main($plugin_name, $version){ + $filepath = get_data_dir($this->os).'plugins/main/'.$plugin_name.'-'.$version.'.dat'; + $result = $this->btapi->get_plugin_main_filename($plugin_name, $version); + if($result && isset($result['status'])){ + if($result['status'] == true){ + $filename = $result['filename']; + $this->download_file($filename, $filepath); + if(file_exists($filepath)){ + return true; + }else{ + throw new Exception('下载插件主程序文件失败,本地文件不存在'); + } + }else{ + throw new Exception('下载插件主程序文件失败:'.($result['msg']?$result['msg']:'未知错误')); + } + }else{ + throw new Exception('下载插件主程序文件失败,接口返回错误'); + } + } + + //解密并下载插件主程序文件 + private function decode_plugin_main($plugin_name, $version, $main_filepath){ + if($this->decode_plugin_main_local($main_filepath)) return true; + $result = $this->btapi->get_decode_plugin_main($plugin_name, $version); + if($result && isset($result['status'])){ + if($result['status'] == true){ + $filename = $result['filename']; + $this->download_file($filename, $main_filepath); + return true; + }else{ + throw new Exception('解密插件主程序文件失败:'.($result['msg']?$result['msg']:'未知错误')); + } + }else{ + throw new Exception('解密插件主程序文件失败,接口返回错误'); + } + } + + //本地解密插件主程序文件 + public function decode_plugin_main_local($main_filepath){ + $userinfo = $this->btapi->get_user_info(); + if(isset($userinfo['uid'])){ + $src = file_get_contents($main_filepath); + if($src===false)throw new Exception('文件打开失败'); + if(!$src || strpos($src, 'import ')!==false)return true; + $uid = $userinfo['uid']; + $serverid = $userinfo['serverid']; + $key = md5(substr($serverid, 10, 16).$uid.$serverid); + $iv = md5($key.$serverid); + $key = substr($key, 8, 16); + $iv = substr($iv, 8, 16); + $data_arr = explode("\n", $src); + $de_text = ''; + foreach($data_arr as $data){ + $data = trim($data); + if(!empty($data) && strlen($data)!=24){ + $tmp = openssl_decrypt($data, 'aes-128-cbc', $key, 0, $iv); + if($tmp) $de_text .= $tmp; + } + } + if(!empty($de_text) && strpos($de_text, 'import ')!==false){ + file_put_contents($main_filepath, $de_text); + return true; + } + return false; + }else{ + throw new Exception('解密插件主程序文件失败,获取用户信息失败'); + } + } + + //去除插件主程序文件授权校验 + private function noauth_plugin_main($main_filepath){ + $data = file_get_contents($main_filepath); + if(!$data) return false; + + $data = str_replace('\'http://www.bt.cn/api/panel/get_soft_list_test', 'public.GetConfigValue(\'home\')+\'/api/panel/get_soft_list_test', $data); + $data = str_replace('\'https://www.bt.cn/api/panel/get_soft_list_test', 'public.GetConfigValue(\'home\')+\'/api/panel/get_soft_list_test', $data); + $data = str_replace('\'http://www.bt.cn/api/panel/get_soft_list', 'public.GetConfigValue(\'home\')+\'/api/panel/get_soft_list', $data); + $data = str_replace('\'https://www.bt.cn/api/panel/get_soft_list', 'public.GetConfigValue(\'home\')+\'/api/panel/get_soft_list', $data); + $data = str_replace('\'http://www.bt.cn/api/panel/notpro', 'public.GetConfigValue(\'home\')+\'/api/panel/notpro', $data); + $data = str_replace('\'https://www.bt.cn/api/panel/notpro', 'public.GetConfigValue(\'home\')+\'/api/panel/notpro', $data); + + $data = str_replace('\'http://www.bt.cn/api/wpanel/get_soft_list_test', 'public.GetConfigValue(\'home\')+\'/api/wpanel/get_soft_list_test', $data); + $data = str_replace('\'https://www.bt.cn/api/wpanel/get_soft_list_test', 'public.GetConfigValue(\'home\')+\'/api/wpanel/get_soft_list_test', $data); + $data = str_replace('\'http://www.bt.cn/api/wpanel/get_soft_list', 'public.GetConfigValue(\'home\')+\'/api/wpanel/get_soft_list', $data); + $data = str_replace('\'https://www.bt.cn/api/wpanel/get_soft_list', 'public.GetConfigValue(\'home\')+\'/api/wpanel/get_soft_list', $data); + $data = str_replace('\'http://www.bt.cn/api/wpanel/notpro', 'public.GetConfigValue(\'home\')+\'/api/wpanel/notpro', $data); + $data = str_replace('\'https://www.bt.cn/api/wpanel/notpro', 'public.GetConfigValue(\'home\')+\'/api/wpanel/notpro', $data); + + $data = str_replace('\'http://www.bt.cn/api/bt_waf/getSpiders', 'public.GetConfigValue(\'home\')+\'/api/bt_waf/getSpiders', $data); + $data = str_replace('\'https://www.bt.cn/api/bt_waf/getSpiders', 'public.GetConfigValue(\'home\')+\'/api/bt_waf/getSpiders', $data); + $data = str_replace('\'http://www.bt.cn/api/bt_waf/addSpider', 'public.GetConfigValue(\'home\')+\'/api/bt_waf/addSpider', $data); + $data = str_replace('\'https://www.bt.cn/api/bt_waf/addSpider', 'public.GetConfigValue(\'home\')+\'/api/bt_waf/addSpider', $data); + $data = str_replace('\'https://www.bt.cn/api/bt_waf/getVulScanInfoList', 'public.GetConfigValue(\'home\')+\'/api/bt_waf/getVulScanInfoList', $data); + $data = str_replace('\'https://www.bt.cn/api/bt_waf/reportInterceptFail', 'public.GetConfigValue(\'home\')+\'/api/bt_waf/reportInterceptFail', $data); + $data = str_replace('\'https://www.bt.cn/api/v2/contact/nps/questions', 'public.GetConfigValue(\'home\')+\'/panel/notpro', $data); + $data = str_replace('\'https://www.bt.cn/api/v2/contact/nps/submit', 'public.GetConfigValue(\'home\')+\'/panel/notpro', $data); + + file_put_contents($main_filepath, $data); + } + + //下载插件其他文件 + private function download_plugin_other($fname, $filemd5 = null){ + $filepath = get_data_dir().'plugins/other/'.$fname; + @mkdir(dirname($filepath), 0777, true); + $result = $this->btapi->get_plugin_other_filename($fname); + if($result && isset($result['status'])){ + if($result['status'] == true){ + $filename = $result['filename']; + $this->download_file($filename, $filepath); + if(file_exists($filepath)){ + if($filemd5 && md5_file($filepath) != $filemd5){ + $msg = filesize($filepath) < 300 ? file_get_contents($filepath) : '插件文件MD5校验失败'; + @unlink($filepath); + throw new Exception($msg); + } + return true; + }else{ + throw new Exception('下载插件文件失败,本地文件不存在'); + } + }else{ + throw new Exception('下载插件文件失败:'.($result['msg']?$result['msg']:'未知错误')); + } + }else{ + throw new Exception('下载插件文件失败,接口返回错误'); + } + } + + //下载文件 + private function download_file($filename, $filepath){ + try{ + $this->btapi->download($filename, $filepath); + }catch(Exception $e){ + @unlink($filepath); + //宝塔bug小文件下载失败,改用base64下载 + $result = $this->btapi->get_file($filename); + if($result && isset($result['status']) && $result['status']==true){ + $filedata = base64_decode($result['data']); + if(strlen($filedata) < 4096 && substr($filedata,0,1)=='{' && substr($filedata,-1,1)=='}'){ + $arr = json_decode($filedata, true); + if($arr){ + throw new Exception('获取文件失败:'.($arr['msg']?$arr['msg']:'未知错误')); + } + } + if(!$filedata){ + throw new Exception('获取文件失败:文件内容为空'); + } + file_put_contents($filepath, $filedata); + }elseif($result){ + throw new Exception('获取文件失败:'.($result['msg']?$result['msg']:'未知错误')); + }else{ + throw new Exception('获取文件失败:未知错误'); + } + } + } + + //获取一键部署列表 + public function get_deplist(){ + $result = $this->btapi->get_deplist(); + if($result && isset($result['list']) && isset($result['type'])){ + if(empty($result['list']) || empty($result['type'])){ + throw new Exception('获取一键部署列表失败:一键部署列表为空'); + } + return $result; + }else{ + throw new Exception('获取一键部署列表失败:'.(isset($result['msg'])?$result['msg']:'面板连接失败')); + } + } + + //获取蜘蛛IP列表 + public function btwaf_getspiders(){ + $result = $this->btapi->btwaf_getspiders(); + if(isset($result['status']) && $result['status']){ + return $result['data']; + }else{ + throw new Exception(isset($result['msg'])?$result['msg']:'获取失败'); + } + } + +} \ No newline at end of file diff --git a/app/lib/Plugins.php b/app/lib/Plugins.php index e8b055e..201621d 100644 --- a/app/lib/Plugins.php +++ b/app/lib/Plugins.php @@ -1,350 +1,154 @@ -get_plugin_list(); - if($result && isset($result['list']) && isset($result['type'])){ - if(empty($result['list']) || empty($result['type'])){ - throw new Exception('获取插件列表失败:插件列表为空'); - } - self::save_plugin_list($result, $os); - }else{ - throw new Exception('获取插件列表失败:'.(isset($result['msg'])?$result['msg']:'面板连接失败')); - } - } - - //保存插件列表 - private static function save_plugin_list($data, $os){ - $data['ip'] = '127.0.0.1'; - $data['serverid'] = ''; - $data['beta'] = 0; - $data['uid'] = 1; - $data['skey'] = ''; - $list = []; - foreach($data['list'] as $plugin){ - if(isset($plugin['endtime'])) $plugin['endtime'] = 0; - $list[] = $plugin; - } - $data['list'] = $list; - $data['ltd'] = strtotime('+10 year'); - $json_file = get_data_dir($os).'config/plugin_list.json'; - if(!file_put_contents($json_file, json_encode($data))){ - throw new Exception('保存插件列表失败,文件无写入权限'); - } - } - - //获取插件列表 - public static function get_plugin_list($os = 'Linux'){ - $json_file = get_data_dir($os).'config/plugin_list.json'; - if(file_exists($json_file)){ - $data = file_get_contents($json_file); - $json_arr = json_decode($data, true); - if($json_arr){ - return $json_arr; - } - } - return false; - } - - //获取一个插件信息 - public static function get_plugin_info($name, $os = 'Linux'){ - $json_arr = self::get_plugin_list($os); - if(!$json_arr) return null; - foreach($json_arr['list'] as $plugin){ - if($plugin['name'] == $name){ - return $plugin; - } - } - return null; - } - - //下载插件(自动判断是否第三方) - public static function download_plugin($plugin_name, $version, $os = 'Linux'){ - $plugin_info = Plugins::get_plugin_info($plugin_name, $os); - if(!$plugin_info) throw new Exception('未找到该插件信息'); - if($plugin_info['type'] == 10 && isset($plugin_info['versions'][0]['download'])){ - if($plugin_info['price'] == 0){ - $btapi = self::get_btapi($os); - $btapi->create_plugin_other_order($plugin_info['id']); - } - $fname = $plugin_info['versions'][0]['download']; - $filemd5 = $plugin_info['versions'][0]['md5']; - Plugins::download_plugin_other($fname, $filemd5, $os); - if(isset($plugin_info['min_image']) && strpos($plugin_info['min_image'], 'fname=')){ - $fname = substr($plugin_info['min_image'], strpos($plugin_info['min_image'], '?fname=')+7); - Plugins::download_plugin_other($fname, null, $os); - } - }else{ - Plugins::download_plugin_package($plugin_name, $version, $os); - } - } - - //下载插件包 - public static function download_plugin_package($plugin_name, $version, $os = 'Linux'){ - $filepath = get_data_dir($os).'plugins/package/'.$plugin_name.'-'.$version.'.zip'; - $btapi = self::get_btapi($os); - $result = $btapi->get_plugin_filename($plugin_name, $version); - if($result && isset($result['status'])){ - if($result['status'] == true){ - $filename = $result['filename']; - self::download_file($btapi, $filename, $filepath); - if(file_exists($filepath)){ - $zip = new ZipArchive; - if ($zip->open($filepath) === true) - { - $zip->extractTo(get_data_dir($os).'plugins/folder/'.$plugin_name.'-'.$version); - $zip->close(); - $main_filepath = get_data_dir($os).'plugins/folder/'.$plugin_name.'-'.$version.'/'.$plugin_name.'/'.$plugin_name.'_main.py'; - if(file_exists($main_filepath) && filesize($main_filepath)>10){ - if(!strpos(file_get_contents($main_filepath), 'import ')){ //加密py文件,需要解密 - self::decode_plugin_main($plugin_name, $version, $main_filepath, $os); - self::noauth_plugin_main($main_filepath); - $zip->open($filepath, ZipArchive::CREATE); - $zip->addFile($main_filepath, $plugin_name.'/'.$plugin_name.'_main.py'); - $zip->close(); - } - } - }else{ - throw new Exception('插件包解压缩失败'); - } - return true; - }else{ - throw new Exception('下载插件包失败,本地文件不存在'); - } - }else{ - throw new Exception('下载插件包失败:'.($result['msg']?$result['msg']:'未知错误')); - } - }else{ - throw new Exception('下载插件包失败,接口返回错误'); - } - } - - //下载插件主程序文件 - public static function download_plugin_main($plugin_name, $version, $os = 'Linux'){ - $filepath = get_data_dir($os).'plugins/main/'.$plugin_name.'-'.$version.'.dat'; - $btapi = self::get_btapi($os); - $result = $btapi->get_plugin_main_filename($plugin_name, $version); - if($result && isset($result['status'])){ - if($result['status'] == true){ - $filename = $result['filename']; - self::download_file($btapi, $filename, $filepath); - if(file_exists($filepath)){ - return true; - }else{ - throw new Exception('下载插件主程序文件失败,本地文件不存在'); - } - }else{ - throw new Exception('下载插件主程序文件失败:'.($result['msg']?$result['msg']:'未知错误')); - } - }else{ - throw new Exception('下载插件主程序文件失败,接口返回错误'); - } - } - - //解密并下载插件主程序文件 - public static function decode_plugin_main($plugin_name, $version, $main_filepath, $os = 'Linux'){ - if(self::decode_plugin_main_local($main_filepath, $os)) return true; - $btapi = self::get_btapi($os); - $result = $btapi->get_decode_plugin_main($plugin_name, $version); - if($result && isset($result['status'])){ - if($result['status'] == true){ - $filename = $result['filename']; - self::download_file($btapi, $filename, $main_filepath); - return true; - }else{ - throw new Exception('解密插件主程序文件失败:'.($result['msg']?$result['msg']:'未知错误')); - } - }else{ - throw new Exception('解密插件主程序文件失败,接口返回错误'); - } - } - - //本地解密插件主程序文件 - public static function decode_plugin_main_local($main_filepath, $os = 'Linux'){ - $btapi = self::get_btapi($os); - $userinfo = $btapi->get_user_info(); - if(isset($userinfo['uid'])){ - $src = file_get_contents($main_filepath); - if($src===false)throw new Exception('文件打开失败'); - if(!$src || strpos($src, 'import ')!==false)return true; - $uid = $userinfo['uid']; - $serverid = $userinfo['serverid']; - $key = md5(substr($serverid, 10, 16).$uid.$serverid); - $iv = md5($key.$serverid); - $key = substr($key, 8, 16); - $iv = substr($iv, 8, 16); - $data_arr = explode("\n", $src); - $de_text = ''; - foreach($data_arr as $data){ - $data = trim($data); - if(!empty($data) && strlen($data)!=24){ - $tmp = openssl_decrypt($data, 'aes-128-cbc', $key, 0, $iv); - if($tmp) $de_text .= $tmp; - } - } - if(!empty($de_text) && strpos($de_text, 'import ')!==false){ - file_put_contents($main_filepath, $de_text); - return true; - } - return false; - }else{ - throw new Exception('解密插件主程序文件失败,获取用户信息失败'); - } - } - - public static function decode_module_file($filepath){ - $src = file_get_contents($filepath); - if($src===false)throw new Exception('文件打开失败'); - if(!$src || strpos($src, 'import ')!==false)return 0; - $key = 'Z2B87NEAS2BkxTrh'; - $iv = 'WwadH66EGWpeeTT6'; - $data_arr = explode("\n", $src); - $de_text = ''; - foreach($data_arr as $data){ - $data = trim($data); - if(!empty($data)){ - $tmp = openssl_decrypt($data, 'aes-128-cbc', $key, 0, $iv); - if($tmp) $de_text .= $tmp; - } - } - if(!empty($de_text) && strpos($de_text, 'import ')!==false){ - file_put_contents($filepath, $de_text); - return 1; - } - return 2; - } - - //去除插件主程序文件授权校验 - public static function noauth_plugin_main($main_filepath){ - $data = file_get_contents($main_filepath); - if(!$data) return false; - - $data = str_replace('\'http://www.bt.cn/api/panel/get_soft_list_test', 'public.GetConfigValue(\'home\')+\'/api/panel/get_soft_list_test', $data); - $data = str_replace('\'https://www.bt.cn/api/panel/get_soft_list_test', 'public.GetConfigValue(\'home\')+\'/api/panel/get_soft_list_test', $data); - $data = str_replace('\'http://www.bt.cn/api/panel/get_soft_list', 'public.GetConfigValue(\'home\')+\'/api/panel/get_soft_list', $data); - $data = str_replace('\'https://www.bt.cn/api/panel/get_soft_list', 'public.GetConfigValue(\'home\')+\'/api/panel/get_soft_list', $data); - $data = str_replace('\'http://www.bt.cn/api/panel/notpro', 'public.GetConfigValue(\'home\')+\'/api/panel/notpro', $data); - $data = str_replace('\'https://www.bt.cn/api/panel/notpro', 'public.GetConfigValue(\'home\')+\'/api/panel/notpro', $data); - - $data = str_replace('\'http://www.bt.cn/api/wpanel/get_soft_list_test', 'public.GetConfigValue(\'home\')+\'/api/wpanel/get_soft_list_test', $data); - $data = str_replace('\'https://www.bt.cn/api/wpanel/get_soft_list_test', 'public.GetConfigValue(\'home\')+\'/api/wpanel/get_soft_list_test', $data); - $data = str_replace('\'http://www.bt.cn/api/wpanel/get_soft_list', 'public.GetConfigValue(\'home\')+\'/api/wpanel/get_soft_list', $data); - $data = str_replace('\'https://www.bt.cn/api/wpanel/get_soft_list', 'public.GetConfigValue(\'home\')+\'/api/wpanel/get_soft_list', $data); - $data = str_replace('\'http://www.bt.cn/api/wpanel/notpro', 'public.GetConfigValue(\'home\')+\'/api/wpanel/notpro', $data); - $data = str_replace('\'https://www.bt.cn/api/wpanel/notpro', 'public.GetConfigValue(\'home\')+\'/api/wpanel/notpro', $data); - - $data = str_replace('\'http://www.bt.cn/api/bt_waf/getSpiders', 'public.GetConfigValue(\'home\')+\'/api/bt_waf/getSpiders', $data); - $data = str_replace('\'https://www.bt.cn/api/bt_waf/getSpiders', 'public.GetConfigValue(\'home\')+\'/api/bt_waf/getSpiders', $data); - - file_put_contents($main_filepath, $data); - } - - //下载插件其他文件 - public static function download_plugin_other($fname, $filemd5 = null, $os = 'Linux'){ - $filepath = get_data_dir().'plugins/other/'.$fname; - @mkdir(dirname($filepath), 0777, true); - $btapi = self::get_btapi($os); - $result = $btapi->get_plugin_other_filename($fname); - if($result && isset($result['status'])){ - if($result['status'] == true){ - $filename = $result['filename']; - self::download_file($btapi, $filename, $filepath); - if(file_exists($filepath)){ - if($filemd5 && md5_file($filepath) != $filemd5){ - $msg = filesize($filepath) < 300 ? file_get_contents($filepath) : '插件文件MD5校验失败'; - @unlink($filepath); - throw new Exception($msg); - } - return true; - }else{ - throw new Exception('下载插件文件失败,本地文件不存在'); - } - }else{ - throw new Exception('下载插件文件失败:'.($result['msg']?$result['msg']:'未知错误')); - } - }else{ - throw new Exception('下载插件文件失败,接口返回错误'); - } - } - - //下载文件 - private static function download_file($btapi, $filename, $filepath){ - try{ - $btapi->download($filename, $filepath); - }catch(Exception $e){ - @unlink($filepath); - //宝塔bug小文件下载失败,改用base64下载 - $result = $btapi->get_file($filename); - if($result && isset($result['status']) && $result['status']==true){ - $filedata = base64_decode($result['data']); - if(strlen($filedata) < 4096 && substr($filedata,0,1)=='{' && substr($filedata,-1,1)=='}'){ - $arr = json_decode($filedata, true); - if($arr){ - throw new Exception('获取文件失败:'.($arr['msg']?$arr['msg']:'未知错误')); - } - } - if(!$filedata){ - throw new Exception('获取文件失败:文件内容为空'); - } - file_put_contents($filepath, $filedata); - }elseif($result){ - throw new Exception('获取文件失败:'.($result['msg']?$result['msg']:'未知错误')); - }else{ - throw new Exception('获取文件失败:未知错误'); - } - } - } - - //刷新一键部署列表 - public static function refresh_deplist($os = 'Linux'){ - $btapi = self::get_btapi($os); - $result = $btapi->get_deplist(); - if($result && isset($result['list']) && isset($result['type'])){ - if(empty($result['list']) || empty($result['type'])){ - throw new Exception('获取一键部署列表失败:一键部署列表为空'); - } - $json_file = get_data_dir($os).'config/deployment_list.json'; - if(!file_put_contents($json_file, json_encode($result))){ - throw new Exception('保存一键部署列表失败,文件无写入权限'); - } - }else{ - throw new Exception('获取一键部署列表失败:'.(isset($result['msg'])?$result['msg']:'面板连接失败')); - } - } - - //获取一键部署列表 - public static function get_deplist($os = 'Linux'){ - $json_file = get_data_dir($os).'config/deployment_list.json'; - if(file_exists($json_file)){ - $data = file_get_contents($json_file); - $json_arr = json_decode($data, true); - if($json_arr){ - return $json_arr; - } - } - return false; - } - +get_plugin_list(); + self::save_plugin_list($result, $os); + } + + //保存插件列表 + private static function save_plugin_list($data, $os){ + $data['ip'] = '127.0.0.1'; + $data['serverid'] = ''; + $data['beta'] = 0; + $data['uid'] = 1; + $data['skey'] = ''; + $list = []; + foreach($data['list'] as $plugin){ + if(isset($plugin['endtime'])) $plugin['endtime'] = 0; + $list[] = $plugin; + } + $data['list'] = $list; + $data['ltd'] = strtotime('+10 year'); + $json_file = get_data_dir($os).'config/plugin_list.json'; + if(!file_put_contents($json_file, json_encode($data))){ + throw new Exception('保存插件列表失败,文件无写入权限'); + } + } + + //获取插件列表 + public static function get_plugin_list($os = 'Linux'){ + $json_file = get_data_dir($os).'config/plugin_list.json'; + if(file_exists($json_file)){ + $data = file_get_contents($json_file); + $json_arr = json_decode($data, true); + if($json_arr){ + return $json_arr; + } + } + return false; + } + + //获取一个插件信息 + public static function get_plugin_info($name, $os = 'Linux'){ + $json_arr = self::get_plugin_list($os); + if(!$json_arr) return null; + foreach($json_arr['list'] as $plugin){ + if($plugin['name'] == $name){ + return $plugin; + } + } + return null; + } + + //下载插件(自动判断是否第三方) + public static function download_plugin($plugin_name, $version, $os = 'Linux'){ + $plugin_info = Plugins::get_plugin_info($plugin_name, $os); + if(!$plugin_info) throw new Exception('未找到该插件信息'); + $btapi = self::get_btapi($os); + $btapi->download_plugin($plugin_name, $version, $plugin_info); + } + + //下载插件主程序文件 + public static function download_plugin_main($plugin_name, $version, $os = 'Linux'){ + $btapi = self::get_btapi($os); + $btapi->download_plugin_main($plugin_name, $version); + } + + //本地解密插件主程序文件 + public static function decode_plugin_main_local($main_filepath, $os = 'Linux'){ + $btapi = new BtPlugins($os); + return $btapi->decode_plugin_main_local($main_filepath); + } + + //本地解密模块文件 + public static function decode_module_file($filepath){ + $src = file_get_contents($filepath); + if($src===false)throw new Exception('文件打开失败'); + if(!$src || strpos($src, 'import ')!==false)return 0; + $key = 'Z2B87NEAS2BkxTrh'; + $iv = 'WwadH66EGWpeeTT6'; + $data_arr = explode("\n", $src); + $de_text = ''; + foreach($data_arr as $data){ + $data = trim($data); + if(!empty($data)){ + $tmp = openssl_decrypt($data, 'aes-128-cbc', $key, 0, $iv); + if($tmp) $de_text .= $tmp; + } + } + if(!empty($de_text) && strpos($de_text, 'import ')!==false){ + file_put_contents($filepath, $de_text); + return 1; + } + return 2; + } + + //刷新一键部署列表 + public static function refresh_deplist($os = 'Linux'){ + $btapi = self::get_btapi($os); + $result = $btapi->get_deplist(); + $json_file = get_data_dir($os).'config/deployment_list.json'; + if(!file_put_contents($json_file, json_encode($result))){ + throw new Exception('保存一键部署列表失败,文件无写入权限'); + } + } + + //获取一键部署列表 + public static function get_deplist($os = 'Linux'){ + $json_file = get_data_dir($os).'config/deployment_list.json'; + if(file_exists($json_file)){ + $data = file_get_contents($json_file); + $json_arr = json_decode($data, true); + if($json_arr){ + return $json_arr; + } + } + return false; + } + + //获取蜘蛛IP列表 + public static function btwaf_getspiders(){ + $result = cache('btwaf_getspiders'); + if($result){ + return $result; + } + $btapi = self::get_btapi('Linux'); + $result = $btapi->btwaf_getspiders(); + cache('btwaf_getspiders', $result, 3600 * 24 * 3); + return $result; + } + } \ No newline at end of file diff --git a/app/lib/ThirdPlugins.php b/app/lib/ThirdPlugins.php new file mode 100644 index 0000000..af9bf37 --- /dev/null +++ b/app/lib/ThirdPlugins.php @@ -0,0 +1,203 @@ +os = $os; + $url = $os == 'Windows' ? config_get('wbt_surl') : config_get('bt_surl'); + if(!$url) throw new Exception('请先配置好第三方云端首页URL'); + $this->url = $url; + } + + //获取插件列表 + public function get_plugin_list() + { + $url = $this->os == 'Windows' ? $this->url . 'api/wpanel/get_soft_list' : $this->url . 'api/panel/get_soft_list'; + $res = $this->curl($url); + $result = json_decode($res, true); + if($result && isset($result['list']) && isset($result['type'])){ + if(empty($result['list']) || empty($result['type'])){ + throw new Exception('获取插件列表失败:插件列表为空'); + } + return $result; + }else{ + throw new Exception('获取插件列表失败:'.(isset($result['msg'])?$result['msg']:'第三方云端连接失败')); + } + } + + //下载插件(自动判断是否第三方) + public function download_plugin($plugin_name, $version, $plugin_info){ + if($plugin_info['type'] == 10 && isset($plugin_info['versions'][0]['download'])){ + $fname = $plugin_info['versions'][0]['download']; + $filemd5 = $plugin_info['versions'][0]['md5']; + $this->download_plugin_other($fname, $filemd5); + if(isset($plugin_info['min_image']) && strpos($plugin_info['min_image'], 'fname=')){ + $fname = substr($plugin_info['min_image'], strpos($plugin_info['min_image'], '?fname=')+7); + $this->download_plugin_other($fname); + } + }else{ + $this->download_plugin_package($plugin_name, $version); + } + } + + //下载插件包 + private function download_plugin_package($plugin_name, $version){ + $filepath = get_data_dir($this->os).'plugins/package/'.$plugin_name.'-'.$version.'.zip'; + + $url = $this->url . 'down/download_plugin'; + $post = ['name'=>$plugin_name, 'version'=>$version, 'os'=>$this->os]; + $this->curl_download($url, $post, $filepath); + + if(file_exists($filepath)){ + $handle = fopen($filepath, "rb"); + $file_head = fread($handle, 4); + fclose($handle); + if(bin2hex($file_head) === '504b0304'){ + $zip = new ZipArchive; + if ($zip->open($filepath) === true) + { + $zip->extractTo(get_data_dir($this->os).'plugins/folder/'.$plugin_name.'-'.$version); + $zip->close(); + return true; + }else{ + @unlink($filepath); + throw new Exception('插件包解压缩失败'); + } + }else{ + $handle = fopen($filepath, "rb"); + $errmsg = htmlspecialchars(fgets($handle)); + fclose($handle); + @unlink($filepath); + throw new Exception('下载插件包失败:'.($errmsg?$errmsg:'未知错误')); + } + }else{ + throw new Exception('下载插件包失败,本地文件不存在'); + } + } + + //下载插件主程序文件 + public function download_plugin_main($plugin_name, $version){ + $filepath = get_data_dir($this->os).'plugins/main/'.$plugin_name.'-'.$version.'.dat'; + + $url = $this->url . 'down/download_plugin_main'; + $post = ['name'=>$plugin_name, 'version'=>$version, 'os'=>$this->os]; + $this->curl_download($url, $post, $filepath); + + if(file_exists($filepath)){ + $line = count(file($filepath)); + if($line > 3) return true; + + $handle = fopen($filepath, "rb"); + $errmsg = htmlspecialchars(fgets($handle)); + fclose($handle); + @unlink($filepath); + throw new Exception('下载插件主程序文件失败:'.($errmsg?$errmsg:'未知错误')); + }else{ + throw new Exception('下载插件主程序文件失败,本地文件不存在'); + } + } + + //下载插件其他文件 + private function download_plugin_other($fname, $filemd5 = null){ + $filepath = get_data_dir().'plugins/other/'.$fname; + @mkdir(dirname($filepath), 0777, true); + + $url = $this->url . 'api/Pluginother/get_file?fname='.urlencode($fname); + $this->curl_download($url, false, $filepath); + + if(file_exists($filepath)){ + $handle = fopen($filepath, "rb"); + $file_head = fread($handle, 15); + fclose($handle); + if($file_head === '{"status":false'){ + $res = file_get_contents($filepath); + $result = json_decode($res, true); + @unlink($filepath); + throw new Exception('下载插件文件失败:'.($result?$result['msg']:'未知错误')); + } + if($filemd5 && md5_file($filepath) != $filemd5){ + $msg = filesize($filepath) < 300 ? file_get_contents($filepath) : '插件文件MD5校验失败'; + @unlink($filepath); + throw new Exception($msg); + } + return true; + }else{ + throw new Exception('下载插件文件失败,本地文件不存在'); + } + } + + //获取一键部署列表 + public function get_deplist(){ + $url = $this->url . 'api/panel/get_deplist'; + $post = ['os' => $this->os]; + $res = $this->curl($url, http_build_query($post)); + $result = json_decode($res, true); + if($result && isset($result['list']) && isset($result['type'])){ + if(empty($result['list']) || empty($result['type'])){ + throw new Exception('获取一键部署列表失败:一键部署列表为空'); + } + return $result; + }else{ + throw new Exception('获取一键部署列表失败:'.(isset($result['msg'])?$result['msg']:'第三方云端连接失败')); + } + } + + //获取蜘蛛IP列表 + public function btwaf_getspiders(){ + $url = $this->url . 'api/bt_waf/getSpiders'; + $res = $this->curl($url); + $result = json_decode($res, true); + if(isset($result['status']) && !$result['status']){ + throw new Exception(isset($result['msg'])?$result['msg']:'获取失败'); + }else{ + return $result; + } + } + + private function curl($url, $post = 0){ + $ua = "Mozilla/5.0 (BtCloud; ".request()->root(true).")"; + return get_curl($url, $post, 0, 0, 0, $ua); + } + + private function curl_download($url, $post, $localpath, $timeout = 300) + { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); + $fp = fopen($localpath, 'w+'); + curl_setopt($ch, CURLOPT_FILE, $fp); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (BtCloud; ".request()->root(true).")"); + if($post){ + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, $post); + } + curl_exec($ch); + if (curl_errno($ch)) { + $message = curl_error($ch); + curl_close($ch); + fclose($fp); + throw new Exception('下载文件失败:'.$message); + } + $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + if($httpcode>299){ + curl_close($ch); + fclose($fp); + throw new Exception('下载文件失败:HTTPCODE-'.$httpcode); + } + curl_close($ch); + fclose($fp); + return true; + } + +} \ No newline at end of file diff --git a/app/script/convert.sh b/app/script/convert.sh index a22d314..56287cc 100644 --- a/app/script/convert.sh +++ b/app/script/convert.sh @@ -1,8 +1,8 @@ #!/bin/bash -Linux_Version="8.0.1" +Linux_Version="8.0.2" Windows_Version="7.9.0" -Btm_Version="2.2.8" +Btm_Version="2.2.9" FILES=( public/install/src/panel6.zip diff --git a/app/view/admin/layout.html b/app/view/admin/layout.html index b5a3c09..47fc92a 100644 --- a/app/view/admin/layout.html +++ b/app/view/admin/layout.html @@ -1,73 +1,74 @@ - - - - - - - {block name="title"}标题{/block} - - - - - - - - - -
- {block name="main"}主内容{/block} - + + + + + + + {block name="title"}标题{/block} + + + + + + + + + + + {block name="main"}主内容{/block} + \ No newline at end of file diff --git a/app/view/admin/list.html b/app/view/admin/list.html index 4fe2cd1..7da4194 100644 --- a/app/view/admin/list.html +++ b/app/view/admin/list.html @@ -1,209 +1,209 @@ -{extend name="admin/layout" /} -{block name="title"}黑白名单{/block} -{block name="main"} - -
-
- - - -{if $type=='black' && config_get('whitelist')=='1'} -
提示:当前为白名单模式,黑名单列表里面的记录不会生效。
-{/if} -{if $type=='white' && config_get('whitelist')=='0'} -
提示:当前未开启白名单模式,白名单列表里面的记录不会生效。
-{/if} -{if $type=='black'} -
添加到黑名单列表中的服务器IP将无法使用此云端
-{/if} -{if $type=='white'} -
只有添加到白名单列表中的服务器IP才可以使用此云端
-{/if} - -
-
-
- - -
-
-   - 重置  - 添加  -
-
-
- - -
-
-
- - - - - +{extend name="admin/layout" /} +{block name="title"}黑白名单{/block} +{block name="main"} + +
+
+ + + +{if $type=='black' && config_get('whitelist')=='1'} +
提示:当前为白名单模式,黑名单列表里面的记录不会生效。
+{/if} +{if $type=='white' && config_get('whitelist')=='0'} +
提示:当前未开启白名单模式,白名单列表里面的记录不会生效。
+{/if} +{if $type=='black'} +
添加到黑名单列表中的服务器IP将无法使用此云端
+{/if} +{if $type=='white'} +
只有添加到白名单列表中的服务器IP才可以使用此云端
+{/if} + +
+
+
+ + +
+
+   + 重置  + 添加  +
+
+
+ + +
+
+
+ + + + + {/block} \ No newline at end of file diff --git a/app/view/admin/log.html b/app/view/admin/log.html index 509e5ee..32969b3 100644 --- a/app/view/admin/log.html +++ b/app/view/admin/log.html @@ -1,74 +1,74 @@ -{extend name="admin/layout" /} -{block name="title"}操作日志{/block} -{block name="main"} - -
-
- -
-
-
- - -
-
-   - 重置  -
-
-
- - -
-
-
- - - - - +{extend name="admin/layout" /} +{block name="title"}操作日志{/block} +{block name="main"} + +
+
+ +
+
+
+ + +
+
+   + 重置  +
+
+
+ + +
+
+
+ + + + + {/block} \ No newline at end of file diff --git a/app/view/admin/plugins.html b/app/view/admin/plugins.html index 8d67fa9..21fa83d 100644 --- a/app/view/admin/plugins.html +++ b/app/view/admin/plugins.html @@ -1,214 +1,276 @@ -{extend name="admin/layout" /} -{block name="title"}插件列表{/block} -{block name="main"} - - -
-
- -
-
-
- - -
-
- -
-
-   - 重置  - 重新获取  - -
-
-
- - -
-
-
- - - - - +{extend name="admin/layout" /} +{block name="title"}插件列表{/block} +{block name="main"} + + +
+
+ +
+
+
+ + +
+
+ +
+
+   + 重置  + 刷新列表  +   + +
+
+
+ + +
+
+
+ + + + + {/block} \ No newline at end of file diff --git a/app/view/admin/pluginswin.html b/app/view/admin/pluginswin.html index 351347e..8c8b06c 100644 --- a/app/view/admin/pluginswin.html +++ b/app/view/admin/pluginswin.html @@ -1,214 +1,276 @@ -{extend name="admin/layout" /} -{block name="title"}插件列表{/block} -{block name="main"} - - -
-
- -
-
-
- - -
-
- -
-
-   - 重置  - 重新获取  - -
-
-
- - -
-
-
- - - - - +{extend name="admin/layout" /} +{block name="title"}插件列表{/block} +{block name="main"} + + +
+
+ +
+
+
+ + +
+
+ +
+
+   + 重置  + 刷新列表  +   + +
+
+
+ + +
+
+
+ + + + + {/block} \ No newline at end of file diff --git a/app/view/admin/record.html b/app/view/admin/record.html index ac963c5..d6d8ea7 100644 --- a/app/view/admin/record.html +++ b/app/view/admin/record.html @@ -1,67 +1,67 @@ -{extend name="admin/layout" /} -{block name="title"}使用记录{/block} -{block name="main"} - -
-
- -
-
-
- - -
-
-   - 重置  -
-
-
- - -
-
-
- - - - - +{extend name="admin/layout" /} +{block name="title"}使用记录{/block} +{block name="main"} + +
+
+ +
+
+
+ + +
+
+   + 重置  +
+
+
+ + +
+
+
+ + + + + {/block} \ No newline at end of file diff --git a/app/view/admin/set.html b/app/view/admin/set.html index 154000f..77a1b61 100644 --- a/app/view/admin/set.html +++ b/app/view/admin/set.html @@ -1,344 +1,451 @@ -{extend name="admin/layout" /} -{block name="title"}系统设置{/block} -{block name="main"} -
-{if $mod=='sys'} -
-
-

系统基本设置

-
-
-
-
- - 开启白名单模式后,只有在白名单列表中的服务器IP才能使用此云端 -
-
- - - 页面地址:/download,开启后可以公开访问,否则只能管理员访问 -
-
- - - 用于一键更新脚本获取最新版本号,以及检测更新接口。并确保已在/public/install/update/放置对应版本更新包 -
-
- - - 用于检测更新接口返回 -
-
- - - 用于检测更新接口返回 -
-
- - - 用于一键更新脚本获取最新版本号,以及检测更新接口。并确保已在/public/win/panel/放置对应版本更新包 -
-
- - - 用于检测更新接口返回 -
-
- - - 用于检测更新接口返回 -
-
- - - 用于一键更新脚本获取最新版本号,以及检测更新接口。并确保已在/public/install/src/放置对应版本更新包 -
-
- - -
-
- - -
-
- -
-
-
-
-
-
-
-

宝塔Linux面板接口设置

-
-
-

以下宝塔面板请使用官方最新脚本安装并绑定账号,用于获取最新插件列表及插件包

-

下载专用插件(Linux),在面板【软件商店】->【第三方应用】,点击【导入插件】,导入该专用插件。

-
-
- - 填写规则如:http://192.168.1.1:8888 ,不要带其他后缀 -
-
- - -
-
- - -
-
-
-
-
-

宝塔Windows面板接口设置

-
-
-

以下宝塔面板请使用官方最新脚本安装并绑定账号,用于获取最新插件列表及插件包

-

下载专用插件(Win),在面板【软件商店】->【第三方应用】,点击【导入插件】,导入该专用插件。

-
-
- - 填写规则如:http://192.168.1.1:8888 ,不要带其他后缀 -
-
- - -
-
- - -
-
-
-
-
-{elseif $mod=='task'} -
-
-

定时任务说明

-
-
-
使用以下命令可以从宝塔官方获取最新的插件列表并批量下载插件包(增量更新)。
你也可以将此命令添加到crontab以使此云端的插件保持最新,建议1天执行1次。
-
使用命令执行之后,可能会导致 /data 目录下文件权限不对,后台插件列表下载插件覆盖会报错,需要手动循环设置 /data 目录权限。
-
上次运行时间:{$runtime|raw}
-
php {:app()->getRootPath()}think updateall

-
-
-
-
-
-
-

定时任务设置

-
-
-
-
- (批量下载不包含所有第三方插件,第三方插件需要去手动下载。) -
-
-
- (批量下载不包含所有第三方插件,第三方插件需要去手动下载。) -
-
- -
-
-
-
-
-{elseif $mod=='account'} -
-
-

管理账号设置

-
-
-
-
- -
-
- - -
-
- - -
-
- - -
-
- -
- 清理缓存 -
-
-
-{elseif $mod=='tools'} -
-
-

批量替换工具

-
-
-
使用以下命令可以将bt安装包、更新包和脚本文件里面的http://www.example.com批量替换成当前网址{:request()->root(true)},每次更新版本后只需要执行一次即可。
-
cd {:app()->getRootPath()}app/script && chmod +x convert.sh && ./convert.sh {:app()->getRootPath()} {:request()->root(true)}

-
-
-
-
-

清理旧版本插件工具

-
-
-
使用以下命令可清理旧版本的插件文件,以释放空间占用。
-
php {:app()->getRootPath()}think clean

-
-
-
-{/if} - - +{extend name="admin/layout" /} +{block name="title"}系统设置{/block} +{block name="main"} +
+{if $mod=='sys'} +
+
+

系统基本设置

+
+
+
+
+ + 开启白名单模式后,只有在白名单列表中的服务器IP才能使用此云端 +
+
+ + + 页面地址:/download,开启后可以公开访问,否则只能管理员访问 +
+
+ +
+
+
+
+
+

Linux面板版本设置

+
+
+
+ + + 用于一键更新脚本获取最新版本号,以及检测更新接口。并确保已在/public/install/update/放置对应版本更新包 +
+
+ + + 用于检测更新接口返回 +
+
+ + + 用于检测更新接口返回 +
+
+ +
+
+
+
+
+
+
+

Windows面板版本设置

+
+
+
+ + + 用于一键更新脚本获取最新版本号,以及检测更新接口。并确保已在/public/win/panel/放置对应版本更新包 +
+
+ + + 用于检测更新接口返回 +
+
+ + + 用于检测更新接口返回 +
+
+ +
+
+
+
+
+

云监控版本设置

+
+
+
+ + + 用于一键更新脚本获取最新版本号,以及检测更新接口。并确保已在/public/install/src/放置对应版本更新包 +
+
+ + +
+
+ + +
+
+ +
+
+
+
+
+{elseif $mod=='api'} +
+
+

宝塔Linux面板接口设置

+
+
+
+
+ +

+
+

以下宝塔面板请使用官方最新脚本安装并绑定账号,用于获取插件列表及插件包

+

下载专用插件(Linux),在面板【软件商店】->【第三方应用】,点击【导入插件】,导入该专用插件。

+
+
+ + 填写规则如:http://192.168.1.1:8888 ,不要带其他后缀 +
+
+ + +
+
+
+
+
+ + 填写规则如:http://www.example.com/ ,必须以/结尾 +
+
+
+ + +
+
+
+
+
+
+
+

宝塔Windows面板接口设置

+
+
+
+
+ +

+
+

以下宝塔面板请使用官方最新脚本安装并绑定账号,用于获取插件列表及插件包

+

下载专用插件(Win),在面板【软件商店】->【第三方应用】,点击【导入插件】,导入该专用插件。

+
+
+ + 填写规则如:http://192.168.1.1:8888 ,不要带其他后缀 +
+
+ + +
+
+
+
+
+ + 填写规则如:http://www.example.com/ ,必须以/结尾 +
+
+
+ + +
+
+
+
+
+ +{elseif $mod=='task'} +
+
+

自动更新插件说明

+
+
+
使用以下命令可以从宝塔官方获取最新的插件列表并批量下载插件包(增量更新)。
你也可以将此命令添加到crontab以使此云端的插件保持最新,建议1天执行1次。
+
使用命令执行之后,可能会导致 /data 目录下文件权限不对,后台插件列表下载插件覆盖会报错,需要手动循环设置 /data 目录权限。
+
上次运行时间:{$runtime|raw}
+
php {:app()->getRootPath()}think updateall

+
+
+
+
+
+
+

自动更新插件设置

+
+
+
+
+ (批量下载不包含所有第三方插件,第三方插件需要去手动下载。) +
+
+
+ (批量下载不包含所有第三方插件,第三方插件需要去手动下载。) +
+
+ +
+
+
+
+
+{elseif $mod=='account'} +
+
+

管理账号设置

+
+
+
+
+ +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+ 清理缓存 +
+
+
+{elseif $mod=='tools'} +
+
+

批量替换工具

+
+
+
使用以下命令可以将bt安装包、更新包和脚本文件里面的http://www.example.com批量替换成当前网址{:request()->root(true)},每次更新版本后只需要执行一次即可。
+
cd {:app()->getRootPath()}app/script && chmod +x convert.sh && ./convert.sh {:app()->getRootPath()} {:request()->root(true)}

+
+
+
+
+

清理旧版本插件工具

+
+
+
使用以下命令可清理旧版本的插件文件,以释放空间占用。
+
php {:app()->getRootPath()}think clean

+
+
+
+{/if} + + {/block} \ No newline at end of file diff --git a/install.sql b/install.sql index dd5eb7a..ee073bd 100644 --- a/install.sql +++ b/install.sql @@ -12,15 +12,15 @@ INSERT INTO `cloud_config` (`key`, `value`) VALUES ('bt_key', ''), ('whitelist', '0'), ('download_page', '1'), -('new_version', '8.0.1'), +('new_version', '8.0.2'), ('update_msg', '暂无更新日志'), -('update_date', '2023-07-20'), +('update_date', '2023-08-28'), ('new_version_win', '7.9.0'), ('update_msg_win', '暂无更新日志'), ('update_date_win', '2023-07-20'), -('new_version_btm', '2.2.8'), +('new_version_btm', '2.2.9'), ('update_msg_btm', '暂无更新日志'), -('update_date_btm', '2023-08-04'), +('update_date_btm', '2023-08-11'), ('updateall_type', '0'), ('syskey', 'UqP94LtI8eWAIgCP'); diff --git a/public/install/install_6.0.sh b/public/install/install_6.0.sh index 5af1d49..0b34e73 100644 --- a/public/install/install_6.0.sh +++ b/public/install/install_6.0.sh @@ -759,6 +759,18 @@ Install_Bt(){ if [ ! -f /www/server/panel/data/userInfo.json ]; then echo "{\"uid\":1,\"username\":\"Administrator\",\"address\":\"127.0.0.1\",\"serverid\":\"1\",\"access_key\":\"test\",\"secret_key\":\"123456\",\"ukey\":\"123456\",\"state\":1}" > /www/server/panel/data/userInfo.json fi + if [ ! -f /www/server/panel/data/panel_nps.pl ]; then + echo "" > /www/server/panel/data/panel_nps.pl + fi + if [ ! -f /www/server/panel/data/btwaf_nps.pl ]; then + echo "" > /www/server/panel/data/btwaf_nps.pl + fi + if [ ! -f /www/server/panel/data/tamper_proof_nps.pl ]; then + echo "" > /www/server/panel/data/tamper_proof_nps.pl + fi + if [ ! -f /www/server/panel/data/total_nps.pl ]; then + echo "" > /www/server/panel/data/total_nps.pl + fi } Set_Bt_Panel(){ Run_User="www" @@ -1022,7 +1034,7 @@ if [ "${PANEL_SSL}" == "True" ];then HTTP_S="https" else HTTP_S="http" -fi +fi echo > /www/server/panel/data/bind.pl echo -e "==================================================================" @@ -1042,7 +1054,6 @@ echo -e " 点击【高级】-【继续访问】或【接受风险并继续】访 echo -e " 教程:https://www.bt.cn/bbs/thread-117246-1-1.html" echo -e "" echo -e "==================================================================" - endTime=`date +%s` ((outTime=($endTime-$startTime)/60)) echo -e "Time consumed:\033[32m $outTime \033[0mMinute!" diff --git a/public/install/install_btmonitor.sh b/public/install/install_btmonitor.sh index aeba392..05c9eb0 100644 --- a/public/install/install_btmonitor.sh +++ b/public/install/install_btmonitor.sh @@ -427,6 +427,9 @@ EOF if [ -f $monitor_path/core/include/c_loader/PluginLoader.so ]; then rm -f $monitor_path/core/include/c_loader/PluginLoader.so fi + if [ -f $monitor_path/sqlite_server/PluginLoader.so ]; then + rm -f $monitor_path/sqlite_server/PluginLoader.so + fi } Start_Monitor(){ diff --git a/public/install/src/bt-monitor-2.2.8.zip b/public/install/src/bt-monitor-2.2.9.zip similarity index 83% rename from public/install/src/bt-monitor-2.2.8.zip rename to public/install/src/bt-monitor-2.2.9.zip index a8adb87..8cbbf6a 100644 Binary files a/public/install/src/bt-monitor-2.2.8.zip and b/public/install/src/bt-monitor-2.2.9.zip differ diff --git a/public/install/src/panel6.zip b/public/install/src/panel6.zip index 851220b..5c67670 100644 Binary files a/public/install/src/panel6.zip and b/public/install/src/panel6.zip differ diff --git a/public/install/update/LinuxPanel-8.0.1.zip b/public/install/update/LinuxPanel-8.0.2.zip similarity index 89% rename from public/install/update/LinuxPanel-8.0.1.zip rename to public/install/update/LinuxPanel-8.0.2.zip index b88f2ae..b7b9909 100644 Binary files a/public/install/update/LinuxPanel-8.0.1.zip and b/public/install/update/LinuxPanel-8.0.2.zip differ diff --git a/public/install/update6.sh b/public/install/update6.sh index d963061..22fea1e 100644 --- a/public/install/update6.sh +++ b/public/install/update6.sh @@ -113,6 +113,18 @@ fi if [ ! -f /www/server/panel/data/userInfo.json ]; then echo "{\"uid\":1,\"username\":\"Administrator\",\"address\":\"127.0.0.1\",\"serverid\":\"1\",\"access_key\":\"test\",\"secret_key\":\"123456\",\"ukey\":\"123456\",\"state\":1}" > /www/server/panel/data/userInfo.json fi +if [ ! -f /www/server/panel/data/panel_nps.pl ]; then + echo "" > /www/server/panel/data/panel_nps.pl +fi +if [ ! -f /www/server/panel/data/btwaf_nps.pl ]; then + echo "" > /www/server/panel/data/btwaf_nps.pl +fi +if [ ! -f /www/server/panel/data/tamper_proof_nps.pl ]; then + echo "" > /www/server/panel/data/tamper_proof_nps.pl +fi +if [ ! -f /www/server/panel/data/total_nps.pl ]; then + echo "" > /www/server/panel/data/total_nps.pl +fi chattr -i /etc/init.d/bt chmod +x /etc/init.d/bt diff --git a/public/install/update_btmonitor.sh b/public/install/update_btmonitor.sh index 9e7e562..7fa45ca 100644 --- a/public/install/update_btmonitor.sh +++ b/public/install/update_btmonitor.sh @@ -339,6 +339,9 @@ Install_Monitor(){ if [ -f $monitor_path/core/include/c_loader/PluginLoader.so ]; then rm -f $monitor_path/core/include/c_loader/PluginLoader.so fi + if [ -f $monitor_path/sqlite_server/PluginLoader.so ]; then + rm -f $monitor_path/sqlite_server/PluginLoader.so + fi } Service_Add(){ diff --git a/public/win/panel/panel_7.9.0.zip b/public/win/panel/panel_7.9.0.zip index 6dfee10..6044eea 100644 Binary files a/public/win/panel/panel_7.9.0.zip and b/public/win/panel/panel_7.9.0.zip differ diff --git a/route/app.php b/route/app.php index e1e816c..10b426f 100644 --- a/route/app.php +++ b/route/app.php @@ -105,6 +105,9 @@ Route::group('api', function () { Route::post('/v2/common_v1_authorization/get_pricing', 'api/return_error2'); Route::any('/bt_waf/getSpiders', 'api/btwaf_getspiders'); + Route::post('/bt_waf/addSpider', 'api/return_empty'); + Route::post('/bt_waf/getVulScanInfoList', 'api/return_empty'); + Route::post('/bt_waf/reportInterceptFail', 'api/return_empty'); Route::miss('api/return_error'); }); diff --git a/wiki/update.md b/wiki/update.md index 9d9c0e9..3e0f3ed 100644 --- a/wiki/update.md +++ b/wiki/update.md @@ -1,120 +1,120 @@ -# Linux面板官方更新包修改记录 - -查询最新版本号:https://www.bt.cn/api/panel/get_version?is_version=1 - -官方更新包下载链接:http://download.bt.cn/install/update/LinuxPanel-版本号.zip - -假设搭建的宝塔第三方云端网址是 http://www.example.com - -- 将class文件夹里面所有的.so文件删除 - -- 将linux/PluginLoader.py复制到class文件夹 - -- 批量解密模块文件:执行 php think decrypt classdir <面板class文件夹路径> - -- 全局搜索替换 https://api.bt.cn => http://www.example.com - -- 全局搜索替换 https://www.bt.cn/api/ => http://www.example.com/api/(需排除clearModel.py、scanningModel.py、ipsModel.py) - -- 全局搜索替换 https://download.bt.cn/install/update6.sh => http://www.example.com/install/update6.sh - -- class/ajax.py 文件 \#是否执行升级程序 下面的 public.get_url() 改成 public.GetConfigValue('home') - - class/jobs.py 文件 \#尝试升级到独立环境 下面的 public.get_url() 改成 public.GetConfigValue('home') - - class/system.py 文件 RepPanel和UpdatePro方法内的 public.get_url() 改成 public.GetConfigValue('home') - -- class/public.py 在 - - ```python - def GetConfigValue(key): - ``` - - 这一行下面加上 - - ```python - if key == 'home': return 'http://www.example.com' - ``` - - 在 def is_bind(): 这一行下面加上 return True - - 在 def check_domain_cloud(domain): 这一行下面加上 return - - 在 def get_improvement(): 这一行下面加上 return False - - 在free_login_area方法内get_free_ips_area替换成get_ips_area - - 在get_free_ip_info方法内,获取IP的部分改成res = get_ips_area([address]) - - 在login_send_body方法内,free_login_area(login_ip=server_ip_area的server_ip_area改成login_ip - -- class/panelPlugin.py 文件,download_icon方法内替换 public.GetConfigValue('home') => 'https://www.bt.cn' - - 删除public.total_keyword(get.query)这一行 - - __set_pyenv方法内,temp_file = public.readFile(filename)这行代码下面加上 - - ```python - temp_file = temp_file.replace('wget -O Tpublic.sh', '#wget -O Tpublic.sh') - temp_file = temp_file.replace('\cp -rpa Tpublic.sh', '#\cp -rpa Tpublic.sh') - temp_file = temp_file.replace('http://download.bt.cn/install/public.sh', 'http://www.example.com/install/public.sh') - temp_file = temp_file.replace('https://download.bt.cn/install/public.sh', 'http://www.example.com/install/public.sh') - ``` - -- class/plugin_deployment.py 文件,SetupPackage方法内替换 public.GetConfigValue('home') => 'https://www.bt.cn' - -- install/install_soft.sh 在bash执行之前加入以下代码 - - ```shell - sed -i "s/http:\/\/download.bt.cn\/install\/public.sh/http:\/\/www.example.com\/install\/public.sh/" lib.sh - sed -i "s/https:\/\/download.bt.cn\/install\/public.sh/http:\/\/www.example.com\/install\/public.sh/" lib.sh - sed -i "/wget -O Tpublic.sh/d" $name.sh - ``` - -- install/public.sh 用官网最新版的[public.sh](http://download.bt.cn/install/public.sh)替换,并去除最下面bt_check一行 - -- 去除无用的定时任务:task.py 文件 删除以下几行 - - "check_panel_msg": check_panel_msg, - - PluginLoader.daemon_panel() - -- 去除WebRTC连接:BTPanel/static/js/public.js 删除stun.start();这一行 - -- 去除首页广告:BTPanel/static/js/index.js 文件删除两处index.recommend_paid_version() - -- 去除首页自动检测更新,避免频繁请求云端:BTPanel/static/js/index.js 文件注释掉bt.system.check_update这一段代码外的setTimeout - -- 去除内页广告:BTPanel/templates/default/layout.html 删除两处getPaymentStatus(); - -- 删除问卷调查:BTPanel/templates/default/layout.html 删除if(window.localStorage.getItem('panelNPS') == null)以及下面的行 - -- [可选]去除各种计算题:复制bt.js到 BTPanel/static/ ,在 BTPanel/templates/default/layout.html 的\前面加入 - - ```javascript - - ``` - -- [可选]去除创建网站自动创建的垃圾文件:在class/panelSite.py,分别删除 - - htaccess = self.sitePath+'/.htaccess' - - index = self.sitePath+'/index.html' - - doc404 = self.sitePath+'/404.html' - - 这3行及分别接下来的4行代码 - -- [可选]关闭未绑定域名提示页面:在class/panelSite.py,root /www/server/nginx/html改成return 400 - -- [可选]关闭自动生成访问日志:在 BTPanel/\_\_init\_\_.py 删除public.write_request_log()这一行 - -- [可选]删除小图标广告:在BTPanel/static/js/site.js,删除“WAF防火墙”对应的span标签 - -- [可选]上传文件默认选中覆盖,在BTPanel/static/js/upload-drog.js,id="all_operation"加checked属性 - - -解压安装包panel6.zip,将更新包改好的文件覆盖到里面,然后重新打包,即可更新安装包。( - -别忘了删除class文件夹里面所有的.so文件) - +# Linux面板官方更新包修改记录 + +查询最新版本号:https://www.bt.cn/api/panel/get_version?is_version=1 + +官方更新包下载链接:http://download.bt.cn/install/update/LinuxPanel-版本号.zip + +假设搭建的宝塔第三方云端网址是 http://www.example.com + +- 将class文件夹里面所有的.so文件删除 + +- 将linux/PluginLoader.py复制到class文件夹 + +- 批量解密模块文件:执行 php think decrypt classdir <面板class文件夹路径> + +- 全局搜索替换 https://api.bt.cn => http://www.example.com + +- 全局搜索替换 https://www.bt.cn/api/ => http://www.example.com/api/(需排除clearModel.py、scanningModel.py、ipsModel.py) + +- 全局搜索替换 https://download.bt.cn/install/update6.sh => http://www.example.com/install/update6.sh + +- class/ajax.py 文件 \#是否执行升级程序 下面的 public.get_url() 改成 public.GetConfigValue('home') + + class/jobs.py 文件 \#尝试升级到独立环境 下面的 public.get_url() 改成 public.GetConfigValue('home') + + class/system.py 文件 RepPanel和UpdatePro方法内的 public.get_url() 改成 public.GetConfigValue('home') + +- class/public.py 在 + + ```python + def GetConfigValue(key): + ``` + + 这一行下面加上 + + ```python + if key == 'home': return 'http://www.example.com' + ``` + + 在 def is_bind(): 这一行下面加上 return True + + 在 def check_domain_cloud(domain): 这一行下面加上 return + + 在 def get_improvement(): 这一行下面加上 return False + + 在free_login_area方法内get_free_ips_area替换成get_ips_area + + 在get_free_ip_info方法内,获取IP的部分改成res = get_ips_area([address]) + + 在login_send_body方法内,free_login_area(login_ip=server_ip_area的server_ip_area改成login_ip + +- class/panelPlugin.py 文件,download_icon方法内替换 public.GetConfigValue('home') => 'https://www.bt.cn' + + 删除public.total_keyword(get.query)这一行 + + __set_pyenv方法内,temp_file = public.readFile(filename)这行代码下面加上 + + ```python + temp_file = temp_file.replace('wget -O Tpublic.sh', '#wget -O Tpublic.sh') + temp_file = temp_file.replace('\cp -rpa Tpublic.sh', '#\cp -rpa Tpublic.sh') + temp_file = temp_file.replace('http://download.bt.cn/install/public.sh', 'http://www.example.com/install/public.sh') + temp_file = temp_file.replace('https://download.bt.cn/install/public.sh', 'http://www.example.com/install/public.sh') + ``` + +- class/plugin_deployment.py 文件,SetupPackage方法内替换 public.GetConfigValue('home') => 'https://www.bt.cn' + +- install/install_soft.sh 在bash执行之前加入以下代码 + + ```shell + sed -i "s/http:\/\/download.bt.cn\/install\/public.sh/http:\/\/www.example.com\/install\/public.sh/" lib.sh + sed -i "s/https:\/\/download.bt.cn\/install\/public.sh/http:\/\/www.example.com\/install\/public.sh/" lib.sh + sed -i "/wget -O Tpublic.sh/d" $name.sh + ``` + +- install/public.sh 用官网最新版的[public.sh](http://download.bt.cn/install/public.sh)替换,并去除最下面bt_check一行 + +- 去除无用的定时任务:task.py 文件 删除以下几行 + + "check_panel_msg": check_panel_msg, + + PluginLoader.daemon_panel() + +- 去除WebRTC连接:BTPanel/static/js/public.js 删除stun.start();这一行 + +- 去除首页广告:BTPanel/static/js/index.js 文件删除两处index.recommend_paid_version() + +- 去除首页自动检测更新,避免频繁请求云端:BTPanel/static/js/index.js 文件注释掉bt.system.check_update这一段代码外的setTimeout + +- 去除内页广告:BTPanel/templates/default/layout.html 删除两处getPaymentStatus(); + +- 删除问卷调查:BTPanel/templates/default/layout.html 删除if(window.localStorage.getItem('panelNPS') == null)以及下面的行 + +- [可选]去除各种计算题:复制bt.js到 BTPanel/static/ ,在 BTPanel/templates/default/layout.html 的\前面加入 + + ```javascript + + ``` + +- [可选]去除创建网站自动创建的垃圾文件:在class/panelSite.py,分别删除 + + htaccess = self.sitePath+'/.htaccess' + + index = self.sitePath+'/index.html' + + doc404 = self.sitePath+'/404.html' + + 这3行及分别接下来的4行代码 + +- [可选]关闭未绑定域名提示页面:在class/panelSite.py,root /www/server/nginx/html改成return 400 + +- [可选]关闭自动生成访问日志:在 BTPanel/\_\_init\_\_.py 删除public.write_request_log这一行 + +- [可选]删除小图标广告:在BTPanel/static/js/site.js,删除“WAF防火墙”对应的span标签 + +- [可选]上传文件默认选中覆盖,在BTPanel/static/js/upload-drog.js,id="all_operation"加checked属性 + + +解压安装包panel6.zip,将更新包改好的文件覆盖到里面,然后重新打包,即可更新安装包。( + +别忘了删除class文件夹里面所有的.so文件) +