示例#1
0
    def process_model(self, template_root: et.ElementBase,
                      diagram_root: et.ElementBase):
        """Обработка модели и создание выходной диаграммы с использованием шаблона"""

        print("MODEL:")
        # print(model)
        pprint(self.model, indent=2, width=120)

        figure_templates: Dict[str, et.ElementBase] = {}
        for obj in template_root.findall(f'object[@type]'):
            obj_type: str = obj.attrib.get("type")
            figure_templates[obj_type] = obj
        print('TEMPLATE OBJECTS:')
        pprint(list(figure_templates.keys()))

        # словарь условных стилей, применяемых к фигурам в зависимости от значений их атрибутов
        # ключ = ключ из модели
        # значение - массив из xml-объектов, в каждом из которых определены свойства key, value и style
        # - key: используется в качестве ключа.
        #        Стиль будет применен к фигурам, для которых в yml-модели указан данный ключ
        # - value: используется как селектор значений.
        #          Будет применен стиль объекта, для которого в yml-модели для ключа key указано данное значение
        # - attributes: используется как селектор атрибутов. Список имен атрибутов, разделенный символом ';'
        #          К целевой фигуре будут применены атрибуты форматирования фигуры со стилем, перечисленные в style
        style_templates: Dict[str, List[et.ElementBase]] = {}
        for obj in template_root.findall(f'object[@key]'):
            style_key: str = obj.attrib.get("key")
            if style_key not in style_templates:
                style_templates[style_key] = []
            style_templates[style_key].append(obj)
        print('STYLE OBJECTS:')
        pprint(list(style_templates.keys()))

        # шаблонов фигур
        # for obj in figure_templates.values():
        #     obj.getparent().remove(obj)
        #
        # for styles in style_templates.values():
        #     for obj in styles:
        #         obj.getparent().remove(obj)

        # обработаем модель
        root_figure: Figure = Figure()
        model = Model(figure_templates, style_templates, diagram_root)
        model.iterate(self.model, root_figure)

        root_figure.resize()

        # очистим выходную диаграмму от объектов, которых нет в модели
        for obj in diagram_root.findall(f'object'):
            if obj.attrib['id'] not in g_figures:
                diagram_root.remove(obj)
示例#2
0
文件: other.py 项目: chemputer/track
 def _get_default_value_from_section(self, section: etree.ElementBase):
     """
     <Default>
         <item> 1.0 </item>
         <item> 1.0 </item>
         <item> 1.0 </item>
     </Default>
     """
     defaults = []
     for it in section.findall('item'):
         defaults.append(self.type.get_default_value(it))
     return defaults
示例#3
0
def rss_document_to_feed_items(feed: Feed,
                               tree: ElementBase) -> List[FeedItem]:
    """Creates a list of FeedItem objects from a xml tree for the feed."""
    item_elements = tree.findall("channel/item")
    return [
        FeedItem(
            feed_id=feed.feed_id,
            title=item_element.findtext("title"),
            link=sanitize_link(item_element.findtext("link")),
            description=parse_description(
                item_element.findtext("description")),
            last_seen=now_in_utc(),
            published=_parse_optional_rss_datetime(
                item_element.findtext("pubDate")),
            created_on=now_in_utc(),
        ) for item_element in item_elements
    ]
示例#4
0
def atom_document_to_feed_items(feed: Feed,
                                tree: ElementBase) -> List[FeedItem]:
    item_elements = tree.findall("{http://www.w3.org/2005/Atom}entry")
    return [
        FeedItem(
            feed_id=feed.feed_id,
            title=item_element.findtext("{http://www.w3.org/2005/Atom}title"),
            link=_parse_optional_link_for_href(
                item_element.find("{http://www.w3.org/2005/Atom}link")),
            description=item_element.findtext(
                "{http://www.w3.org/2005/Atom}content") or "",
            last_seen=now_in_utc(),
            published=_parse_optional_datetime(
                item_element.findtext(
                    "{http://www.w3.org/2005/Atom}published")),
            created_on=now_in_utc(),
        ) for item_element in item_elements
    ]
    def from_section(cls, section: etree.ElementBase, alias):
        args = []
        if section.find('Args') is not None:
            for item in section.find('Args'):
                args.append(
                    MethodArgument(
                        name=item.tag,
                        type_=alias.get_data_type_from_section(item)))
        else:
            for item in section.findall('Arg'):
                args.append(
                    MethodArgument(
                        type_=alias.get_data_type_from_section(item)))

        header_section = section.find('VariableLengthHeaderSize')
        try:
            header_size = int(header_section.text.strip())
        except (ValueError, AttributeError):
            header_size = DEFAULT_HEADER_SIZE

        return cls(section.tag, list(args), header_size)
示例#6
0
def verify_xml_signature(
    xml_doc: XmlElement,
    trusted_x509_cert: Union[crypto_utils.X509Cert,
                             crypto_utils._X509CertOpenSsl] = None,
) -> Tuple[bytes, XmlElementTree, XmlElementTree]:
    """
    Verify the XML signature in ``xml_doc``.

    .. note::
        XML document with more than one signature is not supported.

    If the inputs are ok but the XML signature does not verify,
    raises :class:`XmlSignatureUnverified`.

    If ``trusted_x509_cert`` is None, it requires that the signature in
    ``xml_doc`` includes a a valid X.509 **certificate chain** that
    validates against the *known certificate authorities*.

    If ``trusted_x509_cert`` is given, it must be a **trusted** external
    X.509 certificate, and the verification will be of whether the XML
    signature in ``xml_doc`` was signed by ``trusted_x509_cert`` or not;
    thus **it overrides** any X.509 certificate information included
    in the signature.

    .. note::
        It is strongly recommended to validate ``xml_doc`` beforehand
        (against the corresponding XML schema, using :func:`validate_xml_doc`).

    :param xml_doc:
    :param trusted_x509_cert: a trusted external X.509 certificate, or None
    :raises :class:`XmlSignatureUnverified`:
        signature did not verify
    :raises :class:`XmlSignatureInvalidCertificate`:
        certificate validation failed
    :raises :class:`XmlSignatureInvalid`:
        signature is invalid
    :raises :class:`XmlSchemaDocValidationError`:
        XML doc is not valid
    :raises :class:`ValueError`:

    """
    if not isinstance(xml_doc, XmlElement):
        raise TypeError("'xml_doc' must be an XML document/element.")

    n_signatures = (
        len(xml_doc.findall('.//ds:Signature', namespaces=XML_DSIG_NS_MAP)) +
        len(xml_doc.findall('.//dsig11:Signature',
                            namespaces=XML_DSIG_NS_MAP)) +
        len(xml_doc.findall('.//dsig2:Signature', namespaces=XML_DSIG_NS_MAP)))

    if n_signatures > 1:
        raise NotImplementedError(
            "XML document with more than one signature is not supported.")

    xml_verifier = signxml.XMLVerifier()

    if isinstance(trusted_x509_cert, crypto_utils._X509CertOpenSsl):
        trusted_x509_cert_open_ssl = trusted_x509_cert
    elif isinstance(trusted_x509_cert, crypto_utils.X509Cert):
        trusted_x509_cert_open_ssl = crypto_utils._X509CertOpenSsl.from_cryptography(
            trusted_x509_cert)
    elif trusted_x509_cert is None:
        trusted_x509_cert_open_ssl = None
    else:
        # A 'crypto_utils._X509CertOpenSsl' is ok but we prefer 'crypto_utils.X509Cert'.
        raise TypeError(
            "'trusted_x509_cert' must be a 'crypto_utils.X509Cert' instance, or None."
        )

    # warning: performance issue.
    # note: 'signxml.XMLVerifier.verify()' calls 'signxml.util.XMLProcessor.get_root()',
    #   which converts the data to string, and then reparses it using the same function we use
    #   in 'parse_untrusted_xml()' ('defusedxml.lxml.fromstring'), but without all the precautions
    #   we have there. See:
    #      https://github.com/XML-Security/signxml/blob/v2.6.0/signxml/util/__init__.py#L141-L151
    #   Considering that, we'd rather write to bytes ourselves and control the process.
    f = io.BytesIO()
    write_xml_doc(xml_doc, f)
    tmp_bytes = f.getvalue()

    try:
        # note: by passing 'x509_cert' we override any X.509 certificate information supplied
        #   by the signature itself.

        # note: when an X509Data element is present in the signature and used for verification, but
        #   a KeyValue element is also present, there is an ambiguity and a security hazard because
        #   the public key used to sign the document is already encoded in the certificate (which is
        #   in X509Data), so the verifier must either ignore KeyValue or ensure that it matches what
        #   is in the certificate. SignXML does not perform that validation and throws an
        #   'InvalidInput' error instead.
        #
        #   SII's schema for XML signatures requires both elements to be present, which forces us to
        #   enable 'ignore_ambiguous_key_info' to bypass the error and validate the signature using
        #   X509Data only.
        #
        #   Source:
        #   https://github.com/XML-Security/signxml/commit/ef15da8dbb904f1dedfdd210ae3e0df5da535612
        result: signxml.VerifyResult = xml_verifier.verify(
            data=tmp_bytes,
            require_x509=True,
            x509_cert=trusted_x509_cert_open_ssl,
            ignore_ambiguous_key_info=True,
        )

    except signxml.exceptions.InvalidDigest as exc:
        # warning: catch before 'InvalidSignature' (it is the parent of 'InvalidDigest').
        raise XmlSignatureUnverified(str(exc)) from exc

    except signxml.exceptions.InvalidCertificate as exc:
        # warning: catch before 'InvalidSignature' (it is the parent of 'InvalidCertificate').
        raise XmlSignatureInvalidCertificate(str(exc)) from exc

    except signxml.exceptions.InvalidSignature as exc:
        # XML signature is invalid, for any reason.
        raise XmlSignatureInvalid(str(exc)) from exc

    except signxml.exceptions.InvalidInput as exc:
        raise ValueError("Invalid input.", str(exc)) from exc

    except lxml.etree.DocumentInvalid as exc:
        # Simplest and safest way to get the error message (see 'validate_xml_doc()').
        # Error example:
        #   "Element '{http://www.w3.org/2000/09/xmldsig#}X509Certificate': '\nabc\n' is not a
        #   valid value of the atomic type 'xs:base64Binary'., line 30"
        validation_error_msg = str(exc)
        raise XmlSchemaDocValidationError(validation_error_msg) from exc

    return result.signed_data, result.signed_xml, result.signature_xml