#coding: utf-8
# +-------------------------------------------------------------------
# | 宝塔Windows面板
# +-------------------------------------------------------------------
# | Copyright (c) 2015-2016 宝塔软件(http://www.bt.cn) All rights reserved.
# +-------------------------------------------------------------------
# | Author: 沐落 <cjx@bt.cn>
# +-------------------------------------------------------------------

import public,db,re,os,firewalls

class ftp:
    __xmlPath = None
    setupPath = None
    def __init__(self):
        self.setupPath = public.GetConfigValue('setup_path')
        self.__xmlPath = self.setupPath + '/ftpServer/FileZilla Server.xml'

    def AddUser(self,get):
        """
        添加FTP用户
        @get.ftp_username ftp账号
        @get.ftp_password ftp密码
        @get.path ftp路径
        @get.down 下载速度
        @get.up 上传速度
        @access 读写权限
        """
        try:

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

            import files,time
            fileObj = files.files()

            get['ftp_username'] = get['ftp_username'].replace(' ','')
            if re.search("\W + ",get['ftp_username']):
                return {'status':False,'code':501,'msg':public.getMsg('FTP_USERNAME_ERR_T')}

            if len(get['ftp_username']) < 3: return {'status':False,'code':501,'msg':public.getMsg('FTP_USERNAME_ERR_LEN')}
            if not fileObj.CheckDir(get['path']): return {'status':False,'code':501,'msg':public.getMsg('FTP_USERNAME_ERR_DIR')}
            if public.M('ftps').where('name=?',(get.ftp_username.strip(),)).count(): return public.returnMsg(False,'FTP_USERNAME_ERR_EXISTS',(get.ftp_username,))
            username = get['ftp_username'].strip()
            password = get['ftp_password'].strip()
            if len(password) < 3: return public.returnMsg(False,'密码长度不能小于3位')

            get.path = get['path'].strip()
            get.path = get.path.replace("\\", "/")
            fileObj.CreateDir(get)
            Down = get['down']
            Up = get['up']
            access = get['access']

            if not Down: Down = 1024 #默认1024K
            if not Up: Up = 1024  #默认1024K
            if not access: access = '1' #默认读写权限

            user = {"@Name": username , "Option": [{"@Name": "Pass", "#text": public.Md5(password) }, {"@Name": "Group"}, {"@Name": "Bypass server userlimit", "#text": "1"}, {"@Name": "User Limit", "#text": "5"}, {"@Name": "IP Limit", "#text": "10"}, {"@Name": "Enabled", "#text": "1"}, {"@Name": "Comments"}, {"@Name": "ForceSsl", "#text": "0"}], "IpFilter": {"Disallowed": "", "Allowed": ""}, "Permissions": {"Permission": {"@Dir": get.path , "Option": [{"@Name": "FileRead", "#text": "1"}, {"@Name": "FileWrite", "#text": access}, {"@Name": "FileDelete", "#text": access}, {"@Name": "FileAppend", "#text": "1"}, {"@Name": "DirCreate", "#text": access }, {"@Name": "DirDelete", "#text": access}, {"@Name": "DirList", "#text": "1"}, {"@Name": "DirSubdirs", "#text": "1"}, {"@Name": "IsHome", "#text": "1"}, {"@Name": "AutoCreate", "#text": "1"}]}}, "SpeedLimits": {"@DlType": "2", "@DlLimit": Down, "@ServerDlLimitBypass": "0", "@UlType": "2", "@UlLimit": Up, "@ServerUlLimitBypass": "0", "Download": "", "Upload": ""}}
            data = self.get_ftp_config()
            data['FileZillaServer']['Users']['User'].append(user)
            public.writeFile(self.__xmlPath, public.format_xml(public.dumps_json(data)))

            self.FtpReload()

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

            pid = 0
            if hasattr(get,'pid'): pid = get.pid
            public.M('ftps').add('pid,name,password,path,status,ps,addtime',(pid,username,password,get.path,1,ps,addtime))
            public.WriteLog('TYPE_FTP', 'FTP_ADD_SUCCESS',(username,))
            return public.returnMsg(True,'ADD_SUCCESS')
        except Exception as ex:
            return public.returnMsg(False,'ADD_ERROR')

    def DeleteUser(self,get):
        """
        删除FTP用户
        @get.username 用户名
        @get.id ftp的id
        """
        #try:

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

        username = get['username']
        id = get['id']

        data = self.get_ftp_config()
        users = []
        for user in  data['FileZillaServer']['Users']['User']:
            if user['@Name'] != username: users.append(user)
        data['FileZillaServer']['Users']['User'] = users
        public.writeFile(self.__xmlPath, public.format_xml(public.dumps_json(data)))

        self.FtpReload()
        public.M('ftps').where("id=?",(id,)).delete()
        public.WriteLog('TYPE_FTP', 'FTP_DEL_SUCCESS',(username,))
        return public.returnMsg(True, "DEL_SUCCESS")


    def SetUserPassword(self,get):
        """
        修改用户密码
        @get.ftp_username ftp用户名
        @get.new_password 新密码
        """
        if not self.check_server():
            return public.returnMsg(False,'FileZilla Server软件未安装或不是通过宝塔6.x以上版本安装的.')

        id = get['id']
        username = get['ftp_username'].replace(' ','')
        password = get['new_password'].strip()
        if len(password) < 3: return public.returnMsg(False,'密码长度不能小于3位')

        self.__check_ftp_user(id)

        data = self.set_user_config(username,'Pass',public.Md5(password))
        self.FtpReload()

        public.M('ftps').where("id=?",(id,)).setField('password',password)
        public.WriteLog('TYPE_FTP', 'FTP_PASS_SUCCESS',(username,))
        return public.returnMsg(True,'EDIT_SUCCESS')


    def SetStatus(self,get):
        """
        设置用户状态
        @get.username ftp用户名
        @get.status ftp启用状态
        """
        if not self.check_server():
            return public.returnMsg(False,'FileZilla Server软件未安装或不是通过宝塔6.x以上版本安装的.')

        msg = public.getMsg('OFF');
        if get.status != '0': msg = public.getMsg('ON');
        try:
            id = get['id']
            username = get['username']
            status = get['status']

            self.__check_ftp_user(id)
            self.set_user_config(username,'Enabled',status)

            self.FtpReload()
            public.M('ftps').where("id=?",(id,)).setField('status',status)
            public.WriteLog('TYPE_FTP','FTP_STATUS', (msg,username))
            return public.returnMsg(True, 'SUCCESS')
        except Exception as ex:
            public.WriteLog('TYPE_FTP','FTP_STATUS_ERR', (msg,username,str(ex)))
            return public.returnMsg(False,'FTP_STATUS_ERR',(msg,))

    def check_server(self):
        if public.get_server_status("FileZilla Server") < 0 or not os.path.exists(self.__xmlPath):
            return False
        return True

    def setPort(self,get):
        """
        * 设置FTP端口
        * @param Int _GET['port'] 端口号
        * @return bool
        """
        try:
            if not self.check_server(): return public.returnMsg(False,'FileZilla Server软件未安装或不是通过宝塔6.x以上版本安装的.')

            port = get['port']
            if int(port) < 1 or int(port) > 65535: return public.returnMsg(False,'PORT_CHECK_RANGE')

            self.set_pub_config('Serverports',port)
            self.FtpReload()
            public.WriteLog('TYPE_FTP', "FTP_PORT",(port,))
            #添加防火墙
            #data = ftpinfo(port=port,ps = 'FTP端口')
            get.port=port
            get.ps = public.getMsg('FTP_PORT_PS');
            firewalls.firewalls().AddAcceptPort(get)

            return public.returnMsg(True, 'EDIT_SUCCESS')
        except Exception as ex:
            public.WriteLog('TYPE_FTP', 'FTP_PORT_ERR',(str(ex),))
            return public.returnMsg(False,'EDIT_ERROR')

    def get_ip_info(self,get):
        """
        获取FTP绑定IP
        """
        return public.get_ip_info()

    def get_logs_info(self,get):
        """
        @name 获取日志相关
        """
        data = {}
        data['status'] = self.get_pub_config('Enable logging')
        data['limit'] = self.get_pub_config('Logfile delete time')

        return data

    def set_logs_info(self,get):
        """
        @name 设置日志开关
        @get.status 日志开关
        @get.limit 日志保留天数
        """
        status = int(get.status)
        limit = int(get.limit)

        if not status in [0,1]:
            return public.returnMsg(False,'参数错误')

        self.set_pub_config('Enable logging',str(status))
        self.set_pub_config('Logfile delete time',str(limit))
        self.set_pub_config('Logfile type','1')

        self.FtpReload()

        return public.returnMsg(True,'设置成功')


    def get_ftp_config(self):
        """
        格式化ftp配置
        """
        data = public.loads_json(self.__xmlPath)
        try:
            if data:
                list = data['FileZillaServer']['Users']['User']
                if type(list) != type([1,]):
                    data['FileZillaServer']['Users']['User'] = [list]
            else:
                data = {'FileZillaServer':{'Users':{'User':[]}}}
        except :

            if not data['FileZillaServer']['Users']:
                user = {}
                user["User"] = []
                data['FileZillaServer']['Users'] = user
        return data

    def set_ftp_data(self,get):
        """
        设置ftp配置
        @get.username

        """
        username = get.username
        data = self.get_ftp_config()

        ndata = []
        for user in  data['FileZillaServer']['Users']['User']:
            if user['@Name'] == username:

                dlimit = int(get.dlimit)
                ulimit = int(get.ulimit)
                read = int(get.read)
                write = int(get.write)
                conn_limit = int(get.conn_limit)

                block_list = get.block_ip.split('\n')
                write_list = get.write_ip.split('\n')

                for x in user['Option']:
                    if x['@Name'] == 'User Limit':
                        print(x)
                        x['#text'] = str(conn_limit)
                    elif x['@Name'] == 'IP Limit':
                        x['#text'] = str(conn_limit)

                if dlimit == 0:
                    user['SpeedLimits']['@DlType'] = 1
                else:
                    user['SpeedLimits']['@DlType'] = 2
                    user['SpeedLimits']['@DlLimit'] = dlimit

                if ulimit == 0:
                    user['SpeedLimits']['@UlType'] = 1
                else:
                    user['SpeedLimits']['@UlType'] = 2
                    user['SpeedLimits']['@UlLimit'] = ulimit

                read_list = ['FileRead','DirList','DirSubdirs']
                for x in user['Permissions']['Permission']['Option']:
                    x['#text'] = "0"
                    if x['@Name'] in read_list:
                        if read: x['#text'] = "1"
                    else:
                        if write: x['#text'] = "1"

                if not user['IpFilter']['Disallowed']: user['IpFilter']['Disallowed'] = {}
                if not "IP" in user['IpFilter']['Disallowed']:  user['IpFilter']['Disallowed']['IP'] = []

                if not user['IpFilter']['Allowed']: user['IpFilter']['Allowed'] = {}
                if not "IP" in user['IpFilter']['Allowed']: user['IpFilter']['Allowed']['IP'] = []

                user['IpFilter']['Disallowed']['IP'] = []
                user['IpFilter']['Allowed']['IP'] = []

                for x in block_list:
                    user['IpFilter']['Disallowed']['IP'].append(x)

                for x in write_list:
                    user['IpFilter']['Allowed']['IP'].append(x)
            ndata.append(user)
        data['FileZillaServer']['Users']['User'] = ndata
        public.writeFile(self.__xmlPath, public.format_xml(public.dumps_json(data)))

        self.FtpReload()

        return public.returnMsg(True,'EDIT_SUCCESS')

    def get_ftp_data(self,get):
        """
        获取ftp配置
        @get.username ftp用户名

        """
        username = get.username

        data = self.get_ftp_config()
        conf = {}
        for user in  data['FileZillaServer']['Users']['User']:
            if user['@Name'] == username:

                conf['conn_limit'] = 5
                for x in user['Option']:
                    if x['@Name'] == 'User Limit': conf['conn_limit'] = x['#text']

                conf['dlimit'] = 0
                if int(user['SpeedLimits']['@DlType']) == 2:
                    conf['dlimit'] = int(user['SpeedLimits']['@DlLimit'])

                conf['ulimit'] = 0
                if int(user['SpeedLimits']['@UlType']) == 2:
                    conf['ulimit'] = int(user['SpeedLimits']['@UlLimit'])

                conf['read'] = 0
                conf['write'] = 0
                for item in user['Permissions']['Permission']['Option']:

                    if item['@Name'] == 'FileRead':
                        if item['#text'] == '1':
                            conf['read'] = 1
                    elif item['@Name'] == 'FileWrite':
                        if item['#text'] == '1':
                            conf['write'] = 1


                conf['block_list'] = []
                try:
                    b_ips =  user['IpFilter']['Disallowed']['IP']
                    if type(b_ips) == str:
                        conf['block_list'].append(b_ips)
                    else:
                        for item in b_ips: conf['block_list'].append(item)
                except : pass

                conf['write_list'] = []
                try:
                    w_ips = user['IpFilter']['Allowed']['IP']
                    if type(w_ips) == str:
                        conf['write_list'].append(w_ips)
                    else:
                        for item in user['IpFilter']['Allowed']['IP']:
                            conf['write_list'].append(item)
                except : pass

                break

        return conf


    def __check_ftp_user(self,id):
        """
        检查ftp是否存在用户
        @id ftpid
        """

        find = public.M('ftps').where("id=?",(id,)).field('name,password,path').find()

        data = self.get_ftp_config()
        is_exists = False
        for user in  data['FileZillaServer']['Users']['User']:
            if user['@Name'] == find['name']:
                is_exists = True
                break;

        #不存在则创建
        if not is_exists:
            Down = 1024 #默认1024K
            Up = 1024  #默认1024K
            access = '1' #默认读写权限

            user = {"@Name": find['name'] , "Option": [{"@Name": "Pass", "#text": public.Md5(find['password']) }, {"@Name": "Group"}, {"@Name": "Bypass server userlimit", "#text": "1"}, {"@Name": "User Limit", "#text": "5"}, {"@Name": "IP Limit", "#text": "10"}, {"@Name": "Enabled", "#text": "1"}, {"@Name": "Comments"}, {"@Name": "ForceSsl", "#text": "0"}], "IpFilter": {"Disallowed": "", "Allowed": ""}, "Permissions": {"Permission": {"@Dir": find['path'] , "Option": [{"@Name": "FileRead", "#text": "1"}, {"@Name": "FileWrite", "#text": access}, {"@Name": "FileDelete", "#text": access}, {"@Name": "FileAppend", "#text": "1"}, {"@Name": "DirCreate", "#text": access }, {"@Name": "DirDelete", "#text": access}, {"@Name": "DirList", "#text": "1"}, {"@Name": "DirSubdirs", "#text": "1"}, {"@Name": "IsHome", "#text": "1"}, {"@Name": "AutoCreate", "#text": "1"}]}}, "SpeedLimits": {"@DlType": "2", "@DlLimit": Down, "@ServerDlLimitBypass": "0", "@UlType": "2", "@UlLimit": Up, "@ServerUlLimitBypass": "0", "Download": "", "Upload": ""}}
            data['FileZillaServer']['Users']['User'].append(user)
            public.writeFile(self.__xmlPath, public.format_xml(public.dumps_json(data)))
        return True


    def set_user_config(self,username,key,val):
        """
        设置用户配置
        @username 指定ftp用户名
        @key 指定key值
        @val 具体值
        """
        data = self.get_ftp_config()
        for user in  data['FileZillaServer']['Users']['User']:
            if user['@Name'] == username:
                for item in user['Option']:
                    if item["@Name"] == key:
                        item['#text'] = val
                        break
        public.writeFile(self.__xmlPath, public.format_xml(public.dumps_json(data)))
        return True

    def set_pub_config(self,key,val):
        """
        设置公用配置
        """
        data = self.get_ftp_config()
        for item in  data['FileZillaServer']['Settings']['Item']:
            if item['@name'] == key:
                item['#text'] = val
                break
        public.writeFile(self.__xmlPath, public.format_xml(public.dumps_json(data)))
        return True;

    def get_pub_config(self,key):
        """
        获取公用配置
        @key 具体key值
        """
        data = self.get_ftp_config()
        for item in  data['FileZillaServer']['Settings']['Item']:
            if item['@name'] == key:
               return item['#text']
        return None;

    def FtpReload(self):
        """
        重载配置
        """
        public.set_server_status('FileZilla Server','restart')


    def get_ftp_files(self,get):
        """
        登录ftp获取文件列表
        """
        id = get.id
        if not id: return public.returnMsg(False,'参数传递错误.')

        find = public.M('ftps').where("id=?",(id,)).field('name,password').find()

        if find:
            port = self.get_pub_config('Serverports')
            try:
                from ftplib import FTP
                btftp = FTP()

                btftp.connect('127.0.0.1', int(port))
                btftp.login(find['name'], find['password'])
                data = []
                for x in btftp.nlst(): data.append(x)

                btftp.close()
                return data
            except :
                return public.returnMsg(False, '当前账号的FTP必须是开启状态才能查看!')
                # raise public.PanelError('登录ftp帐号失败,请检查服务器安全组是否放行端口!')

        return public.returnMsg(False,'操作失败，指定ftp账号不存在.')
