Return errors rather than mangle documents
This commit is contained in:
parent
486cafa6b4
commit
1224d9be47
2
LICENSE
2
LICENSE
|
@ -1,4 +1,4 @@
|
|||
Copyright (c) 2017, Přemysl Eric Janouch <p@janouch.name>
|
||||
Copyright (c) 2017 - 2020, Přemysl Eric Janouch <p@janouch.name>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted.
|
||||
|
|
|
@ -5,8 +5,8 @@ pdf-simple-sign
|
|||
'pdf-simple-sign' is a simple PDF signer intended for documents produced by
|
||||
the Cairo library. As such, it currently comes with some restrictions:
|
||||
|
||||
* the document may not have any forms or signatures already, as they will be
|
||||
overwitten
|
||||
* the document may not have any forms or signatures already, as they would be
|
||||
overwritten
|
||||
* the document may not employ cross-reference streams, or must constitute
|
||||
a hybrid-reference file at least
|
||||
* the document may not be newer than PDF 1.6 already, or it will get downgraded
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
//
|
||||
// pdf-simple-sign: simple PDF signer
|
||||
//
|
||||
// Copyright (c) 2017, Přemysl Eric Janouch <p@janouch.name>
|
||||
// Copyright (c) 2017 - 2020, Přemysl Eric Janouch <p@janouch.name>
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted.
|
||||
|
@ -869,15 +869,21 @@ static std::string pdf_sign(std::string& document) {
|
|||
if (page.type != pdf_object::DICT)
|
||||
return "invalid or unsupported page tree";
|
||||
|
||||
// XXX assuming this won't be an indirectly referenced array
|
||||
auto& annots = page.dict["Annots"];
|
||||
if (annots.type != pdf_object::ARRAY)
|
||||
if (annots.type != pdf_object::ARRAY) {
|
||||
// TODO indirectly referenced arrays might not be that hard to support
|
||||
if (annots.type != pdf_object::END)
|
||||
return "unexpected Annots";
|
||||
|
||||
annots = {pdf_object::ARRAY};
|
||||
}
|
||||
annots.array.emplace_back(pdf_object::REFERENCE, sigfield_n, 0);
|
||||
pdf.update(page.n, [&]{ pdf.document += pdf_serialize(page); });
|
||||
|
||||
// 8.6.1 Interactive Form Dictionary
|
||||
// XXX assuming there are no forms already, overwriting everything
|
||||
if (root.dict.count("AcroForm"))
|
||||
return "the document already contains forms, they would be overwritten";
|
||||
|
||||
root.dict["AcroForm"] = {std::map<std::string, pdf_object>{
|
||||
{"Fields", {std::vector<pdf_object>{
|
||||
{pdf_object::REFERENCE, sigfield_n, 0}
|
||||
|
@ -887,7 +893,7 @@ static std::string pdf_sign(std::string& document) {
|
|||
|
||||
// Upgrade the document version for SHA-256 etc.
|
||||
// XXX assuming that it's not newer than 1.6 already -- while Cairo can't currently use a newer
|
||||
// version that 1.5, it's not a bad idea to use cairo_pdf_surface_restrict_to_version()
|
||||
// version than 1.5, it's not a bad idea to use cairo_pdf_surface_restrict_to_version()
|
||||
root.dict["Version"] = {pdf_object::NAME, "1.6"};
|
||||
pdf.update(root_ref->second.n, [&]{ pdf.document += pdf_serialize(root); });
|
||||
pdf.flush_updates();
|
||||
|
|
15
pdf/pdf.go
15
pdf/pdf.go
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// Copyright (c) 2018, Přemysl Eric Janouch <p@janouch.name>
|
||||
// Copyright (c) 2018 - 2020, Přemysl Eric Janouch <p@janouch.name>
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted.
|
||||
|
@ -32,6 +32,7 @@ import (
|
|||
"crypto/ecdsa"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
|
||||
"go.mozilla.org/pkcs7"
|
||||
"golang.org/x/crypto/pkcs12"
|
||||
)
|
||||
|
@ -1166,9 +1167,13 @@ func Sign(document []byte,
|
|||
return nil, errors.New("invalid or unsupported page tree")
|
||||
}
|
||||
|
||||
// XXX: Assuming this won't be an indirectly referenced array.
|
||||
annots := page.Dict["Annots"]
|
||||
if annots.Kind != Array {
|
||||
// TODO(p): Indirectly referenced arrays might not be
|
||||
// that hard to support.
|
||||
if annots.Kind != End {
|
||||
return nil, errors.New("unexpected Annots")
|
||||
}
|
||||
annots = NewArray(nil)
|
||||
}
|
||||
annots.Array = append(annots.Array, NewReference(sigfieldN, 0))
|
||||
|
@ -1179,7 +1184,11 @@ func Sign(document []byte,
|
|||
})
|
||||
|
||||
// 8.6.1 Interactive Form Dictionary
|
||||
// XXX: Assuming there are no forms already, overwriting everything.
|
||||
if _, ok := root.Dict["AcroForm"]; ok {
|
||||
return nil, errors.New("the document already contains forms, " +
|
||||
"they would be overwritten")
|
||||
}
|
||||
|
||||
root.Dict["AcroForm"] = NewDict(map[string]Object{
|
||||
"Fields": NewArray([]Object{NewReference(sigfieldN, 0)}),
|
||||
"SigFlags": NewNumeric(3 /* SignaturesExist | AppendOnly */),
|
||||
|
|
Loading…
Reference in New Issue