"""
Faraday Penetration Test IDE
Copyright (C) 2013  Infobyte LLC (http://www.infobytesec.com/)
See the file 'doc/LICENSE' for the license information

"""
from faraday_plugins.plugins.plugin import PluginBase
import re
import os



current_path = os.path.abspath(os.getcwd())

__author__ = "Francisco Amato"
__copyright__ = "Copyright (c) 2013, Infobyte LLC"
__credits__ = ["Francisco Amato"]
__license__ = ""
__version__ = "1.0.0"
__maintainer__ = "Francisco Amato"
__email__ = "famato@infobytesec.com"
__status__ = "Development"


class WebfuzzerParser:
    """
    The objective of this class is to parse an xml file generated by the webfuzzer tool.

    TODO: Handle errors.
    TODO: Test webfuzzer output version. Handle what happens if the parser doesn't support it.
    TODO: Test cases.

    @param webfuzzer_filepath A proper output generated by webfuzzer
    """

    def __init__(self, webfuzzer_filepath):
        self.filepath = webfuzzer_filepath

        with open(self.filepath) as f:
            try:
                data = f.read()
                f.close()
                m = re.search(
                    r"Scan of ([\w.]+):([\d]+) \[([/\w]+)\] \(([\w.]+)\)", data)
                self.hostname = m.group(1)
                self.port = m.group(2)
                self.uri = m.group(3)
                self.ipaddress = m.group(4)

                m = re.search("Server header:\n\n([\\w\\W]+)\n\n\n", data)
                self.header = m.group(1)

                self.items = []

                pattern = r'\((POST|GET)\): ([\w\W]*?) \]--'

                for m in re.finditer(pattern, data, re.DOTALL):

                    method = m.group(1)
                    info = re.search(
                        "^([\\w\\W]+)\\(([\\w\\W]+)\\)\n--\\[ ([\\w\\W]+)$", m.group(2))

                    vuln = {'method': m.group(1), 'desc': info.group(
                        1), 'url': info.group(2), 'resp': info.group(3)}
                    self.items.append(vuln)

            except SyntaxError as err:
                return None


class WebfuzzerPlugin(PluginBase):
    """
    Example plugin to parse webfuzzer output.
    """

    def __init__(self, *arg, **kwargs):
        super().__init__(*arg, **kwargs)
        self.id = "Webfuzzer"
        self.name = "Webfuzzer Output Plugin"
        self.plugin_version = "0.0.2"
        self.version = "0.2.0"
        self.options = None
        self._current_output = None
        self.host = None
        self._command_regex = re.compile(r'^(sudo webfuzzer|webfuzzer|\.\/webfuzzer)\s+.*?')
        self._completition = {'': '__Usage: ./webfuzzer -G|-P URL [OPTIONS]',
                              '-G': '<url>	get this as starting url (with parameters)',
                              '-P': '<url>	post this as starting url (with parameters)',
                              '-x': 'html output (txt default)',
                              '-c': 'use cookies',
                              '-C': '<cookies>	set this cookie(s) **',
                              '-s': 'check for sql, asp, vb, php errors (default)',
                              '-d': 'check for directory traversal *',
                              '-p': 'check for insecure perl open or xss *',
                              '-e': 'check for execution through shell escapes or xss *',
                              '-a': 'set all of the above switches on *',
                              }

        self._output_path = None

    def parseOutputString(self, output):
        """
        This method will discard the output the shell sends, it will read it from
        the xml where it expects it to be present.
        """

        if self._output_path is None:
            return False
        else:
            if not os.path.exists(self._output_path):
                return False

            parser = WebfuzzerParser(self._output_path)
            h_id = self.createAndAddHost(parser.ipaddress, hostnames=[parser.hostname])
            first = True
            for item in parser.items:
                if first:
                    s_id = self.createAndAddServiceToHost(h_id, parser.port, "tcp", ports=[parser.port])
                    first = False
                v_id = self.createAndAddVulnWebToService(h_id, s_id, name=item['desc'],path=item['url'],
                                                         response=item['resp'], method=item['method'],
                                                         website=parser.hostname)

        del parser

        return True

    def processCommandString(self, username, current_path, command_string):
        """
        """
        super().processCommandString(username, current_path, command_string)
        host = re.search(r"\-([G|P]) ([\w\.\-]+)", command_string)
        if host is not None:
            self.host = host.group(2)
            self._output_path = current_path + "/" + self.host + ".txt"


def createPlugin(*args, **kwargs):
    return WebfuzzerPlugin(*args, **kwargs)
