From 8c60336e041dee3d476871fcc97a4acb135b1995 Mon Sep 17 00:00:00 2001 From: Jeroen Bobbeldijk Date: Sun, 17 Sep 2017 15:24:57 +0200 Subject: [PATCH] Dont parse twice in test, fix some bugs with special pdfs --- .gitignore | 2 ++ sign/helpers.go | 15 +++++++++++++-- sign/pdfcatalog.go | 12 +++++------- sign/pdfvisualsignature.go | 20 +++++++++----------- sign/pdfxref.go | 1 + sign/sign_test.go | 26 ++------------------------ 6 files changed, 32 insertions(+), 44 deletions(-) diff --git a/.gitignore b/.gitignore index 49dff43..5e7870a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ .idea testfiles/*.pdf +testfiles/*.pdf.broken +testfiles/*.pdf.tmp diff --git a/sign/helpers.go b/sign/helpers.go index 91472a2..f679e60 100644 --- a/sign/helpers.go +++ b/sign/helpers.go @@ -14,8 +14,15 @@ import ( func findFirstPage(parent pdf.Value) (pdf.Value, error) { value_type := parent.Key("Type").String() if value_type == "/Pages" { - recurse_parent, recurse_err := findFirstPage(parent.Key("Kids").Index(0)) - return recurse_parent, recurse_err + + for i := 0; i < parent.Key("Kids").Len(); i++ { + recurse_parent, recurse_err := findFirstPage(parent.Key("Kids").Index(i)) + if recurse_err == nil { + return recurse_parent, recurse_err + } + } + + return parent, errors.New("Could not find first page.") } if value_type == "/Page" { @@ -83,6 +90,10 @@ func writePartFromSourceFileToTargetFile(input_file *os.File, output_file *os.Fi // Track read/written bytes so we know when we're done. read_bytes := int64(0) + if length <= 0 { + return nil + } + // Create a buffer for the chunks. buf := make([]byte, max_chunk_length) for { diff --git a/sign/pdfcatalog.go b/sign/pdfcatalog.go index b8957b8..10f8b5b 100644 --- a/sign/pdfcatalog.go +++ b/sign/pdfcatalog.go @@ -1,7 +1,6 @@ package sign import ( - "errors" "strconv" ) @@ -20,15 +19,14 @@ func (context *SignContext) createCatalog() (catalog string, err error) { } } - if !found_pages { - return "", errors.New("Didn't find pages in PDF trailer Root.") - } - rootPtr := root.GetPtr() context.CatalogData.RootString = strconv.Itoa(int(rootPtr.GetID())) + " " + strconv.Itoa(int(rootPtr.GetGen())) + " R" - pages := root.Key("Pages").GetPtr() - catalog += " /Pages " + strconv.Itoa(int(pages.GetID())) + " " + strconv.Itoa(int(pages.GetGen())) + " R" + if found_pages { + pages := root.Key("Pages").GetPtr() + catalog += " /Pages " + strconv.Itoa(int(pages.GetID())) + " " + strconv.Itoa(int(pages.GetGen())) + " R" + } + catalog += " /AcroForm <<" catalog += " /Fields [" + strconv.Itoa(int(context.VisualSignData.ObjectId)) + " 0 R]" diff --git a/sign/pdfvisualsignature.go b/sign/pdfvisualsignature.go index bbc9007..2043120 100644 --- a/sign/pdfvisualsignature.go +++ b/sign/pdfvisualsignature.go @@ -1,7 +1,6 @@ package sign import ( - "errors" "strconv" ) @@ -21,22 +20,21 @@ func (context *SignContext) createVisualSignature() (visual_signature string, er } } - if !found_pages { - return "", errors.New("Didn't find pages in PDF trailer Root.") - } rootPtr := root.GetPtr() context.CatalogData.RootString = strconv.Itoa(int(rootPtr.GetID())) + " " + strconv.Itoa(int(rootPtr.GetGen())) + " R" - first_page, err := findFirstPage(root.Key("Pages")) - if err != nil { - return "", err + if found_pages { + first_page, err := findFirstPage(root.Key("Pages")) + if err != nil { + return "", err + } + + first_page_ptr := first_page.GetPtr() + + visual_signature += " /P " + strconv.Itoa(int(first_page_ptr.GetID())) + " " + strconv.Itoa(int(first_page_ptr.GetGen())) + " R" } - first_page_ptr := first_page.GetPtr() - - visual_signature += " /P " + strconv.Itoa(int(first_page_ptr.GetID())) + " " + strconv.Itoa(int(first_page_ptr.GetGen())) + " R" - visual_signature += " /F 132" visual_signature += " /FT /Sig" visual_signature += " /T " + pdfString("Signature") diff --git a/sign/pdfxref.go b/sign/pdfxref.go index a961023..2addc2e 100644 --- a/sign/pdfxref.go +++ b/sign/pdfxref.go @@ -27,6 +27,7 @@ func (context *SignContext) writeXref() error { } func (context *SignContext) writeXrefTable() error { + // @todo: maybe we need a prev here too. xref_size := "xref\n0 " + strconv.FormatInt(context.PDFReader.XrefInformation.ItemCount, 10) new_xref_size := "xref\n0 " + strconv.FormatInt(context.PDFReader.XrefInformation.ItemCount+4, 10) diff --git a/sign/sign_test.go b/sign/sign_test.go index 9032b34..17b4cee 100644 --- a/sign/sign_test.go +++ b/sign/sign_test.go @@ -123,30 +123,11 @@ func TestSignPDF(t *testing.T) { for _, f := range files { ext := filepath.Ext(f.Name()) if ext != ".pdf" { - fmt.Printf("Skipping file %s", f.Name()) + fmt.Printf("Skipping file %s\n", f.Name()) continue } - input_file, err := os.Open("../testfiles/" + f.Name()) - if err != nil { - t.Errorf("%s: %s", f.Name(), err.Error()) - return - } - - finfo, err := input_file.Stat() - if err != nil { - input_file.Close() - t.Errorf("%s: %s", f.Name(), err.Error()) - return - } - size := finfo.Size() - - _, err = pdf.NewReader(input_file, size) - if err != nil { - input_file.Close() - t.Errorf("%s: %s", f.Name(), err.Error()) - return - } + fmt.Printf("Signing file %s\n", f.Name()) err = SignFile("../testfiles/"+f.Name(), "../testfiles/"+f.Name()+".tmp", SignData{ Signature: SignDataSignature{ @@ -174,11 +155,8 @@ func TestSignPDF(t *testing.T) { defer os.Remove("../testfiles/"+f.Name()+".tmp") if err != nil { - input_file.Close() t.Errorf("%s: %s", f.Name(), err.Error()) return } - - input_file.Close() } }