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

213 lines
8.0 KiB

2 years ago
2 months ago
2 years ago
2 months ago
2 years ago
  1. <?php
  2. namespace app\lib;
  3. use Exception;
  4. use ZipArchive;
  5. class ThirdPlugins
  6. {
  7. private $url;
  8. private $os;
  9. public function __construct($os)
  10. {
  11. $this->os = $os;
  12. if($os == 'en'){
  13. $url = config_get('enbt_surl');
  14. }elseif($os == 'Windows'){
  15. $url = config_get('wbt_surl');
  16. }else{
  17. $url = config_get('bt_surl');
  18. }
  19. if(!$url) throw new Exception('请先配置好第三方云端首页URL');
  20. $this->url = $url;
  21. }
  22. //获取插件列表
  23. public function get_plugin_list()
  24. {
  25. if($this->os == 'en'){
  26. $url = $this->url . 'api/panel/get_plugin_list_en';
  27. }elseif($this->os == 'Windows'){
  28. $url = $this->url . 'api/wpanel/get_plugin_list';
  29. }else{
  30. $url = $this->url . 'api/panel/get_plugin_list';
  31. }
  32. $res = $this->curl($url);
  33. $result = json_decode($res, true);
  34. if($result && isset($result['list']) && isset($result['type'])){
  35. if(empty($result['list']) || empty($result['type'])){
  36. throw new Exception('获取插件列表失败:插件列表为空');
  37. }
  38. return $result;
  39. }else{
  40. throw new Exception('获取插件列表失败:'.(isset($result['msg'])?$result['msg']:'第三方云端连接失败'));
  41. }
  42. }
  43. //下载插件(自动判断是否第三方)
  44. public function download_plugin($plugin_name, $version, $plugin_info){
  45. if($plugin_info['type'] == 10 && isset($plugin_info['versions'][0]['download'])){
  46. $fname = $plugin_info['versions'][0]['download'];
  47. $filemd5 = $plugin_info['versions'][0]['md5'];
  48. $this->download_plugin_other($fname, $filemd5);
  49. if(isset($plugin_info['min_image']) && strpos($plugin_info['min_image'], 'fname=')){
  50. $fname = substr($plugin_info['min_image'], strpos($plugin_info['min_image'], '?fname=')+7);
  51. $this->download_plugin_other($fname);
  52. }
  53. }else{
  54. $this->download_plugin_package($plugin_name, $version);
  55. }
  56. }
  57. //下载插件包
  58. private function download_plugin_package($plugin_name, $version){
  59. $filepath = get_data_dir($this->os).'plugins/package/'.$plugin_name.'-'.$version.'.zip';
  60. $url = $this->url . 'down/download_plugin';
  61. $post = ['name'=>$plugin_name, 'version'=>$version, 'os'=>$this->os];
  62. $this->curl_download($url, $post, $filepath);
  63. if(file_exists($filepath)){
  64. $handle = fopen($filepath, "rb");
  65. $file_head = fread($handle, 4);
  66. fclose($handle);
  67. if(bin2hex($file_head) === '504b0304'){
  68. $zip = new ZipArchive;
  69. if ($zip->open($filepath) === true)
  70. {
  71. $zip->close();
  72. return true;
  73. }else{
  74. @unlink($filepath);
  75. throw new Exception('插件包解压缩失败');
  76. }
  77. }else{
  78. $handle = fopen($filepath, "rb");
  79. $errmsg = htmlspecialchars(fgets($handle));
  80. fclose($handle);
  81. @unlink($filepath);
  82. throw new Exception('下载插件包失败:'.($errmsg?$errmsg:'未知错误'));
  83. }
  84. }else{
  85. throw new Exception('下载插件包失败,本地文件不存在');
  86. }
  87. }
  88. //下载插件主程序文件
  89. public function download_plugin_main($plugin_name, $version){
  90. $filepath = get_data_dir($this->os).'plugins/main/'.$plugin_name.'-'.$version.'.dat';
  91. $url = $this->url . 'down/download_plugin_main';
  92. $post = ['name'=>$plugin_name, 'version'=>$version, 'os'=>$this->os];
  93. $this->curl_download($url, $post, $filepath);
  94. if(file_exists($filepath)){
  95. $line = count(file($filepath));
  96. if($line > 3) return true;
  97. $handle = fopen($filepath, "rb");
  98. $errmsg = htmlspecialchars(fgets($handle));
  99. fclose($handle);
  100. @unlink($filepath);
  101. throw new Exception('下载插件主程序文件失败:'.($errmsg?$errmsg:'未知错误'));
  102. }else{
  103. throw new Exception('下载插件主程序文件失败,本地文件不存在');
  104. }
  105. }
  106. //下载插件其他文件
  107. private function download_plugin_other($fname, $filemd5 = null){
  108. $filepath = get_data_dir().'plugins/other/'.$fname;
  109. @mkdir(dirname($filepath), 0777, true);
  110. $url = $this->url . 'api/Pluginother/get_file?fname='.urlencode($fname);
  111. $this->curl_download($url, false, $filepath);
  112. if(file_exists($filepath)){
  113. $handle = fopen($filepath, "rb");
  114. $file_head = fread($handle, 15);
  115. fclose($handle);
  116. if($file_head === '{"status":false'){
  117. $res = file_get_contents($filepath);
  118. $result = json_decode($res, true);
  119. @unlink($filepath);
  120. throw new Exception('下载插件文件失败:'.($result?$result['msg']:'未知错误'));
  121. }
  122. if($filemd5 && md5_file($filepath) != $filemd5){
  123. $msg = filesize($filepath) < 300 ? file_get_contents($filepath) : '插件文件MD5校验失败';
  124. @unlink($filepath);
  125. throw new Exception($msg);
  126. }
  127. return true;
  128. }else{
  129. throw new Exception('下载插件文件失败,本地文件不存在');
  130. }
  131. }
  132. //获取一键部署列表
  133. public function get_deplist(){
  134. $url = $this->url . 'api/panel/get_deplist';
  135. $post = ['os' => $this->os];
  136. $res = $this->curl($url, http_build_query($post));
  137. $result = json_decode($res, true);
  138. if($result && isset($result['list']) && isset($result['type'])){
  139. if(empty($result['list']) || empty($result['type'])){
  140. throw new Exception('获取一键部署列表失败:一键部署列表为空');
  141. }
  142. return $result;
  143. }else{
  144. throw new Exception('获取一键部署列表失败:'.(isset($result['msg'])?$result['msg']:'第三方云端连接失败'));
  145. }
  146. }
  147. //获取蜘蛛IP列表
  148. public function btwaf_getspiders(){
  149. $url = $this->url . 'api/bt_waf/getSpiders';
  150. $res = $this->curl($url);
  151. $result = json_decode($res, true);
  152. if(isset($result['status']) && !$result['status']){
  153. throw new Exception(isset($result['msg'])?$result['msg']:'获取失败');
  154. }else{
  155. return $result;
  156. }
  157. }
  158. private function curl($url, $post = 0){
  159. $ua = "Mozilla/5.0 (BtCloud; ".request()->root(true).")";
  160. return get_curl($url, $post, 0, 0, 0, $ua);
  161. }
  162. private function curl_download($url, $post, $localpath, $timeout = 300)
  163. {
  164. $ch = curl_init();
  165. curl_setopt($ch, CURLOPT_URL, $url);
  166. curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
  167. $fp = fopen($localpath, 'w+');
  168. curl_setopt($ch, CURLOPT_FILE, $fp);
  169. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
  170. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  171. curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (BtCloud; ".request()->root(true).")");
  172. if($post){
  173. curl_setopt($ch, CURLOPT_POST, 1);
  174. curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
  175. }
  176. curl_exec($ch);
  177. if (curl_errno($ch)) {
  178. $message = curl_error($ch);
  179. curl_close($ch);
  180. fclose($fp);
  181. throw new Exception('下载文件失败:'.$message);
  182. }
  183. $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  184. if($httpcode>299){
  185. curl_close($ch);
  186. fclose($fp);
  187. throw new Exception('下载文件失败:HTTPCODE-'.$httpcode);
  188. }
  189. curl_close($ch);
  190. fclose($fp);
  191. return true;
  192. }
  193. }