Skip to main content

structured_xades/policy/
syntax.rs

1//! Scalar obligations of recognized original policy qualifiers.
2
3use super::{Declaration, Original, XADES, XADES_141, named, user_notice_with};
4use crate::identifier;
5use crate::properties::Error;
6use crate::reference::LexicalSource;
7use crate::scalar::{self, Datatype, ScalarXml, UriXml};
8use crate::xml::{Access, AccessError, Xml};
9use structured_asn1::memory::Work;
10
11/// A syntax/source/resource refusal, without application-policy interpretation.
12#[derive(Debug)]
13pub enum SyntaxError<E, N> {
14    /// Original qualifier grammar or source refusal.
15    Structure(Error<E, N>),
16    /// Requested original base-datatype refusal; Unsupported is not Malformed.
17    Scalar(scalar::Error<E, N>),
18    /// A technical-specification identifier's original URI syntax refusal.
19    Identifier(identifier::CheckError<E, N>),
20}
21
22impl<E, N> From<Error<E, N>> for SyntaxError<E, N> {
23    fn from(cause: Error<E, N>) -> Self {
24        Self::Structure(cause)
25    }
26}
27
28/// Qualifier syntax result in the original XML owner's identity/error domain.
29pub type SyntaxResult<X> = Result<(), SyntaxError<<X as Xml>::Error, <X as Xml>::Id>>;
30
31/// Check recognized SPURI, `SPUserNotice` and `SPDocSpecification` payloads in the
32/// original selected policy. Unknown `AnyType` payloads remain delegated; this
33/// does not grant them semantics or assert a complete baseline level.
34///
35/// EN319132-1 V1.3.1 Annex C declares SPURI as anyURI and EVERY NoticeNumbers/int
36/// as xsd:integer (not machine-sized, positive-only or xsd:int). Both structural
37/// and syntax routes use the SAME notice grammar. No normalization, parsing or
38/// narrowing of XML numbers is duplicated here, including negative/wide values.
39/// <https://forge.etsi.org/rep/esi/x19_13201_XAdES/raw/v1.3.1/1913201-XAdES01903v132.xsd>
40pub fn check_qualifier_syntax<X: ScalarXml + UriXml, W: Work>(
41    access: &Access<'_, X, W>,
42    reading: &Original<X>,
43) -> SyntaxResult<X> {
44    if reading.snapshot() != access.snapshot() {
45        return Err(Error::Access(AccessError::Changed {
46            node: reading.node(),
47        })
48        .into());
49    }
50    access
51        .query(reading.node(), |_, _, _| Ok(()))
52        .map_err(Error::Access)?;
53    let Declaration::Explicit(explicit) = reading.declaration() else {
54        return Ok(());
55    };
56    let mut index = 0;
57    while index < explicit.qualifiers.len() {
58        access
59            .execution()
60            .charge_work(1)
61            .map_err(|cause| Error::Resource {
62                node: reading.node(),
63                cause,
64            })?;
65        let qualifier = &explicit.qualifiers[index];
66        let mut child = access.first_child(qualifier.node).map_err(Error::Access)?;
67        while let Some(node) = child {
68            if named(access, node, XADES, "SPURI")? {
69                scalar::check(access, node, LexicalSource::SimpleContent, Datatype::AnyUri)
70                    .map_err(SyntaxError::Scalar)?;
71            } else if named(access, node, XADES, "SPUserNotice")? {
72                user_notice_with(access, node, |number| {
73                    scalar::check(
74                        access,
75                        number,
76                        LexicalSource::SimpleContent,
77                        Datatype::Integer,
78                    )
79                    .map_err(SyntaxError::Scalar)
80                })?;
81            } else if named(access, node, XADES_141, "SPDocSpecification")? {
82                let reading = identifier::read(access, node).map_err(SyntaxError::Structure)?;
83                identifier::check(access, &reading).map_err(SyntaxError::Identifier)?;
84            }
85            child = access
86                .next_sibling(qualifier.node, node)
87                .map_err(Error::Access)?;
88        }
89        index += 1;
90    }
91    access
92        .query(reading.node(), |_, _, _| Ok(()))
93        .map_err(Error::Access)?;
94    Ok(())
95}