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.

202 lines
7.8 KiB

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