#!/usr/bin/python
#coding: utf-8
#-----------------------------
# 安装脚本
#-----------------------------

import sys,os,shutil
panelPath = os.getenv('BT_PANEL')
os.chdir(panelPath)
sys.path.append("class/")
import public,tarfile

class panel_redis:
    _name = 'redis'
    _version = None
    _setup_path = None

    __path = panelPath + '/plugin/' + _name

    def __init__(self,name,version,setup_path): 
        self._version = version
        self._setup_path = setup_path
    
    def install_soft(self,downurl):

        public.kill('redis_server.exe')
        public.kill('redis-server.exe')

        if public.get_server_status(self._name) >= 0:  
            public.delete_server(self._name)
        
        try:
            if os.path.exists(os.getenv("BT_SETUP") + '/redis'):
                shutil.rmtree(os.getenv("BT_SETUP") + '/redis')
        except :pass      

        if self.get_os_version().find('2008') >=0 :self._version = '3.2'            
        
        #下载插件
        if not os.path.exists(self.__path): os.makedirs(self.__path)

        pluginUrl = downurl + '/win/install/plugin/' + self._name

        fileList = ['icon.png','redis_main.py','info.json','index.html']
        for f in fileList:
            public.bt_print(pluginUrl + '/' + f)
            public.downloadFile(pluginUrl + '/' + f,self.__path + '/' + f)
            if not os.path.exists(self.__path + '/' + f):
                public.bt_print("ERROR:文件下载失败!")
                exit()

        #下载软件
        temp = self._setup_path + '/temp/redis.zip'
        public.downloadFile(downurl + '/win/redis/redis'+ self._version +'.zip',temp)
        if not os.path.exists(temp): return public.returnMsg(False,'文件下载失败,请检查网络!');

        import zipfile
        zip_file = zipfile.ZipFile(temp)  
        for names in zip_file.namelist():  
            zip_file.extract(names,self._setup_path)    

        tpath = os.getenv("BT_SETUP") + '/panel/script/BtTools.exe'

        pwd = '{}{}{}'.format(public.GetRandomString(64),public.GetRandomString1(32),public.GetRandomString2(32))

        ret = self.add_user('redis',pwd,'用于启动宝塔安装的程序,删除后会导致部分软件无法启动,请勿删除')

        if not ret:             
            public.bt_print("redis用户创建失败,请【修复面板】后重新操作，如失败，则检查创建用户是否被安全软件拦截.");
            return
                
        public.set_file_access(os.getenv("BT_SETUP") + "/redis","redis",public.file_all)

        if self._version  in ['3.2','5.0','5.1','5.2','5.3','5.4','5.5']:            
            rRet = public.create_server(self._name,self._name,self._setup_path + '\\redis\\redis-server.exe ','--service-run redis.windows.conf --loglevel verbose',"Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库","redis",pwd.strip())
        else:
            rRet = public.create_server(self._name,self._name,self._setup_path + '\\redis\\redis_server.exe ','',"Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库","redis",pwd.strip())
   
        if public.get_server_status(self._name) == 0:
            if public.set_server_status(self._name,'start'): 
                public.bt_print('redis启动成功.')
            else:
                return public.returnMsg(False,'启动失败，请检查配置文件是否错误!');
        public.bt_print('注意：redis用户密码采用128位混淆加密，并且本地不保存密码，此用户仅用于启动redis服务，并无其他安全问题，请勿随意修改密码和删除，否则将导致目录权限混乱')
        public.bt_print('redis安装成功.')
        if self.get_os_version().find('2008') >=0 :
            public.bt_print('windows 2008将不支持redis6.0，程序将自动为您安装redis 3.2.100.')
        return public.returnMsg(True,'安装成功!');
        

    def get_registry_value(self,key, subkey, value):
        import winreg
        key = getattr(winreg, key)
        handle = winreg.OpenKey(key, subkey)
        (value, type) = winreg.QueryValueEx(handle, value)
        return value

    def get_os_version(self):
        def get(key):
            return self.get_registry_value("HKEY_LOCAL_MACHINE", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", key)
        v = get("ProductName")
        build = get("CurrentBuildNumber")
        os_version = "%s (build) %s" % (v, build)

        return os_version

    def add_user(self,name,pwd,ps):
        import win32netcon, win32security
        import win32net, win32api, win32netcon
        
        is_user = False
        resume = 0
        while True:
            data, total, resume = win32net.NetUserEnum(None, 3, win32netcon.FILTER_NORMAL_ACCOUNT, resume)
            for user in data:
                if user['name'] == name:
                    is_user = True
                    break;
            if not resume: break
  
        if not is_user:            

            d = {}
            d['name'] = name
            d['password'] = pwd
            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, name)
            win32security.LsaAddAccountRights(handle, sid_obj, ('SeServiceLogonRight',) )
            win32security.LsaClose( handle)  
        else:
            public.ExecShell('net user "{}" "{}"'.format(name,pwd))                 
        return True


    def uninstall_soft(self):
        if public.get_server_status(self._name) >= 0:  public.delete_server(self._name)

        return public.returnMsg(True,'卸载成功!');

    def update_soft(self,downurl):
        public.kill('redis_server.exe')
        public.kill('redis-server.exe')
        path = self._setup_path + '/redis'
        sfile = path +'/redis.windows.conf'
        dfile = path + 'redis.windows.conf.backup'
        shutil.copy (sfile,dfile)
        rRet = self.install_soft(downurl)
        if not rRet['status'] : rRet;
        if public.set_server_status(self._name,'stop'):
            shutil.copy (dfile,sfile)
            os.remove(dfile);
            if public.set_server_status(self._name,'start'):
                 return public.returnMsg(True,'更新成功!');
        return public.returnMsg(False,'更新失败!');



