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.

261 lines
9.3 KiB

2 years ago
13 hours ago
2 years ago
13 hours ago
2 years ago
13 hours ago
2 years ago
13 hours ago
2 years ago
13 hours ago
2 years ago
13 hours ago
2 years ago
13 hours ago
2 years ago
13 hours ago
2 years ago
13 hours ago
2 years ago
13 hours ago
2 years ago
13 hours ago
2 years ago
13 hours ago
2 years ago
13 hours ago
2 years ago
13 hours ago
2 years ago
13 hours ago
2 years ago
13 hours ago
2 years ago
13 hours ago
2 years ago
13 hours ago
2 years ago
13 hours ago
2 years ago
13 hours ago
2 years ago
13 hours ago
2 years ago
13 hours ago
2 years ago
13 hours ago
2 years ago
13 hours ago
  1. #coding: utf-8
  2. # +-------------------------------------------------------------------
  3. # | 宝塔Windows面板
  4. # +-------------------------------------------------------------------
  5. # | Copyright (c) 2015-2020 宝塔软件(http://www.bt.cn) All rights reserved.
  6. # +-------------------------------------------------------------------
  7. # | Author: 沐落 <cjx@bt.cn>
  8. # | 面板升级安装公共类
  9. # +-------------------------------------------------------------------
  10. import os, sys
  11. panelPath = os.getenv('BT_PANEL')
  12. os.chdir(panelPath)
  13. sys.path.insert(0,panelPath + "/class/")
  14. import public,time,re,shutil,platform,socket
  15. try:
  16. import ctypes
  17. except ImportError:
  18. ctypes = None
  19. class panel_update:
  20. __cloud_url = 'http://www.example.com'
  21. def __init__(self):
  22. pass
  23. def _check_admin_privileges(self):
  24. try:
  25. # 方法1: 使用ctypes检查管理员权限
  26. if ctypes:
  27. is_admin = ctypes.windll.shell32.IsUserAnAdmin()
  28. if is_admin:
  29. return {'status': True, 'msg': '当前以管理员权限运行'}
  30. else:
  31. return {'status': False, 'msg': '当前未以管理员权限运行,请使用管理员身份运行此脚本'}
  32. # 方法2: 尝试写入系统目录来检测权限
  33. try:
  34. test_file = r"C:\Windows\Temp\bt_panel_test.tmp"
  35. with open(test_file, 'w') as f:
  36. f.write('test')
  37. os.remove(test_file)
  38. return {'status': True, 'msg': '当前以管理员权限运行'}
  39. except (IOError, OSError):
  40. return {'status': False, 'msg': '当前未以管理员权限运行,请使用管理员身份运行此脚本'}
  41. except Exception as e:
  42. return {'status': False, 'msg': f'检测管理员权限时发生错误: {str(e)}'}
  43. def _pre_update_checks(self):
  44. try:
  45. ip_address = self._get_cloud_ip()
  46. if not ip_address:
  47. return {'status': False, 'msg': '无法获取当前云端域名的IP地址'}
  48. if not self._verify_api(ip_address):
  49. return {'status': False, 'msg': '当前云端无法访问,可能未绑定api.bt.cn和www.bt.cn域名'}
  50. if not self._update_hosts(ip_address):
  51. return {'status': False, 'msg': '修改hosts文件失败'}
  52. return {'status': True, 'msg': '升级前检查通过'}
  53. except Exception as e:
  54. return {'status': False, 'msg': f'升级前检查异常: {str(e)}'}
  55. def _get_cloud_ip(self):
  56. domain = re.findall(r'://([^/:]+)', self.__cloud_url)[0]
  57. try:
  58. ip_address = socket.gethostbyname(domain)
  59. return ip_address
  60. except Exception as e:
  61. print(f"获取{domain} IP失败: {str(e)}")
  62. return None
  63. def _verify_api(self, ip_address):
  64. try:
  65. api_url = f"http://{ip_address}/api/SetupCount"
  66. headers = {"Host": "api.bt.cn", "User-Agent": "BT-Panel"}
  67. response = public.HttpGet(api_url, headers=headers, timeout=10)
  68. if response and response.strip() == "ok":
  69. return True
  70. else:
  71. print(f"请求云端验证失败,响应: {response}")
  72. return False
  73. except Exception as e:
  74. print(f"请求云端验证异常: {str(e)}")
  75. return False
  76. def _update_hosts(self, ip_address):
  77. hosts_path = r"C:\Windows\System32\drivers\etc\hosts"
  78. try:
  79. if os.path.exists(hosts_path):
  80. content = public.readFile(hosts_path)
  81. else:
  82. content = ""
  83. lines = content.split('\n')
  84. new_lines = []
  85. for line in lines:
  86. stripped_line = line.strip()
  87. if not stripped_line or stripped_line.startswith('#'):
  88. new_lines.append(line)
  89. continue
  90. if 'api.bt.cn' in line or 'www.bt.cn' in line:
  91. continue
  92. new_lines.append(line)
  93. new_lines.append(f"{ip_address} api.bt.cn")
  94. new_lines.append(f"{ip_address} www.bt.cn")
  95. new_content = '\n'.join(new_lines)
  96. result = public.writeFile(hosts_path, new_content)
  97. if result:
  98. print(f"修改hosts文件成功")
  99. return True
  100. else:
  101. print("修改hosts文件失败")
  102. return False
  103. except Exception as e:
  104. print(f"修改hosts文件异常: {str(e)}")
  105. return False
  106. def UpdatePanel(self,version):
  107. """
  108. Go面板到指定版本
  109. @version
  110. """
  111. import public
  112. admin_check = self._check_admin_privileges()
  113. if not admin_check['status']:
  114. return public.returnMsg(False, admin_check['msg'])
  115. result = self._pre_update_checks()
  116. if not result['status']:
  117. return public.returnMsg(False, result['msg'])
  118. setupPath = os.getenv('BT_SETUP')
  119. loacl_path = setupPath + '/panel.zip'
  120. tmpPath = "{}/temp/panel".format(setupPath)
  121. try:
  122. downUrl = self.__cloud_url + '/win/panel/panel_' + version + '.zip';
  123. if os.path.exists(loacl_path): os.remove(loacl_path)
  124. public.downloadFileByWget(downUrl,loacl_path);
  125. if os.path.getsize(loacl_path) < 1048576: return public.returnMsg(False,"PANEL_UPDATE_ERR_DOWN");
  126. except :
  127. print(public.get_error_info())
  128. return public.returnMsg(False,"更新失败,无法连接到下载节点.");
  129. #处理临时文件目录
  130. tcPath = '{}\class'.format(tmpPath)
  131. if os.path.exists(tmpPath): shutil.rmtree(tmpPath,True)
  132. if not os.path.exists(tmpPath): os.makedirs(tmpPath)
  133. import zipfile
  134. zip_file = zipfile.ZipFile(loacl_path)
  135. for names in zip_file.namelist():
  136. zip_file.extract(names,tmpPath)
  137. zip_file.close()
  138. os.system('net stop btPanel')
  139. #过滤文件
  140. file_list = ['config/config.json','config/index.json','data/libList.conf','data/plugin.json']
  141. for ff_path in file_list:
  142. if os.path.exists(tmpPath + '/' + ff_path): os.remove(tmpPath + '/' + ff_path)
  143. if self.is_2008():
  144. public.rmdir("{}/class/public".format(tmpPath))
  145. public.rmdir("{}/class/BTPanel.py".format(tmpPath))
  146. return public.returnMsg(False,"Windows 2008无法使用最新版本。")
  147. public.mod_reload(public)
  148. import public
  149. #兼容不同版本工具箱
  150. public.kill('BtTools.exe')
  151. toolPath = tmpPath + '/script/BtTools.exe'
  152. if os.path.exists(toolPath):os.remove(toolPath)
  153. s_ver = platform.platform()
  154. cPath = '{}/panel/class'.format(setupPath)
  155. os.system("del /s {}\*.pyc".format(public.to_path(cPath)))
  156. os.system("del /s {}\*.pyt".format(public.to_path(cPath)))
  157. os.system("del /s {}\*_amd64.pyd".format(public.to_path(cPath)))
  158. for name in os.listdir(cPath):
  159. try:
  160. if name.find('.pyd') >=0:
  161. oldName = os.path.join(cPath,name)
  162. newName = os.path.join(cPath,public.GetRandomString(8) + '.pyt')
  163. os.rename(oldName,newName)
  164. if name.find('.dll') >= 0:
  165. oldName = os.path.join(cPath,name)
  166. public.rmdir(oldName)
  167. except : pass
  168. #处理面板程序目录文件
  169. os.system("del /s {}\*.pyc".format(public.to_path(cPath)))
  170. os.system("del /s {}\*.pyt".format(public.to_path(cPath)))
  171. os.system("del /s {}\*.del".format(public.to_path(panelPath)))
  172. for name in os.listdir(panelPath):
  173. try:
  174. if name.find('.exe') >=0:
  175. oldName = os.path.join(panelPath,name)
  176. newName = oldName + '.del'
  177. os.rename(oldName,newName)
  178. except : pass
  179. os.system("echo f|xcopy /s /c /e /y /r {} {}".format(public.to_path(tmpPath),public.to_path(panelPath)))
  180. panel_file = '{}/btPanel.exe'.format(panelPath)
  181. if os.path.exists(panel_file):
  182. os.system("sc stop btPanel")
  183. os.system("sc stop btTask")
  184. time.sleep(2)
  185. os.system("sc delete btPanel")
  186. os.system("sc delete btTask")
  187. os.system("{} --services install".format(public.to_path(panel_file)))
  188. time.sleep(2)
  189. os.system("{} --task install".format(public.to_path(panel_file)))
  190. os.system("sc start btPanel")
  191. os.system("sc start btTask")
  192. if os.path.exists('C:/update.py'): os.remove('C:/update.py')
  193. return public.returnMsg(True,"升级面板成功.")
  194. def is_2008(self):
  195. """
  196. 2008
  197. """
  198. os_ver = public.ReadReg("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "ProductName")
  199. if os_ver.find('2008') >= 0: return True
  200. return False
  201. if __name__ == "__main__":
  202. version = sys.argv[1]
  203. if not version:
  204. version = "8.4.6"
  205. result = panel_update().UpdatePanel(version)
  206. print(result['msg'])