def batchPasteApi(self): path = request.form.get('path', '').encode('utf-8') stype = request.form.get('type', '').encode('utf-8') # filename = request.form.get('filename', '').encode('utf-8') import shutil if not self.checkDir(path): return mw.returnJson(False, '请不要花样作死!') i = 0 myfiles = json.loads(session['selected']['data']) l = len(myfiles) if stype == '1': for key in myfiles: i += 1 mw.writeSpeed(key, i, l) try: sfile = session['selected']['path'] + '/' + key.encode( 'utf-8') dfile = path + '/' + key.encode('utf-8') if os.path.isdir(sfile): shutil.copytree(sfile, dfile) else: shutil.copyfile(sfile, dfile) stat = os.stat(sfile) os.chown(dfile, stat.st_uid, stat.st_gid) except: continue msg = mw.getInfo('从[{1}]批量复制到[{2}]成功', ( session['selected']['path'], path, )) mw.writeLog('文件管理', msg) else: for key in myfiles: try: i += 1 mw.writeSpeed(key, i, l) sfile = session['selected']['path'] + '/' + key.encode( 'utf-8') dfile = path + '/' + key.encode('utf-8') shutil.move(sfile, dfile) except: continue msg = mw.getInfo('从[{1}]批量移动到[{2}]成功', ( session['selected']['path'], path, )) mw.writeLog('文件管理', msg) mw.writeSpeed(None, 0, 0) errorCount = len(myfiles) - i del (session['selected']) msg = mw.getInfo('批量操作成功[{1}],失败[{2}]', (str(i), str(errorCount))) return mw.returnJson(True, msg)
def doLogin(): username = request.form.get('username', '').strip() password = request.form.get('password', '').strip() code = request.form.get('code', '').strip() # print(session) if 'code' in session: if session['code'] != mw.md5(code): return mw.returnJson(False, '验证码错误,请重新输入!') userInfo = mw.M('users').where("id=?", (1, )).field('id,username,password').find() # print(userInfo) # print(password) password = mw.md5(password) # print('md5-pass', password) login_cache_count = 5 login_cache_limit = cache.get('login_cache_limit') filename = 'data/close.pl' if os.path.exists(filename): return mw.returnJson(False, '面板已经关闭!') if userInfo['username'] != username or userInfo['password'] != password: msg = "<a style='color: red'>密码错误</a>,帐号:{1},密码:{2},登录IP:{3}", (( '****', '******', request.remote_addr)) if login_cache_limit == None: login_cache_limit = 1 else: login_cache_limit = int(login_cache_limit) + 1 if login_cache_limit >= login_cache_count: mw.writeFile(filename, 'True') return mw.returnJson(False, '面板已经关闭!') cache.set('login_cache_limit', login_cache_limit, timeout=10000) login_cache_limit = cache.get('login_cache_limit') mw.writeLog('用户登录', mw.getInfo(msg)) return mw.returnJson( False, mw.getInfo("用户名或密码错误,您还可以尝试[{1}]次!", (str(login_cache_count - login_cache_limit)))) cache.delete('login_cache_limit') session['login'] = True session['username'] = userInfo['username'] #print('do_login', session) # fix 跳转时,数据消失,可能是跨域问题 mw.writeFile('data/api_login.txt', userInfo['username']) return mw.returnJson(True, '登录成功,正在跳转...')
def mvRecycleBin(self, path): rPath = self.rPath if not os.path.exists(rPath): os.system('mkdir -p ' + rPath) rFile = rPath + path.replace('/', '_mw_') + '_t_' + str(time.time()) try: import shutil shutil.move(path, rFile) mw.writeLog('文件管理', mw.getInfo('移动文件[{1}]到回收站成功!', (path))) return True except: mw.writeLog('文件管理', mw.getInfo('移动文件[{1}]到回收站失败!', (path))) return False
def reRecycleBinApi(self): rPath = self.rPath path = request.form.get('path', '').encode('utf-8') dFile = path.replace('_mw_', '/').split('_t_')[0] try: import shutil shutil.move(rPath + path, dFile) msg = mw.getInfo('移动文件[{1}]到回收站成功!', (dFile, )) mw.writeLog('文件管理', msg) return mw.returnJson(True, '恢复成功!') except Exception as e: msg = mw.getInfo('从回收站恢复[{1}]失败!', (dFile, )) mw.writeLog('文件管理', msg) return mw.returnJson(False, '恢复失败!')
def setDbPs(): args = getArgs() data = checkArgs(args, ['id', 'name', 'ps']) if not data[0]: return data[1] ps = args['ps'] sid = args['id'] name = args['name'] try: psdb = pSqliteDb('databases') psdb.where("id=?", (sid,)).setField('ps', ps) return mw.returnJson(True, mw.getInfo('修改数据库[{1}]备注成功!', (name,))) except Exception as e: return mw.returnJson(True, mw.getInfo('修改数据库[{1}]备注失败!', (name,)))
def setSshPortApi(self): port = request.form.get('port', '1').strip() if int(port) < 22 or int(port) > 65535: return mw.returnJson(False, '端口范围必需在22-65535之间!') ports = ['21', '25', '80', '443', '7200', '8080', '888', '8888'] if port in ports: return mw.returnJson(False, '(' + port + ')' + '特殊端口不可设置!') file = '/etc/ssh/sshd_config' conf = mw.readFile(file) rep = "#*Port\s+([0-9]+)\s*\n" conf = re.sub(rep, "Port " + port + "\n", conf) mw.writeFile(file, conf) if self.__isFirewalld: mw.execShell('setenforce 0') mw.execShell( 'sed -i "s#SELINUX=enforcing#SELINUX=disabled#" /etc/selinux/config') mw.execShell("systemctl restart sshd.service") elif self.__isUfw: mw.execShell('ufw allow ' + port + '/tcp') mw.execShell("service ssh restart") else: mw.execShell( 'iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport ' + port + ' -j ACCEPT') mw.execShell("/etc/init.d/sshd restart") self.firewallReload() # mw.M('firewall').where( # "ps=?", ('SSH远程管理服务',)).setField('port', port) msg = mw.getInfo('改SSH端口为[{1}]成功!', port) mw.writeLog("防火墙管理", msg) return mw.returnJson(True, '修改成功!')
def addDropAddressApi(self): import re port = request.form.get('port', '').strip() ps = request.form.get('ps', '').strip() rep = "^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(\/\d{1,2})?$" if not re.search(rep, port): return mw.returnJson(False, '您输入的IP地址不合法!') address = port if mw.M('firewall').where("port=?", (address,)).count() > 0: return mw.returnJson(False, '您要放屏蔽的IP已存在屏蔽列表,无需重复处理!') if self.__isUfw: mw.execShell('ufw deny from ' + address + ' to any') else: if self.__isFirewalld: cmd = 'firewall-cmd --permanent --add-rich-rule=\'rule family=ipv4 source address="' + \ address + '" drop\'' mw.execShell(cmd) else: cmd = 'iptables -I INPUT -s ' + address + ' -j DROP' mw.execShell(cmd) msg = mw.getInfo('屏蔽IP[{1}]成功!', (address,)) mw.writeLog("防火墙管理", msg) addtime = time.strftime('%Y-%m-%d %X', time.localtime()) mw.M('firewall').add('port,ps,addtime', (address, ps, addtime)) self.firewallReload() return mw.returnJson(True, '添加成功!')
def delDropAddressApi(self): if not self.getFwStatus(): return mw.returnJson(False, '防火墙启动时,才能删除规则!') port = request.form.get('port', '').strip() ps = request.form.get('ps', '').strip() sid = request.form.get('id', '').strip() address = port if self.__isUfw: mw.execShell('ufw delete deny from ' + address + ' to any') else: if self.__isFirewalld: mw.execShell( 'firewall-cmd --permanent --remove-rich-rule=\'rule family=ipv4 source address="' + address + '" drop\'') elif self.__isMac: pass else: cmd = 'iptables -D INPUT -s ' + address + ' -j DROP' mw.execShell(cmd) msg = mw.getInfo('解除IP[{1}]的屏蔽!', (address,)) mw.writeLog("防火墙管理", msg) mw.M('firewall').where("id=?", (sid,)).delete() self.firewallReload() return mw.returnJson(True, '删除成功!')
def addAcceptPortApi(self): if not self.getFwStatus(): return mw.returnJson(False, '防火墙启动时,才能添加规则!') import re import time port = request.form.get('port', '').strip() ps = request.form.get('ps', '').strip() stype = request.form.get('type', '').strip() rep = "^\d{1,5}(:\d{1,5})?$" if not re.search(rep, port): return mw.returnJson(False, '端口范围不正确!') if mw.M('firewall').where("port=?", (port,)).count() > 0: return mw.returnJson(False, '您要放行的端口已存在,无需重复放行!') msg = mw.getInfo('放行端口[{1}]成功', (port,)) mw.writeLog("防火墙管理", msg) addtime = time.strftime('%Y-%m-%d %X', time.localtime()) mw.M('firewall').add('port,ps,addtime', (port, ps, addtime)) self.addAcceptPort(port) self.firewallReload() return mw.returnJson(True, '添加放行(' + port + ')端口成功!')
def delAcceptPortApi(self): port = request.form.get('port', '').strip() sid = request.form.get('id', '').strip() mw_port = mw.readFile('data/port.pl') try: if(port == mw_port): return mw.returnJson(False, '失败,不能删除当前面板端口!') if self.__isUfw: mw.execShell('ufw delete allow ' + port + '/tcp') else: if self.__isFirewalld: mw.execShell( 'firewall-cmd --permanent --zone=public --remove-port=' + port + '/tcp') mw.execShell( 'firewall-cmd --permanent --zone=public --remove-port=' + port + '/udp') else: mw.execShell( 'iptables -D INPUT -p tcp -m state --state NEW -m tcp --dport ' + port + ' -j ACCEPT') msg = mw.getInfo('删除防火墙放行端口[{1}]成功!', (port,)) mw.writeLog("防火墙管理", msg) mw.M('firewall').where("id=?", (sid,)).delete() self.firewallReload() return mw.returnJson(True, '删除成功!') except Exception as e: return mw.returnJson(False, '删除失败!:' + str(e))
def syncToDatabases(): args = getArgs() data = checkArgs(args, ['type', 'ids']) if not data[0]: return data[1] pdb = pMysqlDb() result = pdb.execute("show databases") isError = isSqlError(result) if isError: return isError stype = int(args['type']) psdb = pSqliteDb('databases') n = 0 if stype == 0: data = psdb.field('id,name,username,password,accept').select() for value in data: result = toDbBase(value) if result == 1: n += 1 else: data = json.loads(args['ids']) for value in data: find = psdb.where("id=?", (value,)).field( 'id,name,username,password,accept').find() # print find result = toDbBase(find) if result == 1: n += 1 msg = mw.getInfo('本次共同步了{1}个数据库!', (str(n),)) return mw.returnJson(True, msg)
def setFileAccessApi(self): if mw.isAppleSystem(): return mw.returnJson(True, '开发机不设置!') filename = request.form.get('filename', '').encode('utf-8') user = request.form.get('user', '').encode('utf-8') access = request.form.get('access', '755') sall = '-R' try: if not self.checkDir(filename): return mw.returnJson(False, '请不要花样作死') if not os.path.exists(filename): return mw.returnJson(False, '指定文件不存在!') os.system('chmod ' + sall + ' ' + access + " '" + filename + "'") os.system('chown ' + sall + ' ' + user + ':' + user + " '" + filename + "'") msg = mw.getInfo('设置[{1}]权限为[{2}]所有者为[{3}]', ( filename, access, user, )) mw.writeLog('文件管理', msg) return mw.returnJson(True, '设置成功!') except: return mw.returnJson(False, '设置失败!')
def getBootTime(self): # 取系统启动时间 start_time = psutil.boot_time() run_time = time.time() - start_time # conf = mw.readFile('/proc/uptime').split() tStr = float(run_time) min = tStr / 60 hours = min / 60 days = math.floor(hours / 24) hours = math.floor(hours - (days * 24)) min = math.floor(min - (days * 60 * 24) - (hours * 60)) return mw.getInfo('已不间断运行: {1}天{2}小时{3}分钟', (str(int(days)), str(int(hours)), str(int(min))))
def setUserPwd(): args = getArgs() data = checkArgs(args, ['password', 'name']) if not data[0]: return data[1] newpassword = args['password'] username = args['name'] id = args['id'] try: pdb = pMysqlDb() psdb = pSqliteDb('databases') name = psdb.where('id=?', (id,)).getField('name') m_version = mw.readFile(getServerDir() + '/version.pl') if m_version.find('5.7') == 0 or m_version.find('8.0') == 0: tmp = pdb.query( "select Host from mysql.user where User='******' AND Host!='localhost'") accept = mapToList(tmp) pdb.execute( "update mysql.user set authentication_string='' where User='******'") result = pdb.execute( "ALTER USER `%s`@`localhost` IDENTIFIED BY '%s'" % (username, newpassword)) for my_host in accept: pdb.execute("ALTER USER `%s`@`%s` IDENTIFIED BY '%s'" % ( username, my_host[0], newpassword)) else: result = pdb.execute("update mysql.user set Password=password('" + newpassword + "') where User='******'") isError = isSqlError(result) if isError != None: return isError pdb.execute("flush privileges") psdb.where("id=?", (id,)).setField('password', newpassword) return mw.returnJson(True, mw.getInfo('修改数据库[{1}]密码成功!', (name,))) except Exception as ex: # print str(ex) return mw.returnJson(False, mw.getInfo('修改数据库[{1}]密码失败!', (name,)))
def createDirApi(self): path = request.form.get('path', '').encode('utf-8') try: if not self.checkFileName(path): return mw.returnJson(False, '目录名中不能包含特殊字符!') if os.path.exists(path): return mw.returnJson(False, '指定目录已存在!') os.makedirs(path) self.setFileAccept(path) msg = mw.getInfo('创建目录[{1}]成功!', (path, )) mw.writeLog('文件管理', msg) return mw.returnJson(True, '目录创建成功!') except Exception as e: return mw.returnJson(False, '目录创建失败!')
def copyDir(self, sfile, dfile): if not os.path.exists(sfile): return mw.returnJson(False, '指定目录不存在!') if os.path.exists(dfile): return mw.returnJson(False, '指定目录已存在!') import shutil try: shutil.copytree(sfile, dfile) stat = os.stat(sfile) os.chown(dfile, stat.st_uid, stat.st_gid) msg = mw.getInfo('复制目录[{1}]到[{2}]成功!', (sfile, dfile)) mw.writeLog('文件管理', msg) return mw.returnJson(True, '目录复制成功!') except: return mw.returnJson(False, '目录复制失败!')
def setFpmConfig(version): args = getArgs() # if not 'max' in args: # return 'missing time args!' version = args['version'] max_children = args['max_children'] start_servers = args['start_servers'] min_spare_servers = args['min_spare_servers'] max_spare_servers = args['max_spare_servers'] pm = args['pm'] file = getServerDir() + '/' + version + '/etc/php-fpm.d/www.conf' conf = mw.readFile(file) rep = "\s*pm.max_children\s*=\s*([0-9]+)\s*" conf = re.sub(rep, "\npm.max_children = " + max_children, conf) rep = "\s*pm.start_servers\s*=\s*([0-9]+)\s*" conf = re.sub(rep, "\npm.start_servers = " + start_servers, conf) rep = "\s*pm.min_spare_servers\s*=\s*([0-9]+)\s*" conf = re.sub(rep, "\npm.min_spare_servers = " + min_spare_servers, conf) rep = "\s*pm.max_spare_servers \s*=\s*([0-9]+)\s*" conf = re.sub(rep, "\npm.max_spare_servers = " + max_spare_servers + "\n", conf) rep = "\s*pm\s*=\s*(\w+)\s*" conf = re.sub(rep, "\npm = " + pm + "\n", conf) mw.writeFile(file, conf) reload(version) msg = mw.getInfo( '设置PHP-{1}并发设置,max_children={2},start_servers={3},min_spare_servers={4},max_spare_servers={5}', ( version, max_children, start_servers, min_spare_servers, max_spare_servers, )) mw.writeLog('插件管理[PHP]', msg) return mw.returnJson(True, '设置成功!')
def createFileApi(self): file = request.form.get('path', '').encode('utf-8') try: if not self.checkFileName(file): return mw.returnJson(False, '文件名中不能包含特殊字符!') if os.path.exists(file): return mw.returnJson(False, '指定文件已存在!') _path = os.path.dirname(file) if not os.path.exists(_path): os.makedirs(_path) open(file, 'w+').close() self.setFileAccept(file) msg = mw.getInfo('创建文件[{1}]成功!', (file, )) mw.writeLog('文件管理', msg) return mw.returnJson(True, '文件创建成功!') except Exception as e: # print str(e) return mw.returnJson(True, '文件创建失败!')
def delete(self, path): if not os.path.exists(path): return mw.returnJson(False, '指定文件不存在!') # 检查是否为.user.ini if path.find('.user.ini') >= 0: os.system("chattr -i '" + path + "'") try: if os.path.exists('data/recycle_bin.pl'): if self.mvRecycleBin(path): return mw.returnJson(True, '已将文件移动到回收站!') os.remove(path) mw.writeLog('文件管理', mw.getInfo('删除文件[{1}]成功!', (path))) return mw.returnJson(True, '删除文件成功!') except: return mw.returnJson(False, '删除文件失败!')
def delRecycleBinApi(self): rPath = self.rPath path = request.form.get('path', '').encode('utf-8') empty = request.form.get('empty', '').encode('utf-8') dFile = path.split('_t_')[0] if not self.checkDir(path): return mw.returnJson(False, '敏感目录,请不要花样作死!') os.system('which chattr && chattr -R -i ' + rPath + path) if os.path.isdir(rPath + path): import shutil shutil.rmtree(rPath + path) else: os.remove(rPath + path) tfile = path.replace('_mw_', '/').split('_t_')[0] msg = mw.getInfo('已彻底从回收站删除{1}!', (tfile, )) mw.writeLog('文件管理', msg) return mw.returnJson(True, msg)
def setDisableFunc(version): filename = mw.getServerDir() + '/php/' + version + '/etc/php.ini' if not os.path.exists(filename): return mw.returnJson(False, '指定PHP版本不存在!') args = getArgs() disable_functions = args['disable_functions'] phpini = mw.readFile(filename) rep = "disable_functions\s*=\s*.*\n" phpini = re.sub(rep, 'disable_functions = ' + disable_functions + "\n", phpini) msg = mw.getInfo('修改PHP-{1}的禁用函数为[{2}]', ( version, disable_functions, )) mw.writeLog('插件管理[PHP]', msg) mw.writeFile(filename, phpini) reload(version) return mw.returnJson(True, '设置成功!')
def setMaxSize(version): args = getArgs() if not 'max' in args: return 'missing time args!' max = args['max'] if int(max) < 2: return mw.returnJson(False, '上传大小限制不能小于2MB!') path = getServerDir() + '/' + version + '/etc/php.ini' conf = mw.readFile(path) rep = u"\nupload_max_filesize\s*=\s*[0-9]+M" conf = re.sub(rep, u'\nupload_max_filesize = ' + max + 'M', conf) rep = u"\npost_max_size\s*=\s*[0-9]+M" conf = re.sub(rep, u'\npost_max_size = ' + max + 'M', conf) mw.writeFile(path, conf) msg = mw.getInfo('设置PHP-{1}最大上传大小为[{2}MB]!', ( version, max, )) mw.writeLog('插件管理[PHP]', msg) return mw.returnJson(True, '设置成功!')
def mvFileApi(self): sfile = request.form.get('sfile', '').encode('utf-8') dfile = request.form.get('dfile', '').encode('utf-8') if not self.checkFileName(dfile): return mw.returnJson(False, '文件名中不能包含特殊字符!') if not os.path.exists(sfile): return mw.returnJson(False, '指定文件不存在!') if not self.checkDir(sfile): return mw.returnJson(False, 'FILE_DANGER') import shutil try: shutil.move(sfile, dfile) msg = mw.getInfo('移动文件或目录[{1}]到[{2}]成功!', ( sfile, dfile, )) mw.writeLog('文件管理', msg) return mw.returnJson(True, '移动文件或目录成功!') except: return mw.returnJson(False, '移动文件或目录失败!')
def uploadFileApi(self): from werkzeug.utils import secure_filename from flask import request path = request.args.get('path', '') if not os.path.exists(path): os.makedirs(path) f = request.files['zunfile'] filename = os.path.join(path, f.filename) s_path = path if os.path.exists(filename): s_path = filename p_stat = os.stat(s_path) f.save(filename) os.chown(filename, p_stat.st_uid, p_stat.st_gid) os.chmod(filename, p_stat.st_mode) msg = mw.getInfo('上传文件[{1}] 到 [{2}]成功!', (filename, path)) mw.writeLog('文件管理', msg) return mw.returnMsg(True, '上传成功!')
def copyFileApi(self): sfile = request.form.get('sfile', '').encode('utf-8') dfile = request.form.get('dfile', '').encode('utf-8') if not os.path.exists(sfile): return mw.returnJson(False, '指定文件不存在!') if os.path.isdir(sfile): return self.copyDir(sfile, dfile) import shutil try: shutil.copyfile(sfile, dfile) msg = mw.getInfo('复制文件[{1}]到[{2}]成功!', ( sfile, dfile, )) mw.writeLog('文件管理', msg) stat = os.stat(sfile) os.chown(dfile, stat.st_uid, stat.st_gid) return mw.returnJson(True, '文件复制成功!') except: return mw.returnJson(False, '文件复制失败!')
def syncGetDatabases(): pdb = pMysqlDb() psdb = pSqliteDb('databases') data = pdb.query('show databases') isError = isSqlError(data) if isError != None: return isError users = pdb.query( "select User,Host from mysql.user where User!='root' AND Host!='localhost' AND Host!=''") nameArr = ['information_schema', 'performance_schema', 'mysql', 'sys'] n = 0 for value in data: b = False for key in nameArr: if value[0] == key: b = True break if b: continue if psdb.where("name=?", (value[0],)).count(): continue host = '127.0.0.1' for user in users: if value[0] == user[0]: host = user[1] break ps = mw.getMsg('INPUT_PS') if value[0] == 'test': ps = mw.getMsg('DATABASE_TEST') addTime = time.strftime('%Y-%m-%d %X', time.localtime()) if psdb.add('name,username,password,accept,ps,addtime', (value[0], value[0], '', host, ps, addTime)): n += 1 msg = mw.getInfo('本次共从服务器获取了{1}个数据库!', (str(n),)) return mw.returnJson(True, msg)