mirror of
https://github.com/typst/typst
synced 2025-05-19 03:25:27 +08:00
More stuff
Still not working :(
This commit is contained in:
parent
afc8c2c11a
commit
a471807e2e
@ -99,7 +99,7 @@ semver = "1"
|
|||||||
serde = { version = "1.0.184", features = ["derive"] }
|
serde = { version = "1.0.184", features = ["derive"] }
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
serde_yaml = "0.9"
|
serde_yaml = "0.9"
|
||||||
sha2 = { version = "0.10.8", featurs = ["oid"] }
|
sha2 = { version = "0.10.8", features = ["oid"] }
|
||||||
shell-escape = "0.1.5"
|
shell-escape = "0.1.5"
|
||||||
siphasher = "1"
|
siphasher = "1"
|
||||||
smallvec = { version = "1.11.1", features = ["union", "const_generics", "const_new"] }
|
smallvec = { version = "1.11.1", features = ["union", "const_generics", "const_new"] }
|
||||||
|
@ -133,7 +133,17 @@ pub fn write_catalog(
|
|||||||
.pair(Name(b"Subtype"), Name(b"XML"));
|
.pair(Name(b"Subtype"), Name(b"XML"));
|
||||||
|
|
||||||
// Prepare digital signatures
|
// Prepare digital signatures
|
||||||
let (signature_range, signature_form_ref) = signature::prepare(alloc, &mut pdf);
|
let (signature_range, signature_form_ref) = signature::prepare(
|
||||||
|
alloc,
|
||||||
|
&mut pdf,
|
||||||
|
ctx.references.signature_annotation,
|
||||||
|
ctx.globals
|
||||||
|
.pages
|
||||||
|
.iter()
|
||||||
|
.filter_map(|p| *p)
|
||||||
|
.last()
|
||||||
|
.expect("Can't sign a doc with no pages"),
|
||||||
|
);
|
||||||
|
|
||||||
// Write the document catalog.
|
// Write the document catalog.
|
||||||
let catalog_ref = alloc.bump();
|
let catalog_ref = alloc.bump();
|
||||||
|
@ -21,6 +21,7 @@ use std::ops::{Deref, DerefMut};
|
|||||||
|
|
||||||
use base64::Engine;
|
use base64::Engine;
|
||||||
use pdf_writer::{Chunk, Pdf, Ref};
|
use pdf_writer::{Chunk, Pdf, Ref};
|
||||||
|
use signature::alloc_signature_annotation;
|
||||||
use typst::foundations::{Datetime, Smart};
|
use typst::foundations::{Datetime, Smart};
|
||||||
use typst::layout::{Abs, Em, PageRanges, Transform};
|
use typst::layout::{Abs, Em, PageRanges, Transform};
|
||||||
use typst::model::Document;
|
use typst::model::Document;
|
||||||
@ -79,6 +80,7 @@ pub fn pdf(
|
|||||||
resources: builder.run(alloc_resources_refs),
|
resources: builder.run(alloc_resources_refs),
|
||||||
})
|
})
|
||||||
.phase(|builder| References {
|
.phase(|builder| References {
|
||||||
|
signature_annotation: builder.run(alloc_signature_annotation),
|
||||||
named_destinations: builder.run(write_named_destinations),
|
named_destinations: builder.run(write_named_destinations),
|
||||||
fonts: builder.run(write_fonts),
|
fonts: builder.run(write_fonts),
|
||||||
color_fonts: builder.run(write_color_fonts),
|
color_fonts: builder.run(write_color_fonts),
|
||||||
@ -207,6 +209,8 @@ impl<'a> From<(WithResources<'a>, GlobalRefs)> for WithGlobalRefs<'a> {
|
|||||||
|
|
||||||
/// The references that have been assigned to each object.
|
/// The references that have been assigned to each object.
|
||||||
struct References {
|
struct References {
|
||||||
|
/// Reference for the digital signature annotation
|
||||||
|
signature_annotation: Ref,
|
||||||
/// List of named destinations, each with an ID.
|
/// List of named destinations, each with an ID.
|
||||||
named_destinations: NamedDestinations,
|
named_destinations: NamedDestinations,
|
||||||
/// The IDs of written fonts.
|
/// The IDs of written fonts.
|
||||||
|
@ -112,7 +112,8 @@ fn write_page(
|
|||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut annotations = Vec::with_capacity(page.content.links.len());
|
let mut annotations = Vec::with_capacity(page.content.links.len() + 1);
|
||||||
|
annotations.push(ctx.references.signature_annotation);
|
||||||
for (dest, rect) in &page.content.links {
|
for (dest, rect) in &page.content.links {
|
||||||
let id = chunk.alloc();
|
let id = chunk.alloc();
|
||||||
annotations.push(id);
|
annotations.push(id);
|
||||||
|
@ -25,26 +25,54 @@ use cms::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
use pdf_writer::{
|
use pdf_writer::{
|
||||||
types::SigFlags, writers::Form, Finish, Name, Pdf, Primitive, Ref, Str,
|
types::SigFlags, writers::Form, Date, Finish, Name, Pdf, Primitive, Ref, Str,
|
||||||
};
|
};
|
||||||
use rsa::{traits::SignatureScheme, Pkcs1v15Sign, RsaPrivateKey};
|
use rsa::{traits::SignatureScheme, Pkcs1v15Sign, RsaPrivateKey};
|
||||||
use sha2::Sha512;
|
use sha2::Sha512;
|
||||||
|
|
||||||
|
use crate::{PdfChunk, WithGlobalRefs};
|
||||||
|
|
||||||
const SIG_SIZE: usize = 1024 * 4;
|
const SIG_SIZE: usize = 1024 * 4;
|
||||||
|
|
||||||
pub fn prepare(alloc: &mut Ref, pdf: &mut Pdf) -> (Range<usize>, Ref) {
|
pub fn alloc_signature_annotation(_: &WithGlobalRefs) -> (PdfChunk, Ref) {
|
||||||
let form_ref = alloc.bump();
|
let mut chunk = PdfChunk::new();
|
||||||
let signature_field_ref = alloc.bump();
|
let r = chunk.alloc();
|
||||||
|
(chunk, r)
|
||||||
|
}
|
||||||
|
|
||||||
let mut signature_field = pdf.indirect(signature_field_ref).dict();
|
pub fn prepare(
|
||||||
|
alloc: &mut Ref,
|
||||||
|
pdf: &mut Pdf,
|
||||||
|
signature_annotation_ref: Ref,
|
||||||
|
last_page_ref: Ref,
|
||||||
|
) -> (Range<usize>, Ref) {
|
||||||
|
let form_ref = alloc.bump();
|
||||||
|
let field_lock_ref = alloc.bump();
|
||||||
|
|
||||||
|
let mut lock = pdf.indirect(field_lock_ref).dict();
|
||||||
|
lock.pair(Name(b"Type"), Name(b"SigFieldLock"));
|
||||||
|
lock.pair(Name(b"Action"), Name(b"All"));
|
||||||
|
lock.finish();
|
||||||
|
|
||||||
|
let mut signature_field = pdf.indirect(signature_annotation_ref).dict();
|
||||||
signature_field.pair(Name(b"Type"), Name(b"Annot"));
|
signature_field.pair(Name(b"Type"), Name(b"Annot"));
|
||||||
signature_field.pair(Name(b"Subtype"), Name(b"Widget"));
|
signature_field.pair(Name(b"Subtype"), Name(b"Widget"));
|
||||||
signature_field.pair(Name(b"FieldType"), Name(b"Sig"));
|
signature_field.pair(Name(b"FT"), Name(b"Sig"));
|
||||||
signature_field.insert(Name(b"Rect")).array().items([0, 0, 0, 0]);
|
signature_field.pair(Name(b"F"), 132);
|
||||||
|
signature_field.pair(Name(b"T"), Str(b"Signature"));
|
||||||
|
signature_field.pair(Name(b"P"), last_page_ref);
|
||||||
|
signature_field.pair(Name(b"Lock"), field_lock_ref);
|
||||||
|
signature_field
|
||||||
|
.insert(Name(b"Rect"))
|
||||||
|
.array()
|
||||||
|
.items([0.0, 0.0, 0.0, 0.0]);
|
||||||
let mut signature_dict = signature_field.insert(Name(b"V")).dict();
|
let mut signature_dict = signature_field.insert(Name(b"V")).dict();
|
||||||
signature_dict.pair(Name(b"Type"), Name(b"Sig"));
|
signature_dict.pair(Name(b"Type"), Name(b"Sig"));
|
||||||
signature_dict.pair(Name(b"Filter"), Name(b"Adobe.PPKLite"));
|
signature_dict.pair(Name(b"Filter"), Name(b"Adobe.PPKLite"));
|
||||||
signature_dict.pair(Name(b"SubFilter"), Name(b"adbe.pkcs7.detached"));
|
signature_dict.pair(Name(b"SubFilter"), Name(b"adbe.pkcs7.detached"));
|
||||||
|
signature_dict.pair(Name(b"Name"), Str(b"Ana Gelez"));
|
||||||
|
signature_dict
|
||||||
|
.pair(Name(b"M"), Date::new(2024).month(08).day(12).hour(15).minute(55));
|
||||||
let mut placeholder = [0; SIG_SIZE];
|
let mut placeholder = [0; SIG_SIZE];
|
||||||
placeholder[0] = 255; // Make sure pdf-writer writes this array as binary
|
placeholder[0] = 255; // Make sure pdf-writer writes this array as binary
|
||||||
let sig_end = signature_dict
|
let sig_end = signature_dict
|
||||||
@ -58,12 +86,25 @@ pub fn prepare(alloc: &mut Ref, pdf: &mut Pdf) -> (Range<usize>, Ref) {
|
|||||||
.array()
|
.array()
|
||||||
.items([0, sig_start as i32, sig_end as i32])
|
.items([0, sig_start as i32, sig_end as i32])
|
||||||
.item(Str(b"typst-document-size"));
|
.item(Str(b"typst-document-size"));
|
||||||
|
|
||||||
|
let mut sig_refs = signature_dict.insert(Name(b"Reference")).array();
|
||||||
|
let mut sig_ref = sig_refs.push().dict();
|
||||||
|
sig_ref.pair(Name(b"Type"), Name(b"SigRef"));
|
||||||
|
sig_ref.pair(Name(b"TransformMethod"), Name(b"DocMDP"));
|
||||||
|
let mut params = sig_ref.insert(Name(b"TransformParams")).dict();
|
||||||
|
params.pair(Name(b"Type"), Name(b"TransformParams"));
|
||||||
|
params.pair(Name(b"P"), 1);
|
||||||
|
params.finish();
|
||||||
|
sig_ref.pair(Name(b"DigestMethod"), Name(b"SHA1"));
|
||||||
|
sig_ref.finish();
|
||||||
|
sig_refs.finish();
|
||||||
|
|
||||||
signature_dict.finish();
|
signature_dict.finish();
|
||||||
signature_field.finish();
|
signature_field.finish();
|
||||||
|
|
||||||
let mut form: Form = pdf.indirect(form_ref).start();
|
let mut form: Form = pdf.indirect(form_ref).start();
|
||||||
form.fields([signature_field_ref]);
|
form.fields([signature_annotation_ref]);
|
||||||
form.sig_flags(SigFlags::SIGNATURES_EXIST);
|
form.sig_flags(SigFlags::SIGNATURES_EXIST | SigFlags::APPEND_ONLY);
|
||||||
|
|
||||||
(sig_start..sig_end, form_ref)
|
(sig_start..sig_end, form_ref)
|
||||||
}
|
}
|
||||||
@ -77,7 +118,10 @@ pub fn write(range: Range<usize>, mut bytes: Vec<u8>) -> Vec<u8> {
|
|||||||
let doc_size_range = doc_size_start..(doc_size_start + needle.len());
|
let doc_size_range = doc_size_start..(doc_size_start + needle.len());
|
||||||
dbg!(&range, &doc_size_range);
|
dbg!(&range, &doc_size_range);
|
||||||
let mut actual_size = Vec::new();
|
let mut actual_size = Vec::new();
|
||||||
<i32 as pdf_writer::Primitive>::write(bytes.len() as i32, &mut actual_size);
|
<i32 as pdf_writer::Primitive>::write(
|
||||||
|
(bytes.len() - range.end) as i32,
|
||||||
|
&mut actual_size,
|
||||||
|
);
|
||||||
actual_size.extend(std::iter::repeat(b' ').take(needle.len() - actual_size.len()));
|
actual_size.extend(std::iter::repeat(b' ').take(needle.len() - actual_size.len()));
|
||||||
bytes.splice(
|
bytes.splice(
|
||||||
doc_size_range.start + range.end..doc_size_range.end + range.end,
|
doc_size_range.start + range.end..doc_size_range.end + range.end,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user