# Path: ptp/libptp/exceptions.py
# class NotSupportedVersionError(PTPError):
#     """:mod:`ptp` error when the version of the tool is not supported."""
#     pass
# 
# Path: ptp/tools/burpsuite/parser.py
# class BurpXMLParser(XMLParser):
#     """BurpSuite XML specialized parser."""
# 
#     __tool__ = 'burpsuite'
#     __version__ = r'1\.[0-9]+[\.[0-9]+]?'
# 
#     @classmethod
#     def is_mine(cls, pathname, filename='*.xml', light=False, first=True):
#         """Check if it can handle the report file.
# 
#         :param str pathname: Path to the report directory.
#         :param str filename: Regex matching the report file.
#         :param bool light: `True` to only parse the ranking of the findings from the report.
#         :param bool first: Only process first file (``True``) or each file that matched (``False``).
# 
#         :return: `True` if it supports the report, `False` otherwise.
#         :rtype: :class:`bool`
# 
#         """
#         try:
#             stream = cls.handle_file(pathname, filename, first=first)
#         except (TypeError, XMLSyntaxError):
#             return False
#         version = stream.attrib.get('burpVersion', '')
#         if not version:
#             return False
#         if not re.findall(cls.__version__, version, re.IGNORECASE):
#             return False
#         return True
# 
#     def parse_metadata(self):
#         """Parse the metadata of the report.
# 
#         :raises: :class:`NotSupportedVersionError` -- if it does not support the version of this report.
# 
#         :return: The metadata of the report.
#         :rtype: dict
# 
#         """
#         raw_metadata = self.stream.attrib.get('burpVersion', '')
#         # Reconstruct the metadata
#         # TODO: Retrieve the other metadata likes the date, etc.
#         metadata = {'version': raw_metadata}
#         if self.check_version(metadata):
#             self.metadata = metadata
#         else:
#             raise NotSupportedVersionError('PTP does NOT support this version of BurpSuite.')
#         return self.metadata
# 
#     def parse_report(self):
#         """Parse the results of the report.
# 
#         :return: List of dicts where each one has a request and response.
#         :rtype: :class:`list`
# 
#         """
#         self.data = []
#         data = []
#         # TODO: maybe a better way to get base64 value
#         if self.stream.find('.//request').attrib['base64'] == 'false':
#             is_base64 = False
#         else:
#             is_base64 = True
#         for item in self.stream.findall('.//item'):
#             response_status_code = item.find('status').text
#             if is_base64:
#                 request = base64.b64decode(item.find('request').text).decode('utf-8')
#                 response = base64.b64decode(item.find('response').text).decode('utf-8')
#             else:
#                 request = item.find('request').text
#                 response = item.find('response').text
#             response_headers, response_body = response.split('\r\n\r\n', 1)
#             # Somehow follow naming conventions from http://docs.python-requests.org/en/master/
#             data.append({
#                 'request': request,
#                 'status_code': response_status_code,
#                 'headers': response_headers,
#                 'body': response_body
#             })
#         self.data.append({'ranking': constants.UNKNOWN, 'transactions': data})
#         return self.data


import mock
import unittest
from lxml import etree
from hamcrest import assert_that, has_entry, equal_to
from ptp.libptp.exceptions import NotSupportedVersionError
from ptp.tools.burpsuite.parser import BurpXMLParser
        from .burp_1_6_30_report import report_true
        from .burp_1_6_30_report import report_true
        from .burp_1_6_30_report import report_true
        from .burp_1_6_30_report import report_true
        from .burp_1_6_30_report import report_true
        from .burp_1_6_30_report import report_true

class TestBurpXMLParser(unittest.TestCase):

    ###
    # BurpXMLParser.is_mine
    ###
    @mock.patch('lxml.etree.parse', side_effect=lxml_etree_parse)
    def test_parser_burp_xml_is_mine(self, mock_lxml_etree_parse):
        with mock.patch('ptp.libptp.parser.AbstractParser._recursive_find', return_value=[report_true]):
            BurpXMLParser.__format__ = ''
            self.assertTrue(BurpXMLParser.is_mine('foo', 'bar', first=True))

    @mock.patch('lxml.etree.parse', side_effect=lxml_etree_parse)
    def test_parser_burp_xml_is_not_mine(self, mock_lxml_etree_parse):
        with mock.patch('ptp.libptp.parser.AbstractParser._recursive_find', return_value=['foo.bar']):
            BurpXMLParser.__format__ = ''
            self.assertFalse(BurpXMLParser.is_mine('foo', 'bar', first=True))

    @mock.patch('lxml.etree.parse', side_effect=lxml_etree_parse)
    def test_parser_burp_xml_is_mine_no_version(self, mock_lxml_etree_parse):
        stripped_report = report_true.replace('<items burpVersion="1.6.30"', '<items NOTVERSIONNEVER="1.6.30"')
        with mock.patch('ptp.libptp.parser.AbstractParser._recursive_find', return_value=[stripped_report]):
            BurpXMLParser.__format__ = ''
            self.assertFalse(BurpXMLParser.is_mine('foo', 'bar', first=True))

    @mock.patch('lxml.etree.parse', side_effect=lxml_etree_parse)
    def test_parser_burp_xml_is_mine_version_not_supported(self, mock_lxml_etree_parse):
        stripped_report = report_true.replace('<items burpVersion="1.6.30"', '<items burpVersion="NOTSUPPORTEDVERSION"')
        with mock.patch('ptp.libptp.parser.AbstractParser._recursive_find', return_value=[stripped_report]):
            BurpXMLParser.__format__ = ''

# Path: ptp/libptp/exceptions.py
# class NotSupportedVersionError(PTPError):
#     """:mod:`ptp` error when the version of the tool is not supported."""
#     pass
# 
# Path: ptp/tools/burpsuite/parser.py
# class BurpXMLParser(XMLParser):
#     """BurpSuite XML specialized parser."""
# 
#     __tool__ = 'burpsuite'
#     __version__ = r'1\.[0-9]+[\.[0-9]+]?'
# 
#     @classmethod
#     def is_mine(cls, pathname, filename='*.xml', light=False, first=True):
#         """Check if it can handle the report file.
# 
#         :param str pathname: Path to the report directory.
#         :param str filename: Regex matching the report file.
#         :param bool light: `True` to only parse the ranking of the findings from the report.
#         :param bool first: Only process first file (``True``) or each file that matched (``False``).
# 
#         :return: `True` if it supports the report, `False` otherwise.
#         :rtype: :class:`bool`
# 
#         """
#         try:
#             stream = cls.handle_file(pathname, filename, first=first)
#         except (TypeError, XMLSyntaxError):
#             return False
#         version = stream.attrib.get('burpVersion', '')
#         if not version:
#             return False
#         if not re.findall(cls.__version__, version, re.IGNORECASE):
#             return False
#         return True
# 
#     def parse_metadata(self):
#         """Parse the metadata of the report.
# 
#         :raises: :class:`NotSupportedVersionError` -- if it does not support the version of this report.
# 
#         :return: The metadata of the report.
#         :rtype: dict
# 
#         """
#         raw_metadata = self.stream.attrib.get('burpVersion', '')
#         # Reconstruct the metadata
#         # TODO: Retrieve the other metadata likes the date, etc.
#         metadata = {'version': raw_metadata}
#         if self.check_version(metadata):
#             self.metadata = metadata
#         else:
#             raise NotSupportedVersionError('PTP does NOT support this version of BurpSuite.')
#         return self.metadata
# 
#     def parse_report(self):
#         """Parse the results of the report.
# 
#         :return: List of dicts where each one has a request and response.
#         :rtype: :class:`list`
# 
#         """
#         self.data = []
#         data = []
#         # TODO: maybe a better way to get base64 value
#         if self.stream.find('.//request').attrib['base64'] == 'false':
#             is_base64 = False
#         else:
#             is_base64 = True
#         for item in self.stream.findall('.//item'):
#             response_status_code = item.find('status').text
#             if is_base64:
#                 request = base64.b64decode(item.find('request').text).decode('utf-8')
#                 response = base64.b64decode(item.find('response').text).decode('utf-8')
#             else:
#                 request = item.find('request').text
#                 response = item.find('response').text
#             response_headers, response_body = response.split('\r\n\r\n', 1)
#             # Somehow follow naming conventions from http://docs.python-requests.org/en/master/
#             data.append({
#                 'request': request,
#                 'status_code': response_status_code,
#                 'headers': response_headers,
#                 'body': response_body
#             })
#         self.data.append({'ranking': constants.UNKNOWN, 'transactions': data})
#         return self.data


# Path: tests/tools/burpsuite/test_parser.py
import mock
import unittest
from lxml import etree
from hamcrest import assert_that, has_entry, equal_to
from ptp.libptp.exceptions import NotSupportedVersionError
from ptp.tools.burpsuite.parser import BurpXMLParser
        from .burp_1_6_30_report import report_true
        from .burp_1_6_30_report import report_true
        from .burp_1_6_30_report import report_true
        from .burp_1_6_30_report import report_true
        from .burp_1_6_30_report import report_true
        from .burp_1_6_30_report import report_true


class TestBurpXMLParser(unittest.TestCase):

    ###
    # BurpXMLParser.is_mine
    ###
    @mock.patch('lxml.etree.parse', side_effect=lxml_etree_parse)
    def test_parser_burp_xml_is_mine(self, mock_lxml_etree_parse):
        with mock.patch('ptp.libptp.parser.AbstractParser._recursive_find', return_value=[report_true]):
            BurpXMLParser.__format__ = ''
            self.assertTrue(BurpXMLParser.is_mine('foo', 'bar', first=True))

    @mock.patch('lxml.etree.parse', side_effect=lxml_etree_parse)
    def test_parser_burp_xml_is_not_mine(self, mock_lxml_etree_parse):
        with mock.patch('ptp.libptp.parser.AbstractParser._recursive_find', return_value=['foo.bar']):
            BurpXMLParser.__format__ = ''
            self.assertFalse(BurpXMLParser.is_mine('foo', 'bar', first=True))

    @mock.patch('lxml.etree.parse', side_effect=lxml_etree_parse)
    def test_parser_burp_xml_is_mine_no_version(self, mock_lxml_etree_parse):
        stripped_report = report_true.replace('<items burpVersion="1.6.30"', '<items NOTVERSIONNEVER="1.6.30"')
        with mock.patch('ptp.libptp.parser.AbstractParser._recursive_find', return_value=[stripped_report]):
            BurpXMLParser.__format__ = ''
            self.assertFalse(BurpXMLParser.is_mine('foo', 'bar', first=True))

    @mock.patch('lxml.etree.parse', side_effect=lxml_etree_parse)
    def test_parser_burp_xml_is_mine_version_not_supported(self, mock_lxml_etree_parse):
        stripped_report = report_true.replace('<items burpVersion="1.6.30"', '<items burpVersion="NOTSUPPORTEDVERSION"')
        with mock.patch('ptp.libptp.parser.AbstractParser._recursive_find', return_value=[stripped_report]):
            BurpXMLParser.__format__ = ''

            self.assertFalse(BurpXMLParser.is_mine('foo', 'bar', first=True))