use std::fmt;
use crate::xml_util::{xml_escape, WriteXml};
use super::types::DigitalSignature;
const XMLDSIG_NS: &str = "http://www.w3.org/2000/09/xmldsig#";
const OPC_DIGSIG_NS: &str = "http://schemas.openxmlformats.org/package/2006/digital-signature";
pub const DIGITAL_SIGNATURE_ORIGIN_CT: &str =
"application/vnd.openxmlformats-package.digital-signature-origin";
pub const DIGITAL_SIGNATURE_XML_CT: &str =
"application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml";
pub const DIGITAL_SIGNATURE_ORIGIN_RT: &str =
"http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/origin";
pub const DIGITAL_SIGNATURE_RT: &str =
"http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/signature";
impl WriteXml for DigitalSignature {
fn write_xml<W: fmt::Write>(&self, w: &mut W) -> fmt::Result {
write!(w, r#"<Signature xmlns="{XMLDSIG_NS}" Id="idSignature">"#,)?;
write!(w, "<SignedInfo>")?;
write!(
w,
r#"<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>"#,
)?;
write!(
w,
r#"<SignatureMethod Algorithm="{}"/>"#,
self.hash_algorithm.algorithm_uri(),
)?;
write!(w, r#"<Reference URI="/ppt/presentation.xml">"#,)?;
write!(
w,
r#"<DigestMethod Algorithm="{}"/>"#,
self.hash_algorithm.algorithm_uri(),
)?;
write!(w, "<DigestValue/>")?;
write!(w, "</Reference>")?;
write!(w, "</SignedInfo>")?;
write!(w, "<SignatureValue/>")?;
write!(w, r#"<Object xmlns:mdssi="{OPC_DIGSIG_NS}">"#,)?;
write!(w, "<SignatureProperties>")?;
write!(
w,
r##"<SignatureProperty Id="idSignerName" Target="#idSignature">"##,
)?;
write!(
w,
"<mdssi:SignerName>{}</mdssi:SignerName>",
xml_escape(&self.signer.name),
)?;
write!(w, "</SignatureProperty>")?;
if let Some(ref email) = self.signer.email {
write!(
w,
r##"<SignatureProperty Id="idSignerEmail" Target="#idSignature">"##,
)?;
write!(
w,
"<mdssi:SignerEmail>{}</mdssi:SignerEmail>",
xml_escape(email),
)?;
write!(w, "</SignatureProperty>")?;
}
if let Some(ref title) = self.signer.title {
write!(
w,
r##"<SignatureProperty Id="idSignerTitle" Target="#idSignature">"##,
)?;
write!(
w,
"<mdssi:SignerTitle>{}</mdssi:SignerTitle>",
xml_escape(title),
)?;
write!(w, "</SignatureProperty>")?;
}
if let Some(ref sign_time) = self.sign_time {
write!(
w,
r##"<SignatureProperty Id="idSignTime" Target="#idSignature">"##,
)?;
write!(
w,
"<mdssi:SignatureTime><mdssi:Format>YYYY-MM-DDThh:mm:ssTZD</mdssi:Format><mdssi:Value>{}</mdssi:Value></mdssi:SignatureTime>",
xml_escape(sign_time),
)?;
write!(w, "</SignatureProperty>")?;
}
write!(
w,
r##"<SignatureProperty Id="idCommitment" Target="#idSignature">"##,
)?;
write!(
w,
r"<mdssi:CommitmentTypeIndication><mdssi:CommitmentTypeId>{}</mdssi:CommitmentTypeId></mdssi:CommitmentTypeIndication>",
self.commitment.commitment_uri(),
)?;
write!(w, "</SignatureProperty>")?;
write!(w, "</SignatureProperties>")?;
write!(w, "</Object>")?;
write!(w, "</Signature>")?;
Ok(())
}
}
pub(crate) fn signature_to_xml(sig: &DigitalSignature) -> Vec<u8> {
let mut xml = String::with_capacity(2048);
xml.push_str(r#"<?xml version="1.0" encoding="UTF-8"?>"#);
sig.write_xml(&mut xml)
.unwrap_or_else(|_| unreachable!("fmt::Write for String is infallible"));
xml.into_bytes()
}