Esempio n. 1
0
    def _find_sicd(self):
        self._is_sicd = False
        self._sicd_meta = None
        if self.des_subheader_offsets is None:
            return

        for i in range(self.des_subheader_offsets.size):
            subhead_bytes = self.get_des_subheader_bytes(i)
            if subhead_bytes.startswith(b'DEXML_DATA_CONTENT'):
                des_header = DataExtensionHeader.from_bytes(subhead_bytes, start=0)
                des_bytes = self.get_des_bytes(i)
                # noinspection PyBroadException
                try:
                    root_node, xml_ns = parse_xml_from_string(des_bytes.decode('utf-8').strip())
                    if 'SIDD' in root_node.tag:  # namespace makes this ugly
                        # NOTE that SIDD files are supposed to have the corresponding
                        # SICD xml as one of the DES AFTER the SIDD xml.
                        # The same basic format is used for both headers.
                        # So, abandon if we find a SIDD xml
                        self._des_index = None
                        self._des_header = None
                        self._is_sicd = False
                        break
                    elif 'SICD' in root_node.tag:  # namespace makes this ugly
                        self._des_index = i
                        self._des_header = des_header
                        self._is_sicd = True
                        self._sicd_meta = SICDType.from_node(root_node, xml_ns, ns_key='default')
                        break
                except Exception:
                    continue
            elif subhead_bytes.startswith(b'DESIDD_XML'):
                # This is an old format SIDD and can't be a SICD
                self._des_index = None
                self._des_header = None
                self._is_sicd = False
                break
            elif subhead_bytes.startswith(b'DESICD_XML'):
                # This is an old format SICD
                des_bytes = self.get_des_bytes(i)
                try:
                    root_node, xml_ns = parse_xml_from_string(des_bytes)
                    if 'SICD' in root_node.tag:  # namespace makes this ugly
                        self._des_index = i
                        self._des_header = None
                        self._is_sicd = True
                        self._sicd_meta = SICDType.from_node(root_node, xml_ns, ns_key='default')
                        break
                except Exception as e:
                    logging.error('We found an apparent old-style SICD DES header, '
                                  'but failed parsing with error {}'.format(e))
                    continue

        if not self._is_sicd:
            return
        self._sicd_meta.derive()
Esempio n. 2
0
    def find_des():
        for i in range(nitf_details.des_subheader_offsets.size):
            subhead_bytes = nitf_details.get_des_subheader_bytes(i)
            if nitf_details.nitf_version == '02.00':
                des_header = DataExtensionHeader0.from_bytes(subhead_bytes,
                                                             start=0)
            elif nitf_details.nitf_version == '02.10':
                des_header = DataExtensionHeader.from_bytes(subhead_bytes,
                                                            start=0)
            else:
                raise ValueError('Got unhandled NITF version {}'.format(
                    nitf_details.nitf_version))

            if subhead_bytes.startswith(b'DEXML_DATA_CONTENT'):
                des_bytes = nitf_details.get_des_bytes(i).decode(
                    'utf-8').strip().encode()
                # noinspection PyBroadException
                try:
                    root_node, xml_ns = parse_xml_from_string(des_bytes)
                    if 'SIDD' in root_node.tag:  # namespace makes this ugly
                        sidd_des.append(
                            (i, des_bytes, root_node, xml_ns, des_header))
                    elif 'SICD' in root_node.tag:
                        sicd_des.append(
                            (i, des_bytes, root_node, xml_ns, des_header))
                except Exception:
                    continue
            elif subhead_bytes.startswith(b'DESIDD_XML'):
                # This is an old format SIDD
                des_bytes = nitf_details.get_des_bytes(i).decode(
                    'utf-8').strip().encode()
                try:
                    root_node, xml_ns = parse_xml_from_string(des_bytes)
                    if 'SIDD' in root_node.tag:  # namespace makes this ugly
                        sidd_des.append(
                            (i, des_bytes, root_node, xml_ns, des_header))
                except Exception as e:
                    logger.exception(
                        'SIDD: Old-style SIDD DES header at index {}, but failed parsing'
                        .format(i))
                    continue
            elif subhead_bytes.startswith(b'DESICD_XML'):
                # This is an old format SICD
                des_bytes = nitf_details.get_des_bytes(i).decode(
                    'utf-8').strip().encode()
                try:
                    root_node, xml_ns = parse_xml_from_string(des_bytes)
                    if 'SICD' in root_node.tag:  # namespace makes this ugly
                        sicd_des.append(
                            (i, des_bytes, root_node, xml_ns, des_header))
                except Exception as e:
                    logger.exception(
                        'SIDD: Old-style SICD DES header at index {}, but failed parsing'
                        .format(i))
                    continue
Esempio n. 3
0
    def check_data_extension_headers():
        # type: () -> (str, Union[DataExtensionHeader, DataExtensionHeader0])
        sicd_des = []

        for i in range(nitf_details.des_subheader_offsets.size):
            subhead_bytes = nitf_details.get_des_subheader_bytes(i)
            des_bytes = None
            if subhead_bytes.startswith(b'DEXML_DATA_CONTENT'):
                des_bytes = nitf_details.get_des_bytes(i)

            elif subhead_bytes.startswith(b'DESIDD_XML'):
                raise ValueError(
                    'This file contains an old format SIDD DES, and should be a SIDD file'
                )
            elif subhead_bytes.startswith(b'DESICD_XML'):
                des_bytes = nitf_details.get_des_bytes(i)

            if des_bytes is None:
                continue

            # compare the SICD structure and the des header structure
            if nitf_details.nitf_version == '02.00':
                des_header = DataExtensionHeader0.from_bytes(subhead_bytes,
                                                             start=0)
            elif nitf_details.nitf_version == '02.10':
                des_header = DataExtensionHeader.from_bytes(subhead_bytes,
                                                            start=0)
            else:
                raise ValueError('Got unhandled NITF version {}'.format(
                    nitf_details.nitf_version))

            try:
                des_bytes = des_bytes.decode('utf-8').strip().encode()
                root_node, xml_ns = parse_xml_from_string(des_bytes)
                # namespace makes this ugly
                if 'SIDD' in root_node.tag:
                    raise ValueError(
                        'This file contains a SIDD DES, and should be a SIDD file'
                    )
                elif 'SICD' in root_node.tag:
                    sicd_des.append((i, des_bytes, des_header))
            except Exception as e:
                logger.error(
                    'Failed parsing the xml DES entry {} as xml'.format(i))
                raise e

        if len(sicd_des) == 0:
            raise ValueError(
                'No SICD DES values found, so this is not a viable SICD file')
        elif len(sicd_des) > 1:
            raise ValueError('Multiple SICD DES values found at indices {},\n'
                             'so this is not a viable SICD file'.format(
                                 [entry[0] for entry in sicd_des]))

        return sicd_des[0][1], sicd_des[0][2]
Esempio n. 4
0
def generic_nitf_header_test(instance, test_file):
    assert isinstance(instance, unittest.TestCase)

    # can we parse it at all? how long does it take?
    with instance.subTest(msg="header parsing"):
        start = time.time()
        details = NITFDetails(test_file)
        # how long does it take?
        logging.info('unpacked nitf details in {}'.format(time.time() - start))
        # how does it look?
        logging.debug(details.nitf_header)

    # is the output as long as it should be?
    with instance.subTest(msg="header length match"):
        header_string = details.nitf_header.to_bytes()
        equality = (len(header_string) == details.nitf_header.HL)
        if not equality:
            logging.error(
                'len(produced header) = {}, nitf_header.HL = {}'.format(
                    len(header_string), details.nitf_header.HL))
        instance.assertTrue(equality)

    # is the output what it should be?
    with instance.subTest(msg="header content match"):
        with open(test_file, 'rb') as fi:
            file_header = fi.read(details.nitf_header.HL)

        equality = (file_header == header_string)
        if not equality:
            chunk_size = 80
            start_chunk = 0
            while start_chunk < len(header_string):
                end_chunk = min(start_chunk + chunk_size, len(header_string))
                logging.error('real[{}:{}] = {}'.format(
                    start_chunk, end_chunk,
                    file_header[start_chunk:end_chunk]))
                logging.error('prod[{}:{}] = {}'.format(
                    start_chunk, end_chunk,
                    header_string[start_chunk:end_chunk]))
                start_chunk = end_chunk
        instance.assertTrue(equality)

    # is each image subheader working?
    if details.img_segment_offsets is not None:
        for i in range(details.img_segment_offsets.size):
            with instance.subTest('image subheader {} match'.format(i)):
                img_bytes = details.get_image_subheader_bytes(i)
                img_sub = ImageSegmentHeader.from_bytes(img_bytes, start=0)
                instance.assertEqual(len(img_bytes),
                                     img_sub.get_bytes_length(),
                                     msg='image subheader as long as expected')
                instance.assertEqual(
                    img_bytes,
                    img_sub.to_bytes(),
                    msg=
                    'image subheader serializes and deserializes as expected')

    # is each text segment working?
    if details.text_segment_offsets is not None:
        for i in range(details.text_segment_offsets.size):
            with instance.subTest('text subheader {} match'.format(i)):
                txt_bytes = details.get_text_subheader_bytes(i)
                txt_sub = TextSegmentHeader.from_bytes(txt_bytes, start=0)
                instance.assertEqual(len(txt_bytes),
                                     txt_sub.get_bytes_length(),
                                     msg='text subheader as long as expected')
                instance.assertEqual(
                    txt_bytes,
                    txt_sub.to_bytes(),
                    msg='text subheader serializes and deserializes as expected'
                )

    # is each graphics segment working?
    if details.graphics_segment_offsets is not None:
        for i in range(details.graphics_segment_offsets.size):
            with instance.subTest('graphics subheader {} match'.format(i)):
                graphics_bytes = details.get_graphics_subheader_bytes(i)
                graphics_sub = GraphicsSegmentHeader.from_bytes(graphics_bytes,
                                                                start=0)
                instance.assertEqual(
                    len(graphics_bytes),
                    graphics_sub.get_bytes_length(),
                    msg='graphics subheader as long as expected')
                instance.assertEqual(
                    graphics_bytes,
                    graphics_sub.to_bytes(),
                    msg=
                    'graphics subheader serializes and deserializes as expected'
                )

    # is each data extenson subheader working?
    if details.des_segment_offsets is not None:
        for i in range(details.des_segment_offsets.size):
            with instance.subTest('des subheader {} match'.format(i)):
                des_bytes = details.get_des_subheader_bytes(i)
                des_sub = DataExtensionHeader.from_bytes(des_bytes, start=0)
                instance.assertEqual(len(des_bytes),
                                     des_sub.get_bytes_length(),
                                     msg='des subheader as long as expected')
                instance.assertEqual(
                    des_bytes,
                    des_sub.to_bytes(),
                    msg='des subheader serializes and deserializes as expected'
                )