btcloud/public/win/panel/data/setup.py
2023-07-21 17:46:50 +08:00

1040 lines
35 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#coding: utf-8
# +-------------------------------------------------------------------
# | 宝塔Windows面板
# +-------------------------------------------------------------------
# | Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
# +-------------------------------------------------------------------
# | Author: 沐落 <cjx@bt.cn>
# +-------------------------------------------------------------------
import os,chardet,time,sys,re
import win32net, win32api, win32netcon,win32security,win32serviceutil
import traceback,shlex,datetime,subprocess,platform
import sqlite3,shutil
def readReg(path,key):
import winreg
try:
newKey = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE ,path)
value,type = winreg.QueryValueEx(newKey, key)
return value
except :
return False
panelPath = readReg(r'SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\宝塔面板','PanelPath')
if not panelPath:
panelPath = os.getenv('BT_PANEL')
if not panelPath: exit();
setupPath = os.path.dirname(panelPath)
error_path = '{}/error.log'.format(setupPath)
logPath = panelPath + '/data/panelExec.log'
class Sql():
#------------------------------
# 数据库操作类 For sqlite3
#------------------------------
__DB_FILE = None # 数据库文件
__DB_CONN = None # 数据库连接对象
__DB_TABLE = "" # 被操作的表名称
__OPT_WHERE = "" # where条件
__OPT_LIMIT = "" # limit条件
__OPT_ORDER = "" # order条件
__OPT_FIELD = "*" # field条件
__OPT_PARAM = () # where值
__LOCK = panelPath + '/data/sqlite_lock.pl'
def __init__(self):
self.__DB_FILE = panelPath + '/data/default.db'
def __GetConn(self):
#取数据库对象
try:
if self.__DB_CONN == None:
self.__DB_CONN = sqlite3.connect(self.__DB_FILE)
self.__DB_CONN.text_factory = str
except Exception as ex:
print(str(ex))
return "error: " + str(ex)
def table(self,table):
#设置表名
self.__DB_TABLE = table
return self
def where(self,where,param):
#WHERE条件
if where:
self.__OPT_WHERE = " WHERE " + where
self.__OPT_PARAM = self.__to_tuple(param)
return self
def __to_tuple(self,param):
#将参数转换为tuple
if type(param) != tuple:
if type(param) == list:
param = tuple(param)
else:
param = (param,)
return param
#更新数据
def update(self,pdata):
if not pdata: return False
keys,param = self.__format_pdata(pdata)
return self.save(keys,param)
#构造数据
def __format_pdata(self,pdata):
keys = pdata.keys()
keys_str = ','.join(keys)
param = []
for k in keys: param.append(pdata[k])
return keys_str,tuple(param)
def field(self,field):
#FIELD条件
if len(field):
self.__OPT_FIELD = field
return self
def getField(self,keyName):
#取回指定字段
result = self.field(keyName).select()
print(result)
if len(result) != 0:
return result[0][keyName]
return result
def __format_field(self,field):
import re
fields = []
for key in field:
s_as = re.search(r'\s+as\s+',key,flags=re.IGNORECASE)
if s_as:
as_tip = s_as.group()
key = key.split(as_tip)[1]
fields.append(key)
return fields
def __get_columns(self):
if self.__OPT_FIELD == '*':
tmp_cols = self.query('PRAGMA table_info('+self.__DB_TABLE+')',())
cols = []
for col in tmp_cols:
if len(col) > 2: cols.append('`' + col[1] + '`')
if len(cols) > 0: self.__OPT_FIELD = ','.join(cols)
def select(self):
#查询数据集
self.__GetConn()
try:
self.__get_columns()
sql = "SELECT " + self.__OPT_FIELD + " FROM " + self.__DB_TABLE + self.__OPT_WHERE + self.__OPT_ORDER + self.__OPT_LIMIT
result = self.__DB_CONN.execute(sql,self.__OPT_PARAM)
data = result.fetchall()
#构造字典系列
if self.__OPT_FIELD != "*":
fields = self.__format_field(self.__OPT_FIELD.split(','))
tmp = []
for row in data:
i=0
tmp1 = {}
for key in fields:
tmp1[key.strip('`')] = row[i]
i += 1
tmp.append(tmp1)
del(tmp1)
data = tmp
del(tmp)
else:
#将元组转换成列表
tmp = list(map(list,data))
data = tmp
del(tmp)
self.__close()
return data
except Exception as ex:
return "error: " + str(ex)
def setField(self,keyName,keyValue):
#更新指定字段
return self.save(keyName,(keyValue,))
def commit(self):
self.__close()
self.__DB_CONN.commit()
def save(self,keys,param):
#更新数据
self.write_lock()
self.__GetConn()
self.__DB_CONN.text_factory = str
try:
opt = ""
for key in keys.split(','):
opt += key + "=?,"
opt = opt[0:len(opt)-1]
sql = "UPDATE " + self.__DB_TABLE + " SET " + opt+self.__OPT_WHERE
#处理拼接WHERE与UPDATE参数
tmp = list(self.__to_tuple(param))
for arg in self.__OPT_PARAM:
tmp.append(arg)
self.__OPT_PARAM = tuple(tmp)
result = self.__DB_CONN.execute(sql,self.__OPT_PARAM)
self.__close()
self.__DB_CONN.commit()
self.rm_lock()
return result.rowcount
except Exception as ex:
return "error: " + str(ex)
def execute(self,sql,param = ()):
#执行SQL语句返回受影响行
self.write_lock()
self.__GetConn()
try:
result = self.__DB_CONN.execute(sql,self.__to_tuple(param))
self.__DB_CONN.commit()
self.rm_lock()
return result.rowcount
except Exception as ex:
return "error: " + str(ex)
#是否有锁
def is_lock(self):
n = 0
while os.path.exists(self.__LOCK):
n+=1
if n > 100:
self.rm_lock()
break
time.sleep(0.01)
#写锁
def write_lock(self):
self.is_lock()
open(self.__LOCK,'wb+').close()
#解锁
def rm_lock(self):
if os.path.exists(self.__LOCK):
os.remove(self.__LOCK)
def query(self,sql,param = ()):
#执行SQL语句返回数据集
self.__GetConn()
try:
result = self.__DB_CONN.execute(sql,self.__to_tuple(param))
#将元组转换成列表
data = list(map(list,result))
return data
except Exception as ex:
return "error: " + str(ex)
def __close(self):
#清理条件属性
self.__OPT_WHERE = ""
self.__OPT_FIELD = "*"
self.__OPT_ORDER = ""
self.__OPT_LIMIT = ""
self.__OPT_PARAM = ()
def close(self):
#释放资源
try:
self.__DB_CONN.close()
self.__DB_CONN = None
except:
pass
def GetLocalIp():
"""
取本地外网IP
"""
try:
filename = panelPath + '/data/iplist.txt'
ipaddress = readFile(filename)
if not ipaddress:
url = 'http://www.example.com/api/getIpAddress';
str = httpGet(url)
writeFile(filename,ipaddress)
ipaddress = re.search('\d+.\d+.\d+.\d+',ipaddress).group(0);
return ipaddress
except:
try:
url = 'https://www.bt.cn/Api/getIpAddress';
str = httpGet(url)
writeFile(filename,ipaddress)
return str
except:
pass
def get_error_info():
errorMsg = traceback.format_exc();
return errorMsg
def get_server_status(name):
try:
serviceStatus = win32serviceutil.QueryServiceStatus(name)
if serviceStatus[1] == 4:
return 1
return 0
except :
return -1
def start_service(name):
try:
timeout = 0;
while get_server_status(name) == 0:
try:
win32serviceutil.StartService(name)
time.sleep(1);
except : time.sleep(1);
timeout += 1
if timeout > 10:break
if get_server_status(name) != 0:
return True,None
return False,'操作失败10秒内未完成启动服务【{}'.format(name)
except :
return False,get_error_info()
def stop_service(name):
try:
timeout = 0;
while get_server_status(name) == 1:
try:
win32serviceutil.StopService(name)
time.sleep(1);
except : time.sleep(1);
timeout += 1
if timeout > 10:break
if get_server_status(name) != 1:
return True,None
return False,'操作失败10秒内未完成启动服务【{}'.format(name)
except :
return False,get_error_info()
def delete_server(name):
try:
stop_service(name)
win32serviceutil.RemoveService(name)
return True,''
except :
return False,get_error_info()
def get_requests_headers():
return {"Content-type":"application/x-www-form-urlencoded","User-Agent":"BT-Panel"}
def downloadFile(url,filename):
try:
import requests
res = requests.get(url,verify=False)
with open(filename,"wb") as f:
f.write(res.content)
except:
import requests
res = requests.get(url,verify=False)
with open(filename,"wb") as f:
f.write(res.content)
def downloadFileByWget(url,filename):
"""
wget下载文件
@url 下载地址
@filename 本地文件路径
"""
try:
if os.path.exists(logPath): os.remove(logPath)
except : pass
loacl_path = '{}/script/wget.exe'.format(panelPath)
if not os.path.exists(loacl_path): downloadFile(get_url()+'/win/panel/data/wget.exe',loacl_path)
if os.path.getsize(loacl_path) < 10:
os.remove(loacl_path)
downloadFile(url,filename)
else:
shell = "{} {} -O {} -t 5 -T 60 --no-check-certificate --auth-no-challenge --force-directorie > {} 2>&1".format(loacl_path,url,filename,logPath)
os.system(shell)
num = 0
re_size = 0
while num <= 5:
if os.path.exists(filename):
cr_size = os.path.getsize(filename)
if re_size > 0 and re_size == cr_size:
break;
else:
re_size = cr_size
time.sleep(0.5)
num += 1
if os.path.exists(filename):
if os.path.getsize(filename) < 1:
os.remove(filename)
downloadFile(url,filename)
else:
downloadFile(url,filename)
def writeFile(filename,s_body,mode='w+',encoding = 'utf-8'):
try:
fp = open(filename, mode,encoding = encoding);
fp.write(s_body)
fp.close()
return True
except:
return False
def readFile(filename,mode = 'r'):
import os,chardet
if not os.path.exists(filename): return False
if not os.path.isfile(filename): return False
encoding = 'utf-8'
f_body = '';
try:
fp = open(filename, mode,encoding = encoding)
f_body = fp.read()
except :
fp.close()
try:
encoding = 'gbk'
fp = open(filename, mode,encoding = encoding)
f_body = fp.read()
except :
fp.close()
encoding = 'ansi'
fp = open(filename, mode,encoding = encoding)
f_body = fp.read()
try:
if f_body[0] == '\ufeff':
#处理带bom格式
new_code = chardet.detect(f_body.encode(encoding))["encoding"]
f_body = f_body.encode(encoding).decode(new_code);
except : pass
fp.close()
return f_body
def httpGet(url,timeout = 60,headers = {}):
try:
import urllib.request,ssl
try:
ssl._create_default_https_context = ssl._create_unverified_context
except:pass;
req = urllib.request.Request(url,headers = headers)
response = urllib.request.urlopen(req,timeout = timeout)
result = response.read()
if type(result) == bytes:
try:
result = result.decode('utf-8')
except :
result = result.decode('gb2312')
return result
except Exception as ex:
if headers: return False
return str(ex)
def httpPost(url, data, timeout=60, headers={}):
try:
import urllib.request,ssl
try:
ssl._create_default_https_context = ssl._create_unverified_context
except:pass;
data2 = urllib.parse.urlencode(data).encode('utf-8')
req = urllib.request.Request(url, data2,headers = headers)
response = urllib.request.urlopen(req,timeout = timeout)
result = response.read()
if type(result) == bytes: result = result.decode('utf-8')
return result
except Exception as ex:
return str(ex);
def get_timeout(url,timeout=3):
try:
start = time.time()
result = int(httpGet(url,timeout))
return result,int((time.time() - start) * 1000 - 500)
except: return 0,False
def get_url(timeout = 0.5):
import json
try:
#
node_list = [{"protocol":"http://","address":"dg2.bt.cn","port":"80","ping":500},{"protocol":"http://","address":"dg1.bt.cn","port":"80","ping":500},{"protocol":"http://","address":"download.bt.cn","port":"80","ping":500},{"protocol":"http://","address":"hk1-node.bt.cn","port":"80","ping":500},{"protocol":"http://","address":"na1-node.bt.cn","port":"80","ping":500},{"protocol":"http://","address":"jp1-node.bt.cn","port":"80","ping":500}]
mnode1 = []
mnode2 = []
mnode3 = []
for node in node_list:
node['net'],node['ping'] = get_timeout(node['protocol'] + node['address'] + ':' + node['port'] + '/net_test',1)
if not node['ping']: continue
if node['ping'] < 100: #当响应时间<100ms且可用带宽大于1500KB时
if node['net'] > 1500:
mnode1.append(node)
elif node['net'] > 1000:
mnode3.append(node)
else:
if node['net'] > 1000: #当响应时间>=100ms且可用带宽大于1000KB时
mnode2.append(node)
if node['ping'] < 100:
if node['net'] > 3000: break #有节点可用带宽大于3000时不再检查其它节点
if mnode1: #优选低延迟高带宽
mnode = sorted(mnode1,key= lambda x:x['net'],reverse=True)
elif mnode3: #备选低延迟,中等带宽
mnode = sorted(mnode3,key= lambda x:x['net'],reverse=True)
else: #终选中等延迟,中等带宽
mnode = sorted(mnode2,key= lambda x:x['ping'],reverse=False)
if not mnode: return 'https://download.bt.cn'
#return mnode[0]['protocol'] + mnode[0]['address'] + ':' + mnode[0]['port']
return "https://" + mnode[0]['address']
except:
return 'https://download.bt.cn'
#删除文件权限
def del_file_access(filename,user):
try:
if filename.lower() in ["c:/","c:","c:\\","c"]:
return True
import win32security
sd = win32security.GetFileSecurity(filename, win32security.DACL_SECURITY_INFORMATION)
dacl = sd.GetSecurityDescriptorDacl()
ace_count = dacl.GetAceCount()
for i in range(ace_count ,0 ,-1):
try:
data = {}
data['rev'], data['access'], usersid = dacl.GetAce(i-1)
data['user'],data['group'], data['type'] = win32security.LookupAccountSid('', usersid)
if data['user'].lower() == user.lower(): dacl.DeleteAce(i-1) #删除旧的dacl
if data['user'].lower() == 'users': dacl.DeleteAce(i-1) #删除旧的dacl
except :
try:
#处理拒绝访问
dacl.DeleteAce(i-1)
except : pass
sd.SetSecurityDescriptorDacl(1, dacl, 0)
win32security.SetFileSecurity(filename, win32security.DACL_SECURITY_INFORMATION, sd)
except :
pass
return True
def set_file_access(filename,user,access):
try:
sd = win32security.GetFileSecurity(filename, win32security.DACL_SECURITY_INFORMATION)
dacl = sd.GetSecurityDescriptorDacl()
ace_count = dacl.GetAceCount()
for i in range(ace_count, 0,-1):
try:
data = {}
data['rev'], data['access'], usersid = dacl.GetAce(i-1)
data['user'],data['group'], data['type'] = win32security.LookupAccountSid('', usersid)
if data['user'].lower() == user.lower(): dacl.DeleteAce(i-1) #删除旧的dacl
if data['user'].lower() == 'users': dacl.DeleteAce(i-1) #删除旧的dacl
except :
pass
try:
userx, domain, type = win32security.LookupAccountName("", user)
except :
userx, domain, type = win32security.LookupAccountName("", 'IIS APPPOOL\\' + user)
if access > 0: dacl.AddAccessAllowedAceEx(win32security.ACL_REVISION, 3, access, userx)
sd.SetSecurityDescriptorDacl(1, dacl, 0)
win32security.SetFileSecurity(filename, win32security.DACL_SECURITY_INFORMATION, sd)
return True,None
except :
return False,get_error_info()
def ExecShell(cmdstring, cwd=None, timeout=None, shell=True):
if shell:
cmdstring_list = cmdstring
else:
cmdstring_list = shlex.split(cmdstring)
if timeout:
end_time = datetime.datetime.now() + datetime.timedelta(seconds=timeout)
sub = subprocess.Popen(cmdstring_list, cwd=cwd, stdin=subprocess.PIPE,shell=shell,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
while sub.poll() is None:
time.sleep(0.1)
if timeout:
if end_time <= datetime.datetime.now():
raise Exception("Timeout%s"%cmdstring)
a,e = sub.communicate()
if type(a) == bytes:
try:
a = a.decode('utf-8')
except :
a = a.decode('gb2312','ignore')
if type(e) == bytes:
try:
e = e.decode('utf-8')
except :
e = e.decode('gb2312','ignore')
return a,e
def GetRandomString(length):
from random import Random
strings = ''
chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789'
chrlen = len(chars) - 1
random = Random()
for i in range(length):
strings += chars[random.randint(0, chrlen)]
return strings
def GetRandomString1(length):
from random import Random
strings = ''
chars = '0123456789'
chrlen = len(chars) - 1
random = Random()
for i in range(length):
strings += chars[random.randint(0, chrlen)]
return strings
def GetRandomString2(length):
from random import Random
strings = ''
chars = '!@#$%^&*()_+.,?[]-='
chrlen = len(chars) - 1
random = Random()
for i in range(length):
strings += chars[random.randint(0, chrlen)]
return strings
def chdck_salt():
sql = Sql()
sql.table('users').execute("ALTER TABLE 'users' ADD 'salt' TEXT",())
u_list = sql.table('users').field('id,username,password,salt').select()
for u_info in u_list:
salt = GetRandomString(12) #12位随机
pdata = {}
pdata['password'] = md5(md5(u_info['password']+'_bt.cn') + salt)
pdata['salt'] = salt
sql.table('users').where('id=?',(u_info['id'],)).update(pdata)
def md5(strings):
"""
生成MD5
@strings 要被处理的字符串
return string(32)
"""
import hashlib
m = hashlib.md5()
m.update(strings.encode('utf-8'))
return m.hexdigest()
def password_salt(password,username=None,uid=None):
chdck_salt()
sql = Sql()
if not uid:
if not username:
raise Exception('username或uid必需传一项')
uid = sql.table('users').where('username=?',(username,)).getField('id')
salt = sql.table('users').where('id=?',(uid,)).getField('salt')
return md5(md5(password+'_bt.cn')+salt)
def check_user(username):
resume = 0
while True:
data, total, resume = win32net.NetUserEnum(None, 3, win32netcon.FILTER_NORMAL_ACCOUNT, resume)
for user in data:
if user['name'] == username: return True
if not resume: break
return False
def add_user(username,password,ps):
try:
if not check_user(username):
d = {}
d['name'] = username
d['password'] = password
d['comment'] = ps
d['flags'] = win32netcon.UF_NORMAL_ACCOUNT | win32netcon.UF_SCRIPT
d['priv'] = win32netcon.USER_PRIV_USER
win32net.NetUserAdd(None, 1, d)
#设置用户允许登录服务
handle = win32security.LsaOpenPolicy(None, win32security.POLICY_ALL_ACCESS)
sid_obj, domain, tmp = win32security.LookupAccountName(None, username)
win32security.LsaAddAccountRights(handle, sid_obj, ('SeServiceLogonRight',) )
win32security.LsaClose( handle)
if not check_user(username): return False, '添加用户[{}]失败.'.format(username)
writeFile('{}/data/{}'.format(panelPath,username),password)
return True , None
else:
ExecShell('net user "{}" "{}"'.format(username,password))
writeFile('{}/data/{}'.format(panelPath,username),password)
return True , None
except :
return False,get_error_info()
def add_user_bywww():
pwd = GetRandomString(64) + GetRandomString1(32) + GetRandomString2(32)
status,error = add_user('www',pwd,'用于启动宝塔安装的程序,删除后会导致部分软件无法启动,请勿删除')
if not status:
writeFile(error_path,error)
return False
return True
def add_user_bymysql():
pwd = GetRandomString(64) + GetRandomString1(32) + GetRandomString2(32)
status,error = add_user('mysql',pwd,'用于启动宝塔安装的程序,删除后会导致部分软件无法启动,请勿删除')
if not status:
writeFile(error_path,error)
return False
return True
def getIP(url):
import socket,re
tmp = re.search('http://(.+)\:\d*',url)
if tmp:
domain = tmp.groups()[0]
myaddr = socket.getaddrinfo(domain, 'http')
return myaddr[0][4][0]
return ''
def add_panel_dir():
try:
slist = [
[panelPath , [] ],
['{}/data'.format(panelPath) , [] ],
['{}/script'.format(panelPath) , [] ],
['{}/backup'.format(panelPath) , [] ],
['{}/backup/database/sqlserver'.format(setupPath[:2]) , [ 'Authenticated Users']],
['{}/wwwroot'.format(setupPath[:2]) , [ 'IIS_IUSRS','www'] ],
['{}/wwwlogs'.format(setupPath) , [ 'IIS_IUSRS','www'] ],
['{}/php'.format(setupPath) , [ 'IIS_IUSRS','www'] ],
['{}/mysql'.format(setupPath) , [ 'mysql'] ],
['{}/temp'.format(setupPath) , [ 'IIS_IUSRS','www'] ],
['{}/temp/session'.format(setupPath) , [ 'IIS_IUSRS','www'] ],
['C:/Temp' , [ 'IIS_IUSRS','www'] ],
]
is_break = False
for sobj in slist:
if not os.path.exists(sobj[0]):
os.makedirs(sobj[0])
n = 0
while n < 5:
if os.path.exists(sobj[0]): break
os.makedirs(sobj[0])
time.sleep(0.5)
n += 1
if not os.path.exists(sobj[0]):
writeFile(error_path,"自动创建目录【{}】失败,已重试最大次数 5 次,请手动创建该目录后重新安装".format(sobj[0]))
return False
del_file_access(sobj[0],'users')
for user in sobj[1]:
n = 0
while n < 3:
status,error = set_file_access(sobj[0],user,2032127)
if status: break
time.sleep(0.5)
if not status:
writeFile(error_path,"目录{}设置{}权限设置错误 -> {}".format(sobj[0],user,error))
break
del_file_access(setupPath,'users')
url = get_url()
files = ['default.db','session.db','system.db','phplib.win','defaultDoc.html','404.html']
for f_name in files:
local_path = '{}/data/{}'.format(panelPath,f_name)
download_url = '{}/win/panel/data/{}'.format(url,f_name)
n = 0
while n < 10:
n += 1;
try:
if os.path.exists(local_path) and os.path.getsize(local_path) < 10: os.remove(local_path)
if not os.path.exists(local_path): downloadFileByWget(download_url,local_path)
if os.path.getsize(local_path) and os.path.getsize(local_path) > 10: break;
writeFile(error_path,'download {} error ->> {} \r\n {}'.format(f_name,download_url,""))
except :
ip = getIP(url)
writeFile(error_path,'download {} error ->> {} \r\n connect {} \r\n {}'.format(ip,f_name,download_url,get_error_info()))
if n > 5: return False
time.sleep(0.2)
return True
except :
writeFile(error_path,get_error_info())
return False
def unzip(src_path,dst_path):
import zipfile
zip_file = zipfile.ZipFile(src_path)
for names in zip_file.namelist():
zip_file.extract(names,dst_path)
zip_file.close()
return True
def to_path(path):
return path.replace('/','\\')
def download_panel(file_list = []):
try:
url = 'http://www.example.com'
ExecShell("taskkill /f /t /im BtTools.exe")
#下载面板
loacl_path = setupPath + '/panel.zip'
tmpPath = "{}/temp/panel".format(setupPath)
if os.path.exists(loacl_path): os.remove(loacl_path)
if os.path.exists(tmpPath): shutil.rmtree(tmpPath,True)
if not os.path.exists(tmpPath): os.makedirs(tmpPath)
p_ver = sys.argv[2]
downUrl = url + '/win/panel/panel_' + p_ver + '.zip';
downloadFileByWget(downUrl,loacl_path);
unzip(loacl_path,tmpPath)
for ff_path in file_list:
if os.path.exists(tmpPath + '/' + ff_path): os.remove(tmpPath + '/' + ff_path)
tcPath = '{}\class'.format(tmpPath)
for name in os.listdir(tcPath):
try:
if name.find('win_amd64.pyd') >=0:
oldName = os.path.join(tcPath,name);
lName = name.split('.')[0] + '.pyd'
newName = os.path.join(tcPath,lName)
if not os.path.exists(newName):os.rename(oldName,newName)
except :pass
cPath = '{}/panel/class'.format(setupPath)
if os.path.exists(cPath):
os.system("del /s {}\*.pyc".format(to_path(cPath)))
os.system("del /s {}\*.pyt".format(to_path(cPath)))
for name in os.listdir(cPath):
try:
if name.find('.pyd') >=0:
oldName = os.path.join(cPath,name)
newName = os.path.join(cPath,GetRandomString(8) + '.pyt')
os.rename(oldName,newName)
except : pass
os.system("del /s {}\*.pyc".format(to_path(cPath)))
os.system("del /s {}\*.pyt".format(to_path(cPath)))
os.system("xcopy /s /c /e /y /r {} {}".format(to_path(tmpPath),to_path(panelPath)))
try:
os.remove(loacl_path)
except : pass
try:
shutil.rmtree(tmpPath,True)
except : pass
s_ver = platform.platform()
net_v = '45'
if s_ver.find('2008') >= 0: net_v = '20'
writeFile('{}/data/net'.format(setupPath),net_v)
not_workorder_path = '{}/data/not_workorder.pl'.format(panelPath)
if not os.path.exists(not_workorder_path):
writeFile(not_workorder_path,'True')
bind_path = '{}/data/bind_path.pl'.format(panelPath)
if os.path.exists(bind_path):
os.remove(bind_path)
userinfo_path = '{}/data/userInfo.json'.format(panelPath)
if not os.path.exists(userinfo_path):
writeFile(userinfo_path,'{"uid":1,"username":"Administrator","address":"127.0.0.1","serverid":"1","access_key":"test","secret_key":"123456","ukey":"123456","state":1}')
local_path = '{}/temp/api.py'.format(setupPath)
downloadFileByWget('{}/win/panel/data/api.py'.format(url),local_path)
if os.path.exists(local_path):
os.remove('C:/Program Files/python/Lib/site-packages/requests/api.py')
shutil.move(local_path,'C:/Program Files/python/Lib/site-packages/requests')
local_path = '{}/script/BtTools.exe'.format(panelPath)
downloadFileByWget('{}/win/panel/BtTools{}.exe'.format(url,net_v),local_path)
if os.path.getsize(local_path) > 128:
return True
return False
downloadFileByWget('{}/win/panel/data/softList.conf'.format(url),'{}/data/softList.conf'.format(panelPath))
try:
from gevent import monkey
except :
os.system('"C:\Program Files\python\python.exe" -m pip install gevent')
except :
writeFile(error_path,get_error_info())
def update_panel():
file_list = ['config/config.json','config/index.json','data/libList.conf','data/plugin.json']
download_panel(file_list)
py_path = 'C:/Program Files/python/python.exe'
ExecShell("\"{}\" {}/panel/runserver.py --startup auto install".format(py_path,setupPath))
ExecShell("\"{}\" {}/panel/task.py --startup auto install".format(py_path,setupPath))
print("升级成功,重启面板后生效..")
def init_panel_data():
try:
sql = Sql()
username = sql.table('users').where('id=?',(1,)).getField('username')
if username == 'admin':
username = GetRandomString(8)
password = GetRandomString(8)
writeFile(panelPath + '/data/default.pl',password)
sql.table('users').where('id=?',(1,)).setField('username',username)
pwd = password_salt(md5(password),uid=1)
result = sql.table('users').where('id=?',(1,)).setField('password',pwd)
backup_path = panelPath[:2] + '/backup'
www_path = panelPath[:2] + '/wwwroot'
if not os.path.exists(backup_path): os.makedirs(backup_path)
if not os.path.exists(www_path): os.makedirs(www_path)
sql.table('config').where('id=?',(1,)).setField('backup_path',backup_path)
sql.table('config').where('id=?',(1,)).setField('sites_path',www_path)
bind_path = panelPath+ '/data/bind_path.pl'
if not os.path.exists(bind_path): writeFile(bind_path,'True')
admin_path = panelPath+ '/data/admin_path.pl'
if not os.path.exists(admin_path): writeFile(admin_path,"/" + GetRandomString(8))
port_path = panelPath+ '/data/port.pl'
if not os.path.exists(port_path): writeFile(port_path,'8888')
recycle_bin_db = panelPath+ '/data/recycle_bin_db.pl'
if not os.path.exists(recycle_bin_db): writeFile(recycle_bin_db,'True')
recycle_bin = panelPath+ '/data/recycle_bin.pl'
if not os.path.exists(recycle_bin): writeFile(recycle_bin,'True')
conf_path = panelPath + '/config/config.json'
if os.path.exists(conf_path):
conf = readFile(conf_path).replace('[PATH]',setupPath.replace('\\','/'))
writeFile(conf_path,conf)
GetLocalIp()
return True
except :
writeFile(error_path,get_error_info())
return False
def add_panel_services(num = 0):
try:
py_path = 'C:/Program Files/python/python.exe'
delete_server('btPanel')
ret = ExecShell("\"{}\" {}/panel/runserver.py --startup auto install".format(py_path,setupPath))
delete_server('btTask')
ret1 = ExecShell("\"{}\" {}/panel/task.py --startup auto install".format(py_path,setupPath))
if get_server_status('btPanel') < 0 or get_server_status('btTask') < 0:
if num <= 0 :
localPath = setupPath + "/temp/Time_Zones.reg";
downloadFileByWget(get_url() + '/win/panel/data/Time_Zones.reg',localPath)
ExecShell("regedit /s " + localPath)
add_panel_services(1)
else:
writeFile(error_path,ret[0] + ret[1] + ret1[0] + ret1[1])
else:
os.system('sc failure btPanel reset=1800 actions=restart/60000/restart/120000/restart/30000')
os.system('sc failure btTask reset=1800 actions=restart/60000/restart/120000/restart/30000')
start_service('btPanel')
start_service('btTask')
except :
writeFile(error_path,get_error_info())
def add_firewall_byport():
conf = ExecShell('netsh advfirewall firewall show rule "宝塔面板"')[0]
if conf.lower().find('tcp') == -1:
ExecShell("netsh advfirewall firewall add rule name=宝塔面板 dir=in action=allow protocol=tcp localport=8888");
ExecShell("netsh advfirewall firewall add rule name=网站访问端口 dir=in action=allow protocol=tcp localport=80");
ExecShell("netsh advfirewall firewall add rule name=远程桌面 dir=in action=allow protocol=tcp localport=3389");
ExecShell("netsh advfirewall firewall add rule name=HTTPS端口 dir=in action=allow protocol=tcp localport=443");
ExecShell("netsh advfirewall firewall add rule name=FTP主动端口 dir=in action=allow protocol=tcp localport=21");
ExecShell("netsh advfirewall firewall add rule name=FTP被动端口 dir=in action=allow protocol=tcp localport=3000-4000");
def get_error_log():
error = readFile(error_path)
try:
data = {}
data['msg'] = 'setup'
data['os'] = 'Windows'
data['error'] = error
data['version'] = ''
httpPost('http://www.example.com/api/wpanel/PanelBug',data)
except :
pass
return error
if __name__ == "__main__":
stype = sys.argv[1];
if not stype in ['get_error_log']:
if os.path.exists(error_path): os.remove(error_path)
result = eval('{}()'.format(stype))
print(result)