import datetime

from ..dojo_test_case import DojoTestCase

from dojo.models import Test
from dojo.tools.wpscan.parser import WpscanParser


class TestWpscanParser(DojoTestCase):

    def test_parse_file_empty(self):
        """Report from the tool wich have no data"""
        testfile = open("unittests/scans/wpscan/empty.json")
        parser = WpscanParser()
        findings = parser.get_findings(testfile, Test())
        self.assertEqual(0, len(findings))

    def test_parse_file_exemple(self):
        testfile = open("unittests/scans/wpscan/sample.json")
        parser = WpscanParser()
        findings = parser.get_findings(testfile, Test())
        for finding in findings:
            for endpoint in finding.unsaved_endpoints:
                endpoint.clean()
        self.assertEqual(4, len(findings))
        finding = findings[0]
        self.assertIsNone(finding.unique_id_from_tool)  # interesting findings are not vlunerability
        self.assertEqual("Info", finding.severity)  # it is not a vulnerability so severity should be 'Info'
        self.assertEqual("Interesting finding: Headers", finding.title)
        self.assertEqual(datetime.datetime(2021, 3, 26, 11, 50, 50), finding.date)

    def test_parse_file_with_no_vuln_has_no_findings(self):
        testfile = open("unittests/scans/wpscan/wordpress_no_vuln.json")
        parser = WpscanParser()
        findings = parser.get_findings(testfile, Test())
        for finding in findings:
            for endpoint in finding.unsaved_endpoints:
                endpoint.clean()
        self.assertEqual(7, len(findings))

    def test_parse_file_with_one_vuln_has_one_findings(self):
        testfile = open("unittests/scans/wpscan/wordpress_one_vuln.json")
        parser = WpscanParser()
        findings = parser.get_findings(testfile, Test())
        for finding in findings:
            for endpoint in finding.unsaved_endpoints:
                endpoint.clean()
        self.assertEqual(8, len(findings))
        finding = findings[0]
        self.assertEqual("8873", finding.unique_id_from_tool)
        self.assertNotEqual("Info", finding.severity)  # it is a vulnerability so not 'Info'
        self.assertEqual("YouTube Embed <= 11.8.1 - Cross-Site Request Forgery (CSRF)", finding.title)
        self.assertEqual(datetime.datetime(2019, 7, 2, 19, 11, 16), finding.date)

    def test_parse_file_with_multiple_vuln_has_multiple_finding(self):
        testfile = open("unittests/scans/wpscan/wordpress_many_vuln.json")
        parser = WpscanParser()
        findings = parser.get_findings(testfile, Test())
        for finding in findings:
            for endpoint in finding.unsaved_endpoints:
                endpoint.clean()
        self.assertEqual(8, len(findings))
        finding = findings[0]
        self.assertEqual("8873", finding.unique_id_from_tool)
        self.assertNotEqual("Info", finding.severity)  # it is a vulnerability so not 'Info'
        self.assertEqual("YouTube Embed <= 11.8.1 - Cross-Site Request Forgery (CSRF)", finding.title)
        self.assertEqual(datetime.datetime(2019, 7, 2, 19, 11, 16), finding.date)

    def test_parse_file_with_multiple_vuln(self):
        testfile = open("unittests/scans/wpscan/wpscan.json")
        parser = WpscanParser()
        findings = parser.get_findings(testfile, Test())
        for finding in findings:
            for endpoint in finding.unsaved_endpoints:
                endpoint.clean()
        self.assertEqual(6, len(findings))

        with self.subTest(i=0):
            finding = findings[0]
            self.assertEqual("7391118e-eef5-4ff8-a8ea-f6b65f442c63", finding.unique_id_from_tool)
            self.assertNotEqual("Info", finding.severity)  # it is a vulnerability so not 'Info'
            self.assertEqual("Contact Form 7 < 5.3.2 - Unrestricted File Upload", finding.title)
            self.assertEqual("CVE-2020-35489", finding.cve)
            self.assertEqual(datetime.datetime(2021, 3, 17, 12, 21, 6), finding.date)
            self.assertEqual("", finding.get_scanner_confidence_text())  # data are => 100%

        with self.subTest(i=4):
            finding = findings[4]
            self.assertIsNone(finding.unique_id_from_tool)  # interesting findings are not vlunerability
            self.assertEqual("Info", finding.severity)  # it is not a vulnerability so severity should be 'Info'
            self.assertEqual("Interesting finding: WordPress readme found: http://example/readme.html", finding.title)
            self.assertEqual(datetime.datetime(2021, 3, 17, 12, 21, 6), finding.date)
            self.assertEqual("", finding.get_scanner_confidence_text())  # data are => "confidence": 100,

    def test_parse_file_with_multiple_vuln_in_version(self):
        testfile = open("unittests/scans/wpscan/wordpress_vuln_version.json")
        parser = WpscanParser()
        findings = parser.get_findings(testfile, Test())
        for finding in findings:
            for endpoint in finding.unsaved_endpoints:
                endpoint.clean()
        self.assertEqual(11, len(findings))

        with self.subTest(i=2):
            finding = findings[2]
            self.assertEqual("d40374cf-ee95-40b7-9dd5-dbb160b877b1", finding.unique_id_from_tool)
            self.assertNotEqual("Info", finding.severity)  # it is a vulnerability so not 'Info'
            self.assertEqual("WordPress 2.8.1-4.7.2 - Control Characters in Redirect URL Validation", finding.title)
            self.assertEqual("fixed in : 4.6.4", finding.mitigation)
            self.assertEqual("", finding.get_scanner_confidence_text())  # data are => 100%

    def test_parse_file_issue5774(self):
        testfile = open("unittests/scans/wpscan/issue5774.json")
        parser = WpscanParser()
        findings = parser.get_findings(testfile, Test())
        for finding in findings:
            for endpoint in finding.unsaved_endpoints:
                endpoint.clean()
        self.assertEqual(59, len(findings))
        with self.subTest(i=0):
            finding = findings[0]
            self.assertEqual("16353d45-75d1-4820-b93f-daad90c322a8", finding.unique_id_from_tool)
            self.assertNotEqual("Info", finding.severity)
            self.assertEqual("All in One SEO Pack <= 2.9.1.1 - Authenticated Stored Cross-Site Scripting (XSS)", finding.title)
            self.assertEqual("fixed in : 2.10", finding.mitigation)
            self.assertEqual(7, finding.scanner_confidence)
            self.assertEqual("Tentative", finding.get_scanner_confidence_text())  # data are at 30%
        with self.subTest(i=30):
            finding = findings[0]
            self.assertEqual("16353d45-75d1-4820-b93f-daad90c322a8", finding.unique_id_from_tool)
            self.assertNotEqual("Info", finding.severity)
            self.assertEqual("All in One SEO Pack <= 2.9.1.1 - Authenticated Stored Cross-Site Scripting (XSS)", finding.title)
            self.assertEqual("fixed in : 2.10", finding.mitigation)
            self.assertEqual("Tentative", finding.get_scanner_confidence_text())  # data are at 30%

        with self.subTest(i=50):
            finding = findings[50]
            self.assertEqual("6a3ec618-c79e-4b9c-9020-86b157458ac5", finding.unique_id_from_tool)
            self.assertNotEqual("Info", finding.severity)
            self.assertEqual("WordPress 4.7-5.7 - Authenticated Password Protected Pages Exposure", finding.title)
            self.assertEqual("fixed in : 4.7.20", finding.mitigation)
            self.assertEqual(0, finding.scanner_confidence)
            finding.scanner_confidence = 1
            self.assertEqual("Certain", finding.get_scanner_confidence_text())  # data are => 100%

    def test_confidence(self):
        parser = WpscanParser()
        self.assertEquals(0, parser._get_scanner_confidence(100))
        self.assertEquals(5, parser._get_scanner_confidence(50))
        self.assertEquals(7, parser._get_scanner_confidence(30))
        self.assertEquals(10, parser._get_scanner_confidence(0))
