Exemple #1
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
Exemple #2
0
    def _find_sidd(self):
        self._is_sidd = False
        if self.des_subheader_offsets is None:
            return

        self._sidd_meta = []
        self._sicd_meta = []

        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_bytes = self.get_des_bytes(i)
                try:
                    root_node, xml_ns = parse_xml_from_string(des_bytes)
                    if 'SIDD' in root_node.tag:
                        self._is_sidd = True
                        self._sidd_meta.append(SIDDType.from_node(root_node, xml_ns, ns_key='default'))
                    elif 'SICD' in root_node.tag:
                        self._sicd_meta.append(SICDType.from_node(root_node, xml_ns, ns_key='default'))
                except Exception as e:
                    logger.error('Failed checking des xml header at index {} with error {}'.format(i, e))
                    continue
            elif subhead_bytes.startswith(b'DESIDD_XML'):
                # This is an old format SIDD header
                des_bytes = self.get_des_bytes(i)
                try:
                    root_node, xml_ns = parse_xml_from_string(des_bytes)
                    if 'SIDD' in root_node.tag:
                        self._is_sidd = True
                        self._sidd_meta.append(SIDDType.from_node(root_node, xml_ns, ns_key='default'))
                except Exception as e:
                    logger.error(
                        'We found an apparent old-style SIDD DES header at index {},\n\t'
                        'but failed parsing with error {}'.format(i, e))
                    continue
            elif subhead_bytes.startswith(b'DESICD_XML'):
                # This is an old format SICD header
                des_bytes = self.get_des_bytes(i)
                try:
                    root_node, xml_ns = parse_xml_from_string(des_bytes)
                    if 'SICD' in root_node.tag:
                        self._sicd_meta.append(SICDType.from_node(root_node, xml_ns, ns_key='default'))
                except Exception as e:
                    logger.error(
                        'We found an apparent old-style SICD DES header at index {},\n\t'
                        'but failed parsing with error {}'.format(i, e))
                    continue

        if not self._is_sidd:
            return

        for sicd in self._sicd_meta:
            sicd.derive()
Exemple #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]
Exemple #4
0
    def from_xml_string(cls, xml_string):
        """
        Construct the research object from an xml string.

        Parameters
        ----------
        xml_string : str|bytes

        Returns
        -------
        ResearchType
        """

        root_node, xml_ns = parse_xml_from_string(xml_string)
        ns_key = 'default' if 'default' in xml_ns else None
        return cls.from_node(root_node, xml_ns=xml_ns, ns_key=ns_key)
Exemple #5
0
def _evaluate_xml_string_validity(xml_string=None):
    """
    Check the validity of the SIDD xml, as defined by the given string.

    Parameters
    ----------
    xml_string : str|bytes

    Returns
    -------
    is_valid : bool
    sidd_urn : str
    sidd : SIDDType1|SIDDType2
    """

    root_node, xml_ns = parse_xml_from_string(xml_string)
    if 'default' not in xml_ns:
        raise ValueError(
            'Could not properly interpret the namespace collection from xml\n{}'.format(xml_ns))

    # todo: validate the xml namespace elements here

    sidd_urn = xml_ns['default']
    # check that our urn is mapped
    try:
        _ = get_urn_details(sidd_urn)
        check_schema = True
    except Exception as e:
        logger.exception('SIDD: The SIDD namespace has unrecognized value')
        check_schema = False

    valid_xml = None
    if check_schema:
        valid_xml = evaluate_xml_versus_schema(xml_string, sidd_urn)
    if valid_xml is None:
        valid_xml = True

    # perform the various sidd structure checks
    if sidd_urn == 'urn:SIDD:1.0.0':
        the_sidd = SIDDType1.from_node(root_node, xml_ns=xml_ns)
        valid_sidd_contents = the_sidd.is_valid(recursive=True, stack=False)
    elif sidd_urn == 'urn:SIDD:2.0.0':
        the_sidd = SIDDType2.from_node(root_node, xml_ns=xml_ns)
        valid_sidd_contents = the_sidd.is_valid(recursive=True, stack=False)
    else:
        raise ValueError('Got unhandled urn {}'.format(sidd_urn))
    return valid_xml & valid_sidd_contents, sidd_urn, the_sidd
Exemple #6
0
    def _extract_crsd(self):
        """
        Extract and interpret the CRSD structure from the file.
        """

        xml = self.get_crsd_bytes()
        if self.crsd_version.startswith('1.0'):
            the_type = CRSDType
        else:
            raise ValueError(_unhandled_version_text.format(self.crsd_version))

        root_node, xml_ns = parse_xml_from_string(xml)
        if 'default' in xml_ns:
            self._crsd_meta = the_type.from_node(root_node,
                                                 xml_ns,
                                                 ns_key='default')
        else:
            self._crsd_meta = the_type.from_node(root_node, xml_ns)
Exemple #7
0
def _evaluate_xml_string_validity(xml_string):
    """
    Check the validity of the SICD xml, as defined by the given string.

    Parameters
    ----------
    xml_string : str|bytes

    Returns
    -------
    (bool, str, SICDType)
    """

    root_node, xml_ns = parse_xml_from_string(xml_string)
    if xml_ns is None:
        raise ValueError(
            'SICD XML invalid, because no apparent namespace defined in the xml,\n\t'
            'which starts `{}...`'.format(xml_string[:15]))

    if 'default' not in xml_ns:
        raise ValueError(
            'Could not properly interpret the namespace collection from xml\n{}'
            .format(xml_ns))

    sicd_urn = xml_ns['default']
    # check that our urn is mapped
    try:
        _ = get_urn_details(sicd_urn)
        check_schema = True
    except Exception as e:
        logger.exception('SICD: The SICD namespace has unrecognized value')
        check_schema = False

    valid_xml = None
    if check_schema:
        valid_xml = evaluate_xml_versus_schema(xml_string, sicd_urn)
    if valid_xml is None:
        valid_xml = True

    # perform the various sicd structure checks
    the_sicd = SICDType.from_node(root_node, xml_ns=xml_ns)
    valid_sicd_contents = the_sicd.is_valid(recursive=True, stack=False)
    return valid_xml & valid_sicd_contents, sicd_urn, the_sicd
Exemple #8
0
    def get_sicd(self):
        """
        Extract the SICD details.

        Returns
        -------
        SICDType
        """

        if self._sicd is not None:
            return self._sicd
        if self._user_data is None:
            self._read_user_data()
        if self._caspr_data is None:
            self._find_caspr_data()
        # Check if the user data contains a sicd structure.
        sicd_string = None
        for nam in ['SICDMETA', 'SICD_META', 'SICD']:
            if sicd_string is None:
                sicd_string = self._user_data.get(nam, None)
        # If so, assume that this SICD is valid and simply present it
        if sicd_string is not None:
            root_node, xml_ns = parse_xml_from_string(sicd_string)
            self._sicd = SICDType.from_node(root_node, xml_ns)
            self._sicd.derive()
        else:
            # otherwise, we populate a really minimal sicd structure
            num_rows, num_cols = self.data_size
            self._sicd = SICDType(ImageData=ImageDataType(NumRows=num_rows,
                                                          NumCols=num_cols,
                                                          FirstRow=0,
                                                          FirstCol=0,
                                                          PixelType=self.pixel_type,
                                                          FullImage=FullImageType(NumRows=num_rows,
                                                                                  NumCols=num_cols),
                                                          SCPPixel=RowColType(Row=num_rows/2,
                                                                              Col=num_cols/2)))
        return self._sicd
Exemple #9
0
    def _find_sicd(self) -> None:
        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().encode())
                    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
                        if xml_ns is None:
                            self._sicd_meta = SICDType.from_node(root_node, xml_ns, ns_key=None)
                        else:
                            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.decode('utf-8').strip().encode())
                    if 'SICD' in root_node.tag:  # namespace makes this ugly
                        self._des_index = i
                        self._des_header = None
                        self._is_sicd = True
                        if xml_ns is None:
                            self._sicd_meta = SICDType.from_node(root_node, xml_ns, ns_key=None)
                        else:
                            self._sicd_meta = SICDType.from_node(root_node, xml_ns, ns_key='default')
                        break
                except Exception as e:
                    logger.error(
                        'We found an apparent old-style SICD DES header,\n\t'
                        'but failed parsing with error {}'.format(e))
                    continue

        if not self._is_sicd:
            return

        # noinspection PyBroadException
        try:
            self._sicd_meta.derive()
        except Exception as e:
            pass