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_json = "1"
|
||||
serde_yaml = "0.9"
|
||||
sha2 = { version = "0.10.8", featurs = ["oid"] }
|
||||
sha2 = { version = "0.10.8", features = ["oid"] }
|
||||
shell-escape = "0.1.5"
|
||||
siphasher = "1"
|
||||
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"));
|
||||
|
||||
// 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.
|
||||
let catalog_ref = alloc.bump();
|
||||
|
@ -21,6 +21,7 @@ use std::ops::{Deref, DerefMut};
|
||||
|
||||
use base64::Engine;
|
||||
use pdf_writer::{Chunk, Pdf, Ref};
|
||||
use signature::alloc_signature_annotation;
|
||||
use typst::foundations::{Datetime, Smart};
|
||||
use typst::layout::{Abs, Em, PageRanges, Transform};
|
||||
use typst::model::Document;
|
||||
@ -79,6 +80,7 @@ pub fn pdf(
|
||||
resources: builder.run(alloc_resources_refs),
|
||||
})
|
||||
.phase(|builder| References {
|
||||
signature_annotation: builder.run(alloc_signature_annotation),
|
||||
named_destinations: builder.run(write_named_destinations),
|
||||
fonts: builder.run(write_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.
|
||||
struct References {
|
||||
/// Reference for the digital signature annotation
|
||||
signature_annotation: Ref,
|
||||
/// List of named destinations, each with an ID.
|
||||
named_destinations: NamedDestinations,
|
||||
/// The IDs of written fonts.
|
||||
|
@ -112,7 +112,8 @@ fn write_page(
|
||||
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 {
|
||||
let id = chunk.alloc();
|
||||
annotations.push(id);
|
||||
|
@ -25,26 +25,54 @@ use cms::{
|
||||
},
|
||||
};
|
||||
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 sha2::Sha512;
|
||||
|
||||
use crate::{PdfChunk, WithGlobalRefs};
|
||||
|
||||
const SIG_SIZE: usize = 1024 * 4;
|
||||
|
||||
pub fn prepare(alloc: &mut Ref, pdf: &mut Pdf) -> (Range<usize>, Ref) {
|
||||
let form_ref = alloc.bump();
|
||||
let signature_field_ref = alloc.bump();
|
||||
pub fn alloc_signature_annotation(_: &WithGlobalRefs) -> (PdfChunk, Ref) {
|
||||
let mut chunk = PdfChunk::new();
|
||||
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"Subtype"), Name(b"Widget"));
|
||||
signature_field.pair(Name(b"FieldType"), Name(b"Sig"));
|
||||
signature_field.insert(Name(b"Rect")).array().items([0, 0, 0, 0]);
|
||||
signature_field.pair(Name(b"FT"), Name(b"Sig"));
|
||||
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();
|
||||
signature_dict.pair(Name(b"Type"), Name(b"Sig"));
|
||||
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"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];
|
||||
placeholder[0] = 255; // Make sure pdf-writer writes this array as binary
|
||||
let sig_end = signature_dict
|
||||
@ -58,12 +86,25 @@ pub fn prepare(alloc: &mut Ref, pdf: &mut Pdf) -> (Range<usize>, Ref) {
|
||||
.array()
|
||||
.items([0, sig_start as i32, sig_end as i32])
|
||||
.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_field.finish();
|
||||
|
||||
let mut form: Form = pdf.indirect(form_ref).start();
|
||||
form.fields([signature_field_ref]);
|
||||
form.sig_flags(SigFlags::SIGNATURES_EXIST);
|
||||
form.fields([signature_annotation_ref]);
|
||||
form.sig_flags(SigFlags::SIGNATURES_EXIST | SigFlags::APPEND_ONLY);
|
||||
|
||||
(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());
|
||||
dbg!(&range, &doc_size_range);
|
||||
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()));
|
||||
bytes.splice(
|
||||
doc_size_range.start + range.end..doc_size_range.end + range.end,
|
||||
|
Loading…
x
Reference in New Issue
Block a user