#coding: utf-8
#-------------------------------------------------------------------
# 宝塔Linux面板
#-------------------------------------------------------------------
# Copyright (c) 2015-2099 宝塔软件(http://bt.cn) All rights reserved.
#-------------------------------------------------------------------
# Author: hwliang <hwl@bt.cn>
#-------------------------------------------------------------------

#------------------------------
# sqlite模型
#------------------------------
import os,sys,re,json,shutil,psutil,time
from databaseModel.base import databaseBase
import public,panelMysql
try:
    from BTPanel import session
except :pass

import datatool
class main(databaseBase,datatool.datatools):

    sid = 0
    _version = None
    _setup_path = None

    def __init__(self):

        ndb = public.M('databases').order("id desc").field('id,pid,name,username,password,accept,ps,addtime,type').select()
        if type(ndb) == str:
            public.M('databases').execute("alter TABLE databases add type TEXT DEFAULT MySQL",());

        if public.get_server_status("mysql") >=0 :
            self._version = re.search('([MySQL|MariaDB-]+\d+\.\d+)',public.get_server_path('mysql')).groups()[0]
            self._setup_path  = public.GetConfigValue('setup_path') + '/mysql/' + self._version

    def get_list(self,args):
        """
        @获取数据库列表
        @sql_type = mysql
        """
        return self.get_base_list(args, sql_type = 'mysql')

    def GetCloudServer(self,args):
        '''
            @name 获取远程服务器列表
            @author hwliang<2021-01-10>
            @return list
        '''
        return self.GetBaseCloudServer(args)


    def AddCloudServer(self,args):
        '''
        @添加远程数据库
        '''
        return self.AddBaseCloudServer(args)

    def RemoveCloudServer(self,args):
        '''
        @删除远程数据库
        '''
        return self.RemoveBaseCloudServer(args)

    def ModifyCloudServer(self,args):
        '''
        @修改远程数据库
        '''
        return self.ModifyBaseCloudServer(args)


    def AddDatabase(self,args):
        """
        @添加数据库
        """
        res = self.add_base_database(args)
        if not res['status']: return res

        data_name = res['data_name']
        username = res['username']
        password = res['data_pwd']
        address = args['address'].strip()

        codeing = args['codeing']
        codeStr= public.get_database_codestr(codeing)

        #远程数据库
        self.sid = 0
        try:
            self.sid = int(args['sid'])
        except :pass

        mysql_obj = public.get_mysql_obj_by_sid(self.sid)
        #从MySQL验证是否存在
        if self.database_exists_for_mysql(mysql_obj,data_name):
            return public.returnMsg(False,'指定数据库已在MySQL中存在，请换个名称!')

        if public.check_chinese(data_name) or public.check_chinese(password):
            return public.returnMsg(False,'数据库名称或密码不能为中文，请更换!')

        for a in address.split(','):
            if a != '%' and not public.check_ip(a): return public.returnMsg(False,'访问权限设置不正确，应为%或指定ip.')

        result = mysql_obj.execute("create database `" + data_name + "` DEFAULT CHARACTER SET " + codeing + " COLLATE " + codeStr)
        isError = self.IsSqlError(result)
        if  isError != None: return isError

        mysql_obj.execute("drop user '" + username + "'@'localhost'")
        for a in address.split(','):
            mysql_obj.execute("drop user '" + username + "'@'" + a + "'")

        dtype = 'MySQL'
        self.__CreateUsers(data_name,username,password,address)

        if not hasattr(args,'ps'): args['ps'] = public.getMsg('INPUT_PS');
        addTime = time.strftime('%Y-%m-%d %X',time.localtime())

        pid = 0
        if hasattr(args,'pid'): pid = args.pid

        if hasattr(args,'contact'):
            site = public.M('sites').where("id=?",(args.contact,)).field('id,name').find()
            if site:
                pid = int(args.contact)
                args['ps'] = site['name']

        db_type = 0
        if self.sid: db_type = 2

        #添加入SQLITE
        public.M('databases').add('pid,sid,db_type,name,username,password,accept,ps,addtime,type',(pid,self.sid,db_type,data_name,username,password,address,args['ps'],addTime,dtype))
        public.WriteLog("TYPE_DATABASE", 'DATABASE_ADD_SUCCESS',(data_name,))
        return public.returnMsg(True,'ADD_SUCCESS')

    def DeleteDatabase(self,args):
        """
        @删除数据库
        """

        id = args['id']
        find = public.M('databases').where("id=?",(id,)).field('id,pid,name,username,password,type,accept,ps,addtime,sid,db_type').find();
        if not find: return public.returnMsg(False,'指定数据库不存在.')

        name = args['name']
        accept = find['accept'];
        username = find['username'];

        self.sid = find['sid']
        if find['db_type'] in ['0',0] or self.sid: # 删除本地数据库
            if not self.check_server():
                return public.returnMsg(False,'MySQL服务未安装或不是通过宝塔6.x以上版本安装的.')

            if not self.sid:
                if not self.DeleteToRecycleBin(name):
                    return public.returnMsg(False,'数据库移动到回收站失败.')

            #删除MYSQL
            mysql_obj = public.get_mysql_obj_by_sid(self.sid)
            result = mysql_obj.execute("drop database `" + name + "`")
            isError=self.IsSqlError(result)
            if  isError != None: return isError
            try:
                users = mysql_obj.query("select Host from mysql.user where User='" + username + "' AND Host!='localhost'")
                mysql_obj.execute("drop user '" + username + "'@'localhost'")
                for us in users:
                    mysql_obj.execute("drop user '" + username + "'@'" + us[0] + "'")
            except :pass
            mysql_obj.execute("flush privileges")

        #删除SQLITE
        public.M('databases').where("id=?",(id,)).delete()
        public.WriteLog("TYPE_DATABASE", 'DATABASE_DEL_SUCCESS',(name,))
        return public.returnMsg(True, 'DEL_SUCCESS')


    def ToBackup(self,args):
        """
        @备份数据库 id 数据库id
        """
        id = args['id']
        find = public.M('databases').where("id=?",(id,)).find()
        if not find: return public.returnMsg(False,'数据库不存在!')

        fileName = find['name'] + '_' + time.strftime('%Y%m%d_%H%M%S',time.localtime()) + '.sql'

        backupName = session['config']['backup_path'] + '/database/' + fileName

        dir_path = os.path.dirname(backupName)
        if not os.path.exists(dir_path):
            os.makedirs(dir_path)

        dump_path = None
        try:
            dump_path = self._setup_path + "/bin/mysqldump.exe"
        except :pass

        if not dump_path or not os.path.exists(dump_path):
            return public.returnMsg(False,'无法使用备份和还原功能，请先安装本地MySQL服务.')

        if find['db_type'] in ['0',0]:
            if not self.check_server():
                return public.returnMsg(False,'MySQL服务未安装或不是通过宝塔6.x以上版本安装的.')

            root = public.M('config').where('id=?',(1,)).getField('mysql_root');
            try:
                myconf = public.readFile(self._setup_path + '/my.ini')
                rep = "port\s*=\s*([0-9]+)"
                port = re.search(rep,myconf).groups()[0].strip();
            except :
                port = '3306'

            backup_shell = "{}/bin/mysqldump.exe -R -E --hex-blob --opt --force --default-character-set={} -P{} -uroot -p{} -R \"{}\" > {}".format(self._setup_path,public.get_database_character(find['name']),port,root,self.db_name_to_unicode(find['name']),backupName)
            ret = public.ExecShell(backup_shell)

        elif find['db_type'] in ['1',1]:
        # 远程数据库
            try:
                conn_config = json.loads(find['conn_config'])
                res = self.check_cloud_database_status(conn_config)
                if isinstance(res,dict): return res
                os.environ["MYSQL_PWD"] = str(conn_config['db_password'])
                public.ExecShell(self._setup_path+"/bin/mysqldump.exe -h "+ conn_config['db_host'] +" -P "+ str(int(conn_config['db_port'])) +" -R -E --triggers=false --default-character-set=" + public.get_database_character(find['name']) + " --force --opt \"" + str(find['name']) + "\"  -u "+ str(conn_config['db_user']) +" -p"+str(conn_config['db_password'])+"  > " + backupName)
            except Exception as e:
                raise
            finally:
                os.environ["MYSQL_PWD"] = ""
        elif find['db_type'] in ['2',2]:
            try:
                conn_config = public.M('database_servers').where('id=?',find['sid']).find()
                res = self.check_cloud_database_status(conn_config)
                if isinstance(res,dict): return res
                os.environ["MYSQL_PWD"] = str(conn_config['db_password'])
                public.ExecShell(self._setup_path+"/bin/mysqldump.exe -h "+ conn_config['db_host'] +" -P "+ str(int(conn_config['db_port'])) +" -R -E --triggers=false --default-character-set=" + public.get_database_character(find['name']) + " --force --opt \"" + str(find['name']) + "\"  -u "+ str(conn_config['db_user']) +" -p"+str(conn_config['db_password'])+"  > " + backupName)
            except Exception as e:
                raise
            finally:
                os.environ["MYSQL_PWD"] = ""
        else:
            return public.returnMsg(False,'不支持的数据库类型')

        if not os.path.exists(backupName):
            return public.returnMsg(False,'BACKUP_ERROR');

        public.M('backup').add('type,name,pid,filename,size,addtime',(1,fileName,id,backupName,0,time.strftime('%Y-%m-%d %X',time.localtime())))
        public.WriteLog("TYPE_DATABASE", "DATABASE_BACKUP_SUCCESS",(find['name'],))

        if os.path.getsize(backupName) < 2048:
            return public.returnMsg(True, '备份执行成功，备份文件小于2Kb，请检查备份完整性.')
        else:
            return public.returnMsg(True, 'BACKUP_SUCCESS')


    def DelBackup(self,args):
        """
        @删除备份文件
        """
        return self.delete_base_backup(args)



    def InputSql(self,args):

        name = args.name
        file = args.file

        find = public.M('databases').where("name=?",(name,)).find()
        if not find: return public.returnMsg(False,'数据库不存在!')

        tmp = file.split('.')
        exts = ['sql','zip','bak']
        ext = tmp[len(tmp) -1]
        if ext not in exts:
            return public.returnMsg(False, 'DATABASE_INPUT_ERR_FORMAT')

        backupPath = session['config']['backup_path'] + '/database'

        if ext == 'zip':
            try:
                fname = os.path.basename(file).replace('.zip','')
                dst_path = backupPath + '/' +fname
                if not os.path.exists(dst_path): os.makedirs(dst_path)

                public.unzip(file,dst_path)
                for x in os.listdir(dst_path):
                    if x.find('bak') >= 0 or x.find('sql') >= 0:
                        file = dst_path + '/' + x
                        break
            except :
                return public.returnMsg(False,'导入失败，该文件不是有效的zip格式的文件。')

        if not os.path.exists(file): return public.returnMsg(False, 'FILE_NOT_EXISTS',(file,))

        dump_path = None
        try:
            dump_path = self._setup_path + "/bin/mysqldump.exe"
        except :pass

        if not dump_path or not os.path.exists(dump_path):
            return public.returnMsg(False,'无法使用备份和还原功能，请先安装本地MySQL服务.')

        if find['db_type'] in ['0',0]:
            if not self.check_server():
                return public.returnMsg(False,'MySQL服务未安装或不是通过宝塔6.x以上版本安装的.')

            root = public.M('config').where('id=?',(1,)).getField('mysql_root');
            os.environ["MYSQL_PWD"] = str(root)
            public.ExecShell(self._setup_path + "/bin/mysql.exe -P"+str(public.get_mysql_info()['port'])+" -uroot -p" + root + " --force --default-character-set=utf8 \"" + name + "\" < " + file)

        elif find['db_type'] in ['1',1]:
                conn_config = json.loads(find['conn_config'])
                os.environ["MYSQL_PWD"] = str(conn_config['db_password'])
                public.ExecShell(self._setup_path + "/bin/mysql.exe -h "+ conn_config['db_host'] +" -P "+str(int(conn_config['db_port']))+" -u"+str(conn_config['db_user'])+" -p" + str(conn_config['db_password']) + " --force \"" + name + "\" < " +'"'+ file +'"')
        elif find['db_type'] in ['2',2]:
            conn_config = public.M('database_servers').where('id=?',find['sid']).find()
            os.environ["MYSQL_PWD"] = str(conn_config['db_password'])
            public.ExecShell(self._setup_path + "/bin/mysql.exe -h "+ conn_config['db_host'] +" -P "+str(int(conn_config['db_port']))+" -u"+str(conn_config['db_user'])+" -p" + str(conn_config['db_password']) + " --force \"" + name + "\" < " +'"'+ file +'"')

        public.WriteLog("TYPE_DATABASE", '导入数据库[{}]成功'.format(name))
        return public.returnMsg(True, 'DATABASE_INPUT_SUCCESS')


    def SyncToDatabases(self,args):
        """
        @同步数据库到服务器
        """
        n = 0
        type = int(args['type'])

        sql = public.M('databases')
        if type == 0:
            data = sql.field('id,name,username,password,accept,type,sid,db_type').where('type=?','MySQL').select()
            for value in data:
                if value['db_type'] in ['1',1]: continue # 跳过远程数据库
                result = self.ToDataBase(value)
                if result == 1: n +=1
        else:
            import json
            data = json.loads(args.ids)
            for value in data:
                find = sql.where("id=?",(value,)).field('id,name,username,password,accept,type').find()
                result = self.ToDataBase(find)
                if result == 1: n +=1

        return public.returnMsg(True,'DATABASE_SYNC_SUCCESS',(str(n),))



    #从服务器获取数据库
    def SyncGetDatabases(self,get):

        n = 0
        s = 0
        db_type = 0

        self.sid = get.get('sid/d',0)
        if self.sid: db_type = 2
        mysql_obj = public.get_mysql_obj_by_sid(self.sid)

        nameArr = ['information_schema','performance_schema','mysql','sys','master','model','msdb','tempdb']

        data = mysql_obj.query("show databases")

        users = mysql_obj.query("select User,Host from mysql.user where User!='root' AND Host!='localhost' AND Host!=''")
        isError = self.IsSqlError(users)
        if isError != None: return isError

        sql = public.M('databases')
        for value in data:
            b = False
            for key in nameArr:
                if value[0] == key:
                    b = True
                    break
            if b:continue
            if value[0].find('_backup') >= 0: continue

            if sql.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 = public.getMsg('INPUT_PS')
            if value[0] == 'test':
                    ps = public.getMsg('DATABASE_TEST')
            addTime = time.strftime('%Y-%m-%d %X',time.localtime())
            if sql.table('databases').add('name,sid,db_type,username,password,accept,ps,addtime,type',(value[0],self.sid,db_type,value[0],'',host,ps,addTime,'MySQL')): n +=1

        return public.returnMsg(True,'DATABASE_GET_SUCCESS',(str(n),))


    def GetDatabaseAccess(self,args):
        """
        @获取数据库权限
        """
        name = args['name']
        db_name = public.M('databases').where('username=?',name).getField('name')
        if not db_name: return public.returnMsg(False,'指定数据库不存在')

        mysql_obj = public.get_mysql_obj(db_name)

        users = mysql_obj.query("select Host from mysql.user where User='" + name + "' AND Host!='localhost'")
        isError = self.IsSqlError(users)
        if isError != None: return isError
        users = self.map_to_list(users)

        if len(users)<1:
            return public.returnMsg(True,"127.0.0.1")
        accs = []
        for c in users:accs.append(c[0]);

        return public.returnMsg(True, ','.join(accs))

    def SetDatabaseAccess(self,args):
        """
        @设置数据库权限
        """
        users = None

        name = args['name']
        db_find = public.M('databases').where('username=?',(name,)).find()
        if not db_find: public.returnMsg(False,'指定数据库不存在')

        db_name = db_find['name']
        self.sid = db_find['sid']

        access = args['access'].strip()
        if access in ['']: return public.returnMsg(False,'IP地址不能为空!')

        mysql_obj = public.get_mysql_obj(db_name)
        result = mysql_obj.query("show databases")
        isError = self.IsSqlError(result)
        if isError != None: return isError

        users = mysql_obj.query("select Host from mysql.user where User='" + name + "' AND Host!='localhost'")
        for us in users:
            mysql_obj.execute("drop user '" + name + "'@'" + us[0] + "'")

        password = public.M('databases').where("username=?",(name,)).getField('password')
        self.__CreateUsers(db_name,name,password,access)

        return public.returnMsg(True, 'SET_SUCCESS')

    def ResDatabasePassword(self,args):
        """
        @修改用户密码
        """
        id = args['id']
        username = args['name']
        newpassword = args['password']

        find = public.M('databases').where("id=?",(id,)).field('id,pid,name,username,password,type,accept,ps,addtime,sid').find();
        if not find: return public.returnMsg(False, '修改失败，指定数据库不存在.');

        if not newpassword:
            return public.returnMsg(False, '修改失败，数据库[' + username + ']密码不能为空.');

        name = find['name']
        try:
            if len(re.search("^[\w@\.]+$", newpassword).groups()) > 0:
                return public.returnMsg(False, '数据库密码不能为空或带有特殊字符')
        except :
            return public.returnMsg(False, '数据库密码不能为空或带有特殊字符')

        if not self.check_server(): return public.returnMsg(False,'MySQL服务未安装或不是通过宝塔6.x以上版本安装的.')

        if public.check_chinese(username) or public.check_chinese(newpassword):
            return public.returnMsg(False,'数据库名称或密码不能为中文，请更换!')

        #修改MYSQL
        self.sid = find['sid']
        if self.sid and username == 'root':
            return public.returnMsg(False,'不能修改远程数据库的root密码')

        mysql_obj = public.get_mysql_obj_by_sid(self.sid)
        m_version = public.readFile(self._setup_path + '/version.pl')

        if self.sid:
            m_version = mysql_obj.query('select version();')[0][0]

        if m_version.find('5.7') == 0  or m_version.find('8.0') == 0 :
            accept = self.map_to_list(mysql_obj.query("select Host from mysql.user where User='" + name + "' AND Host!='localhost'"))
            mysql_obj.execute("update mysql.user set authentication_string='' where User='" + username + "'")
            result = mysql_obj.execute("ALTER USER `%s`@`localhost` IDENTIFIED BY '%s'" % (username,newpassword))
            for my_host in accept:
                mysql_obj.execute("ALTER USER `%s`@`%s` IDENTIFIED BY '%s'" % (username,my_host[0],newpassword))
        elif m_version.find('10.5.') != -1 or m_version.find('10.4.') != -1:
            accept = self.map_to_list(mysql_obj.query("select Host from mysql.user where User='" + name + "' AND Host!='localhost'"))
            result = mysql_obj.execute("ALTER USER `%s`@`localhost` IDENTIFIED BY '%s'" % (username,newpassword))
            for my_host in accept:
                mysql_obj.execute("ALTER USER `%s`@`%s` IDENTIFIED BY '%s'" % (username,my_host[0],newpassword))
        else:
            result = mysql_obj.execute("update mysql.user set Password=password('" + newpassword + "') where User='" + username + "'")

        isError=self.IsSqlError(result)
        if  isError != None: return isError

        mysql_obj.execute("flush privileges")

        #修改SQLITE
        if int(id) > 0:
            public.M('databases').where("id=?",(id,)).setField('password',newpassword)
        else:
            public.M('config').where("id=?",(id,)).setField('mysql_root',newpassword)
            session['config']['mysql_root'] = newpassword

        public.WriteLog("TYPE_DATABASE",'DATABASE_PASS_SUCCESS',(name,))
        return public.returnMsg(True,'DATABASE_PASS_SUCCESS',(name,))


    def SetupPassword(self,args):
        #设置ROOT密码

        if not hasattr(args, 'password'):return public.returnMsg(False, '修改失败,参数传递错误.')

        password = args['password'].strip()
        if not self.check_server(): return public.returnMsg(False,'MySQL服务未安装或不是通过宝塔6.x以上版本安装的.')
        if not password:  return public.returnMsg(False, '修改失败，root密码不能为空.')

        if re.search('[\u4e00-\u9fa5]',password):
            return public.returnMsg(False,'数据库名称不能为中文，请换个密码!')

        rep = "^[\w@\.]+$"
        if not re.match(rep, password): return public.returnMsg(False, 'root密码不能为空或带有特殊符号!')
        mysql_root = public.M('config').where("id=?",(1,)).getField('mysql_root')
        #修改MYSQL
        mysql_obj = panelMysql.panelMysql()
        result = mysql_obj.query("show databases")
        isError=self.IsSqlError(result)

        is_modify = True
        if  isError != None:
            #尝试使用新密码
            public.M('config').where("id=?",(1,)).setField('mysql_root',password)
            result = mysql_obj.query("show databases")
            isError=self.IsSqlError(result)
            if  isError != None:
                setup_path = public.GetConfigValue('setup_path')
                shell = public.get_run_python("%s && cd %s/panel && [PYTHON] tools.py root %s" % (setup_path[0:2],setup_path,password));
                os.system(shell)
                is_modify = False
        if is_modify:
            if self._version.find('5.7') >= 0  or self._version.find('8.0') >= 0:
                mysql_obj.execute("UPDATE mysql.user SET authentication_string='' WHERE user='root'")
                mysql_obj.execute("ALTER USER 'root'@'localhost' IDENTIFIED BY '%s'" % password)
                mysql_obj.execute("ALTER USER 'root'@'127.0.0.1' IDENTIFIED BY '%s'" % password)
            else:
                result = mysql_obj.execute("update mysql.user set Password=password('" + password + "') where User='root'")
            mysql_obj.execute("flush privileges")

        msg = public.getMsg('DATABASE_ROOT_SUCCESS');
        #修改SQLITE
        public.M('config').where("id=?",(1,)).setField('mysql_root',password)
        public.WriteLog("TYPE_DATABASE", "DATABASE_ROOT_SUCCESS")
        session['config']['mysql_root']= password
        return public.returnMsg(True,msg)




    def check_del_data(self,args):
        """
        @删除数据库前置检测
        """
        return self.check_base_del_data(args)


    #检测是否6.x安装的服务
    def check_server(self):
         if public.get_server_status("mysql") < 0 or not os.path.exists(self._setup_path + '/my.ini')  :
             return False
         return True

    def db_name_to_unicode(self,name):
        '''
            @name 中文数据库名转换为Unicode编码
            @author hwliang<2021-12-20>
            @param name<string> 数据库名
            @return name<string> Unicode编码的数据库名
        '''
        name = name.replace('.','@002e')
        return name.encode("unicode_escape").replace(b"\\u",b"@").decode()

    def __CreateUsers(self,data_name,username,password,address):
        """
        @创建数据库用户
        """
        mysql_obj = public.get_mysql_obj_by_sid(self.sid)

        mysql_obj.execute("CREATE USER `%s`@`localhost` IDENTIFIED BY '%s'" % (username,password))
        mysql_obj.execute("grant all privileges on `%s`.* to `%s`@`localhost`" % (data_name,username))
        for a in address.split(','):
            if a:
                mysql_obj.execute("CREATE USER `%s`@`%s` IDENTIFIED BY '%s'" % (username,a,password))
                mysql_obj.execute("grant all privileges on `%s`.* to `%s`@`%s`" % (data_name,username,a))
        mysql_obj.execute("flush privileges")



    def DeleteTo(self,filename):
        """
        @永久删除数据库
        @filename str 文件路径
        """
        try:

            name = os.path.basename(filename).split('_t_')[0].replace('BTDB_','')
            if os.path.exists(filename):os.remove(filename)

            spath = '{}/data/recycle_bin_db/{}'.format(public.get_panel_path(),name)
            data = json.loads(public.readFile(spath))
            os.remove(spath)
        except :pass

        public.WriteLog("TYPE_DATABASE", 'DATABASE_DEL_SUCCESS',(name,))
        return public.returnMsg(True,'DEL_SUCCESS');

    def DeleteToRecycleBin(self,name):
        """
        @删除数据库到回收站
        @name 数据库名称
        """
        backup_name = name + '_backup'

        if not os.path.exists('data/recycle_bin_db.pl'):
            return True

        srcPath = '{}/data/{}'.format(self._setup_path,self.db_name_to_unicode(name))

        if not os.path.exists(srcPath):
            return True

        dstPath = srcPath.replace(self.db_name_to_unicode(name),backup_name)
        try:
            os.rename(srcPath,dstPath)
        except :
            try:
                public.move(srcPath,dstPath)
            except :
                public.copytree(srcPath,dstPath)

        if not os.path.exists(srcPath): os.makedirs(srcPath)
        if os.path.exists(dstPath):

            import panelTask,json
            task_obj = panelTask.bt_task()
            exec_shell = public.to_path(public.get_run_python('[PYTHON] {}/script/backup.py db_recyclebin {}'.format(public.get_panel_path(),name)))
            task_obj.create_task('删除数据库[{}]到数据库回收站'.format(name), 0, exec_shell)
            data = public.M('databases').where("name=?",(name,)).field('id,pid,name,username,password,type,accept,ps,addtime').find();

            data['codeing'] = public.get_database_character(name)
            spath = 'data/recycle_bin_db'
            if not os.path.exists(spath): os.makedirs(spath)
            public.writeFile('{}/{}'.format(spath,data['name']),json.dumps(data))

            return True
        return False


    def RecycleDB(self,filename):
        """
        @恢复数据库
        @filename str 备份文件路径
        """
        if not os.path.exists(filename):
            return public.returnMsg(False,'恢复数据库失败，指定备份文件不存在.');

        name = os.path.basename(filename).split('_t_')[0].replace('BTDB_','');
        if public.M('databases').where("name=?",(name,)).count():
            return public.returnMsg(True,'已存在同名数据库.')

        spath = '{}/data/recycle_bin_db/{}'.format(public.get_panel_path(),name)
        data = json.loads(public.readFile(spath))

        mysql_obj = panelMysql.panelMysql()
        result = mysql_obj.execute("create database `" + name + "` DEFAULT CHARACTER SET " + data['codeing'] + " COLLATE " + public.get_database_codestr(data['codeing']))
        isError = self.IsSqlError(result)
        if  isError != None: return isError

        self.__CreateUsers(data['name'],data['username'],data['password'],data['accept'])
        public.M('databases').add('id,pid,name,username,password,accept,ps,addtime,type',(data['id'],data['pid'],data['name'],data['username'],data['password'],data['accept'],data['ps'],data['addtime'],data['type']))

        root = public.M('config').where('id=?',(1,)).getField('mysql_root');
        shell = public.to_path(self._setup_path + "/bin/mysql.exe -uroot -p" + root + " --force --default-character-set=utf8 " + name + " < " + filename)
        public.ExecShell(shell)
        os.remove(filename)
        public.WriteLog("TYPE_DATABASE", '从数据库回收站恢复【{}】成功.'.format(name))
        return public.returnMsg(True,"RECYCLEDB")


    #添加到服务器
    def ToDataBase(self,find):
        if find['username'] == 'bt_default': return 0
        if len(find['password']) < 3 :
            find['username'] = find['name']
            find['password'] = public.md5(str(time.time()) + find['name'])[0:10]
            public.M('databases').where("id=?",(find['id'],)).save('password,username',(find['password'],find['username']))

        if not self.check_server(): return public.returnMsg(False,'MySQL服务未安装或不是通过宝塔6.x以上版本安装的.')

        mysql_obj =  panelMysql.panelMysql()

        result = mysql_obj.execute("create database " + find['name'])
        isError = self.IsSqlError(result)
        if  isError != None: return -1

        mysql_obj.execute("drop user '" + find['username'] + "'@'localhost'")
        mysql_obj.execute("drop user '" + find['username'] + "'@'" + find['accept'] + "'")
        self.__CreateUsers(find['name'],find['username'],find['password'],find['accept'])

        return 1


    # 获取当前数据库信息
    def GetInfo(self,get):
        info=self.GetdataInfo(get)
        return info
        if info:
            return info
        else:
            return public.returnMsg(False,"获取数据库失败!")

    #修复表信息
    def ReTable(self,get):
        m_version = self._version
        if m_version.find('5.1.')!=-1:return public.returnMsg(False,"不支持mysql5.1!")
        info=self.RepairTable(get)
        if info:
            return public.returnMsg(True,"修复完成!")
        else:
            return public.returnMsg(False,"修复失败!")

    # 优化表
    def OpTable(self,get):
        info=self.OptimizeTable(get)
        if info:
            return public.returnMsg(True,"优化成功!")
        else:
            return public.returnMsg(False,"优化失败或者已经优化过了")

    #更改表引擎
    def AlTable(self,get):
        info=self.AlterTable(get)
        if info:
            return public.returnMsg(True,"更改成功")
        else:
            return public.returnMsg(False,"更改失败")


    #判断数据库是否存在—从MySQL
    def database_exists_for_mysql(self,mysql_obj,dataName):
        databases_tmp = self.map_to_list(mysql_obj.query('show databases'))
        if not isinstance(databases_tmp,list):
            return True

        for i in databases_tmp:
            if i[0] == dataName:
                return True
        return False

    def check_cloud_database_status(self,conn_config):
        """
        @检测远程数据库是否连接
        """
        try:
            import db_mysql
            if not 'db_name' in conn_config: conn_config['db_name'] = None
            mysql_obj = db_mysql.panelMysql().set_host(conn_config['db_host'],conn_config['db_port'],conn_config['db_name'],conn_config['db_user'],conn_config['db_password'])
            result = mysql_obj.query("show databases")

            isError = self.IsSqlError(result)
            if isError != None:  return public.returnMsg(False,result)

            if not conn_config['db_name']: return True
            for i in result:
                if i[0] == conn_config['db_name']:
                    return True
            return public.returnMsg(False,'指定数据库不存在!')
        except Exception as ex:

            res  = self.GetMySQLError(ex)
            if not res: res = str(ex)
            return public.returnMsg(False,res)


    def GetMySQLError(self,e):
        res = ''
        if e.args[0] == 1045:
            res = '用户名或密码错误!'
        if e.args[0] == 1049:
            res = '数据库不存在!'
        if e.args[0] == 1044:
            res = '没有指定数据库的访问权限，或指定数据库不存在!'
        if e.args[0] == 1062:
            res = '数据库已存在!'
        if e.args[0] == 1146:
            res = '数据表不存在!'
        if e.args[0] == 2003:
            res = '数据库服务器连接失败!'
        if res:
            res = res + "<pre>" + str(e) + "</pre>"
        else:
            res = str(e)
        return res