Re: [Podofo-users] Incrementally sign PDF
On Thu, 2016-11-17 at 09:59 +0100, zyx wrote: > I'm afraid I still miss here some important detail(s), I'm sorry. Hi, just as a follow up, after some playing with it and with help from some other folks, it's just as you said, Leonard. Unfortunately trying to parse and interpret the existing appearance streams and update them (or just create a new) with the correct value of the fields before signing, is quite out of question for me. I'm sorry. I changed podofosign to at least set AcroForm's /NeedAppearances to 'false', if it's 'true', but nothing else. I left there a TODO for anyone brave, though it won't be me for sure. For the record, it's revision 1799. As far as I can tell, this behaviour is similar to what some other libraries, which can sign PDF documents, do. Bye, zyx -- http://www.litePDF.cz i...@litepdf.cz -- Check out the vibrant tech community on one of the world's most engaging tech sites, SlashDot.org! http://sdm.link/slashdot ___ Podofo-users mailing list Podofo-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/podofo-users
Re: [Podofo-users] Incrementally sign PDF
Hi, On Wed, 2016-11-16 at 21:49 +, Leonard Rosenthol wrote: > You would need to generate appearances for ALL fields to make this > work. Oh, that's quite unfortunate. If I understand it properly, then the file generator (in this case LibreOffice) is the problem, that it was too lazy to create the streams and required the viewer to generate the streams for it. But wait, the file I attached in the previous message has the /AP entry also for the "4 0 obj", the only first text-field annotation in the file. I'm afraid I still miss here some important detail(s), I'm sorry. What I do not understand is that why the viewer doesn't use the appearance stream of the signature field as is and rather hides it (or re-generates it too, to an empty appearance?), even it is already available. And the viewer doesn't even show the signature in its signature panel in this case. Bye, zyx -- http://www.litePDF.cz i...@litepdf.cz -- ___ Podofo-users mailing list Podofo-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/podofo-users
Re: [Podofo-users] Incrementally sign PDF
The original field doesn’t have an appearance – which is why the text disappears when you remove NeedAppearance. You would need to generate appearances for ALL fields to make this work. Leonard On 11/16/16, 11:15 AM, "zyx" wrote: On Wed, 2016-11-16 at 18:49 +, Leonard Rosenthol wrote: > So the best thing here is to add appearance generation functionality > and then invoke it as part of Signing. Hi, thanks for a quick reply. The problem is that my added annotation has a /AP dictionary, with a /N key only. Neither the signature panel notices the signature though. I generated a simple file using Libreoffice and then signed it (attached). The original file has only one annotation, the new file has two, the original and the signature field. The signature is 20 0 obj. When I edit the file and remove the "/NeedAppearances true" from the updated AcroForm (overwrote with spaces), then I see what I expected to see. The original field has also "deftext" default value, which is not shown after my manual changes in the file content after open. The value is shown only when I select the field, which is sort of funny (focused- >shown, unfocused->hidden). Note that I have basically no control on the input PDF file, I only sign it and that's all. Bye, zyx P.S.: I may also note that I use pretty ancient Acrobat reader (9.5.5), though I think it doesn't matter that much, does it? -- http://www.litePDF.cz i...@litepdf.cz -- ___ Podofo-users mailing list Podofo-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/podofo-users
Re: [Podofo-users] Incrementally sign PDF
If a PDF contains annotations (be they form fields/widgets or others) and no appearance dictionary (/AP) is provided, then you use the NeedAppearances key to inform the viewer that it needs to construct them. However, in order for the viewer to create them, it has to modify the PDF by adding all the new objects. And having all these new objects, breaks the signature. It’s one of many reasons why appearances are required in all the subset standards – and is also now required in PDF 2.0 files!! So the best thing here is to add appearance generation functionality and then invoke it as part of Signing. Leonard On 11/16/16, 10:22 AM, "zyx" wrote: On Mon, 2016-09-26 at 15:32 +, Thomas Szendefi wrote: > Leonard kindly checked the generated PDF for me and found out that > the code is not adding the signatures annotation to the page. Hello, that was one of the issues, that's true. Unfortunately it wasn't the only one. I made some semi-extensive changes in the PoDoFo trunk code recently, currently ending at revision 1790, where I removed the obsolete PdfSigInc* API. There were many issues with it, as you noticed, apart of being a very single-purpose API and very hard to extend. I replaced it with something fully generic. That is: * PdfMemDocument can load existing documents for incremental updates now (the Load() methods received a new optional argument pForUpdate), and such loaded documents can be saved using a new WriteUpdate() method (instead of Write()), to save an incremental update, instead of a full file rewrite. This way the incremental signing happens in the same way as before, with all the freedom what would be included in the drawing and what not, you only call WriteUpdate() instead of Write() at the end and that's all (+ you Load() the document with bForUpdate = true, of course). * I added a tool named 'podofosign' (tools/podofosign/podofosign.cpp), which can be used to sign existing PDF files. It serves also as an example of "how the things work in PoDoFo". The signing happens better with the incremental update, specifically for the linearized documents or documents with XRef streams, because such were resaved silently in the background, which doesn't conform as an incremental update. I also checked the testrun.pdf file you sent me on 2016-09-29 with the new code and it "fails" to show the added signature annotation, despite it being properly added into the page and the AcroForm. I tracked the issue down to AcroForm's "/NeedAppearances true" key. When I remove it, then the Acrobat Reader will show the added annotation (and will claim that the document had been modified since it had been signed, the same as all the default values in the form are gone, thus the form is all empty). I'd appreciate any insight on the /NeedAppearances key with respect of the signature fields, because I didn't find anything useful in the PDF 1.7 reference/specification (the word as such is only twice in the document (excluding the Index), and its description references only 'Variable Text' fields, which is not a Sig, right?). Bye, zyx -- http://www.litePDF.cz i...@litepdf.cz -- ___ Podofo-users mailing list Podofo-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/podofo-users -- ___ Podofo-users mailing list Podofo-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/podofo-users
Re: [Podofo-users] Incrementally sign PDF
On Wed, 2016-11-16 at 18:49 +, Leonard Rosenthol wrote: > So the best thing here is to add appearance generation functionality > and then invoke it as part of Signing. Hi, thanks for a quick reply. The problem is that my added annotation has a /AP dictionary, with a /N key only. Neither the signature panel notices the signature though. I generated a simple file using Libreoffice and then signed it (attached). The original file has only one annotation, the new file has two, the original and the signature field. The signature is 20 0 obj. When I edit the file and remove the "/NeedAppearances true" from the updated AcroForm (overwrote with spaces), then I see what I expected to see. The original field has also "deftext" default value, which is not shown after my manual changes in the file content after open. The value is shown only when I select the field, which is sort of funny (focused- >shown, unfocused->hidden). Note that I have basically no control on the input PDF file, I only sign it and that's all. Bye, zyx P.S.: I may also note that I use pretty ancient Acrobat reader (9.5.5), though I think it doesn't matter that much, does it? -- http://www.litePDF.cz i...@litepdf.cz fdef.pdf Description: Adobe PDF document -- ___ Podofo-users mailing list Podofo-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/podofo-users
Re: [Podofo-users] Incrementally sign PDF
On Mon, 2016-09-26 at 15:32 +, Thomas Szendefi wrote: > Leonard kindly checked the generated PDF for me and found out that > the code is not adding the signatures annotation to the page. Hello, that was one of the issues, that's true. Unfortunately it wasn't the only one. I made some semi-extensive changes in the PoDoFo trunk code recently, currently ending at revision 1790, where I removed the obsolete PdfSigInc* API. There were many issues with it, as you noticed, apart of being a very single-purpose API and very hard to extend. I replaced it with something fully generic. That is: * PdfMemDocument can load existing documents for incremental updates now (the Load() methods received a new optional argument pForUpdate), and such loaded documents can be saved using a new WriteUpdate() method (instead of Write()), to save an incremental update, instead of a full file rewrite. This way the incremental signing happens in the same way as before, with all the freedom what would be included in the drawing and what not, you only call WriteUpdate() instead of Write() at the end and that's all (+ you Load() the document with bForUpdate = true, of course). * I added a tool named 'podofosign' (tools/podofosign/podofosign.cpp), which can be used to sign existing PDF files. It serves also as an example of "how the things work in PoDoFo". The signing happens better with the incremental update, specifically for the linearized documents or documents with XRef streams, because such were resaved silently in the background, which doesn't conform as an incremental update. I also checked the testrun.pdf file you sent me on 2016-09-29 with the new code and it "fails" to show the added signature annotation, despite it being properly added into the page and the AcroForm. I tracked the issue down to AcroForm's "/NeedAppearances true" key. When I remove it, then the Acrobat Reader will show the added annotation (and will claim that the document had been modified since it had been signed, the same as all the default values in the form are gone, thus the form is all empty). I'd appreciate any insight on the /NeedAppearances key with respect of the signature fields, because I didn't find anything useful in the PDF 1.7 reference/specification (the word as such is only twice in the document (excluding the Index), and its description references only 'Variable Text' fields, which is not a Sig, right?). Bye, zyx -- http://www.litePDF.cz i...@litepdf.cz -- ___ Podofo-users mailing list Podofo-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/podofo-users
Re: [Podofo-users] Incrementally sign PDF
On Mon, 2016-09-26 at 15:32 +, Thomas Szendefi wrote: > That works fine, but only for files not containing form fields. Hi, just a little follow up, also to let you know that I didn't forget of this. The attached is a patch, which applies on top of the svn trunk of PoDoFo (currently at revision 1785), which partially addresses the issue. It's partially, because it still fails for linearized PDF files. That part requires more thinking. Bye, zyx -- http://www.litePDF.cz i...@litepdf.czIndex: src/doc/PdfSigIncMemDocument.cpp === --- src/doc/PdfSigIncMemDocument.cpp (revision 1785) +++ src/doc/PdfSigIncMemDocument.cpp (working copy) @@ -310,15 +310,11 @@ PdfAcroForm* PdfSigIncMemDocument::GetEx if(pdfRef.IsIndirect()) { PdfObject* pOldFields = pOldAcroForm->GetObject()->GetDictionary().GetKey( PdfName("Fields") ); if(pOldFields) { - if(pOldFields->GetDataType() == ePdfDataType_Array ) { - pdfRef.SetObjectNumber(pOldAcroForm->GetObject()->Reference().ObjectNumber() - 1); - this->GetObjects().SetObjectCount(pdfRef); - PdfObject *pNewObj = this->GetObjects().CreateObject(); - m_pAcroForms = new PdfAcroForm( this, pNewObj, ePdfAcroFormDefaultAppearance_None ); - this->GetCatalog()->GetDictionary().AddKey( "AcroForm", m_pAcroForms->GetObject()->Reference() ); - } else if(pOldFields->GetDataType() == ePdfDataType_Reference ) { - m_pAcroForms = pOldAcroForm; - } + pdfRef.SetObjectNumber(pOldAcroForm->GetObject()->Reference().ObjectNumber() - 1); + this->GetObjects().SetObjectCount(pdfRef); + PdfObject *pNewObj = this->GetObjects().CreateObject(); + m_pAcroForms = new PdfAcroForm( this, pNewObj, ePdfAcroFormDefaultAppearance_None ); + this->GetCatalog()->GetDictionary().AddKey( "AcroForm", m_pAcroForms->GetObject()->Reference() ); } else { pdfRef.SetObjectNumber(pOldAcroForm->GetObject()->Reference().ObjectNumber() - 1); this->GetObjects().SetObjectCount(pdfRef); @@ -327,10 +323,12 @@ PdfAcroForm* PdfSigIncMemDocument::GetEx this->GetCatalog()->GetDictionary().AddKey( "AcroForm", m_pAcroForms->GetObject()->Reference() ); } } else { - m_pAcroForms = pOldAcroForm; + PdfObject *pNewObj = this->GetObjects().CreateObject(); + m_pAcroForms = new PdfAcroForm( this, pNewObj, ePdfAcroFormDefaultAppearance_None ); + this->GetCatalog()->GetDictionary().AddKey( "AcroForm", m_pAcroForms->GetObject()->Reference() ); } } - + return m_pAcroForms; } @@ -404,13 +402,12 @@ void PdfSigIncMemDocument::CreateAnnotat PdfAnnotation* pAnnot = new PdfAnnotation(pPage, ePdfAnnotation_Widget, m_SignRect, &this->GetObjects()); pdf_int64 flags = 132; pAnnot->GetObject()->GetDictionary().AddKey("F", PdfObject(flags)); - PdfAcroForm *pAcroForm = this->GetAcroForm(); + PdfAcroForm *pAcroForm = this->GetAcroForm(); if(pAcroForm) { - if(!pAcroForm->GetObject()->GetDictionary().HasKey(PdfName("SigFlags"))) { - pdf_int64 val = 3; - pAcroForm->GetObject()->GetDictionary().AddKey("SigFlags", PdfObject(val)); - } + pAcroForm->GetObject()->GetDictionary().RemoveKey(PdfName("SigFlags")); + pdf_int64 val = 3; + pAcroForm->GetObject()->GetDictionary().AddKey("SigFlags", PdfObject(val)); PdfSignatureField signField( pAnnot, pAcroForm, this); @@ -435,15 +432,20 @@ void PdfSigIncMemDocument::CreateAnnotat PdfPage *pPage = m_PagesRef[0]; PdfObject *pAnnot = pPage->GetOwnAnnotationsArray(false, m_Document); - if(!pAnnot) -pAnnot = pPage->GetOwnAnnotationsArray(true, m_Document); - else { + if(!pAnnot) { +pAnnot = pPage->GetOwnAnnotationsArray(true, this); + } else { if (pPage->GetObject()->GetDictionary().HasKey( "Annots" ) ) { PdfObject *pTmpObj = pPage->GetObject()->GetDictionary().GetKey( "Annots" ); if(pTmpObj->IsReference()) { PdfObject *newAnnot = new PdfObject(*pAnnot); this->GetObjects().push_back(newAnnot); pAnnot = newAnnot; + } else if (pTmpObj->IsArray()) { + pAnnot = pPage->GetOwnAnnotationsArray(true, this); + pAnnot->GetArray() = pTmpObj->GetArray(); + } else { + PODOFO_RAISE_ERROR(ePdfError_InternalLogic); } } } -- Developer Access Program for Intel Xeon Phi Processors Access to Intel Xe
Re: [Podofo-users] Incrementally sign PDF
On Mon, 2016-09-19 at 10:11 +0200, zyx wrote: > You can find the workaround attached. I hesitate to commit it to > PoDoFo sources, but maybe I'll just do it for the time being. Hi, I decided to commit that change as a temporary workaround. It's better this way than the crash. I committed it as revision 1781: http://sourceforge.net/p/podofo/code/1781 Bye, zyx -- http://www.litePDF.cz i...@litepdf.cz -- Check out the vibrant tech community on one of the world's most engaging tech sites, SlashDot.org! http://sdm.link/slashdot ___ Podofo-users mailing list Podofo-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/podofo-users
Re: [Podofo-users] Incrementally sign PDF
http://www.litePDF.cz i...@litepdf.cz -- zyx Bye, file. Thanks in advance. I have some, but they are odd, thus I'd like to have a real-life PDF would it be possible to share a test PDF with a form to sign, please? Hi, > > the annots array. > (reference) seems to be neither inside the AcroForm dictionary nor > btw if I look at the file with PoDoFoBrowser the signature On Mon, 2016-09-26 at 15:32 +, Thomas Szendefi wrote: -- ___ Podofo-users mailing list Podofo-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/podofo-users
Re: [Podofo-users] Incrementally sign PDF
Hi, here a short summary of what I did until now: - I took this code http://sourceforge.net/p/podofo/mailman/message/35312841/ - And added this http://sourceforge.net/p/podofo/mailman/message/35376704/ patch to rev. 1779 of PoDoFo That works fine, but only for files not containing form fields. Leonard kindly checked the generated PDF for me and found out that the code is not adding the signatures annotation to the page. I am not able to fix this simple sounding task by myself, if this is not too much work for you guys, could you please provide another patch? btw if I look at the file with PoDoFoBrowser the signature (reference) seems to be neither inside the AcroForm dictionary nor the annots array. Regards, Thomas -- ___ Podofo-users mailing list Podofo-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/podofo-users
Re: [Podofo-users] Incrementally sign PDF
Actually, Acrobat/Reader does a LOT MORE that to determine if a document is signed. SigFlags is just a “quick check” but we don’t rely on it. Leonard On 9/20/16, 1:46 PM, "Josef Rokos" wrote: Hi, this code tells Acrobat Reader that signature is in form: PdfAcroForm *frm = document.GetAcroForm(ePdfCreateObject, ePdfAcroFormDefaultAppearance_None); if(!frm->GetObject()->GetDictionary().HasKey(PdfName("SigFlags"))) { pdf_int64 val = 3; frm->GetObject()->GetDictionary().AddKey("SigFlags", PdfObject(val)); } Pepa On Tue, Sep 20, 2016 at 1:29 PM, zyx wrote: > On Tue, 2016-09-20 at 09:06 +, Thomas Szendefi wrote: >> Do you have any idea why the signature is not recognized by Adobe >> Reader if there are form fields inside the signed PDF? PDFs without >> any formfields are working fine now. > > Hi, > nope, nothing specific off head. Except, maybe, there is some > requirement on the PDF file to note to the AcroForm that the file is > signed, there is some /Sig attribute or something like that, and if > that one is missing, the Acrobat Reader doesn't search for signatures. > I noticed something like that a very long time ago. > > By the way, your replies break threading for some reason. > Bye, > zyx > > -- > http://www.litePDF.cz i...@litepdf.cz > > -- > ___ > Podofo-users mailing list > Podofo-users@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/podofo-users -- ___ Podofo-users mailing list Podofo-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/podofo-users -- ___ Podofo-users mailing list Podofo-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/podofo-users
Re: [Podofo-users] Incrementally sign PDF
Someone sends me a PDF that demonstrates the problem with Reader, I can investigate. Leonard On 9/20/16, 12:29 PM, "zyx" wrote: On Tue, 2016-09-20 at 09:06 +, Thomas Szendefi wrote: > Do you have any idea why the signature is not recognized by Adobe > Reader if there are form fields inside the signed PDF? PDFs without > any formfields are working fine now. Hi, nope, nothing specific off head. Except, maybe, there is some requirement on the PDF file to note to the AcroForm that the file is signed, there is some /Sig attribute or something like that, and if that one is missing, the Acrobat Reader doesn't search for signatures. I noticed something like that a very long time ago. By the way, your replies break threading for some reason. Bye, zyx -- http://www.litePDF.cz i...@litepdf.cz -- ___ Podofo-users mailing list Podofo-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/podofo-users -- ___ Podofo-users mailing list Podofo-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/podofo-users
Re: [Podofo-users] Incrementally sign PDF
Hi, this code tells Acrobat Reader that signature is in form: PdfAcroForm *frm = document.GetAcroForm(ePdfCreateObject, ePdfAcroFormDefaultAppearance_None); if(!frm->GetObject()->GetDictionary().HasKey(PdfName("SigFlags"))) { pdf_int64 val = 3; frm->GetObject()->GetDictionary().AddKey("SigFlags", PdfObject(val)); } Pepa On Tue, Sep 20, 2016 at 1:29 PM, zyx wrote: > On Tue, 2016-09-20 at 09:06 +, Thomas Szendefi wrote: >> Do you have any idea why the signature is not recognized by Adobe >> Reader if there are form fields inside the signed PDF? PDFs without >> any formfields are working fine now. > > Hi, > nope, nothing specific off head. Except, maybe, there is some > requirement on the PDF file to note to the AcroForm that the file is > signed, there is some /Sig attribute or something like that, and if > that one is missing, the Acrobat Reader doesn't search for signatures. > I noticed something like that a very long time ago. > > By the way, your replies break threading for some reason. > Bye, > zyx > > -- > http://www.litePDF.cz i...@litepdf.cz > > -- > ___ > Podofo-users mailing list > Podofo-users@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/podofo-users -- ___ Podofo-users mailing list Podofo-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/podofo-users
Re: [Podofo-users] Incrementally sign PDF
On Tue, 2016-09-20 at 09:06 +, Thomas Szendefi wrote: > Do you have any idea why the signature is not recognized by Adobe > Reader if there are form fields inside the signed PDF? PDFs without > any formfields are working fine now. Hi, nope, nothing specific off head. Except, maybe, there is some requirement on the PDF file to note to the AcroForm that the file is signed, there is some /Sig attribute or something like that, and if that one is missing, the Acrobat Reader doesn't search for signatures. I noticed something like that a very long time ago. By the way, your replies break threading for some reason. Bye, zyx -- http://www.litePDF.cz i...@litepdf.cz -- ___ Podofo-users mailing list Podofo-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/podofo-users
Re: [Podofo-users] Incrementally sign PDF
>On Thu, 2016-09-15 at 16:07 +, Thomas Szendefi wrote: >> I have that code running with 0.9.4, but it prints the following error >> message on the console for almost every PDF I try: >> PoDoFo encounter an error. Error: 5 ePdfError_UnexpectedEOF ??? >> Error Description: End of file was reached unxexpectedly. >> ??? Callstack: >> ??? #0 Error Source: /proj/sc5/src/mu/components/libs/podofo- >> 0.9.4/src/base/PdfParserObject.cpp:199 >> ??? Information: Expected variant. >> ? >> (Thrown in the very beginning inside PdfSigIncMemDocument::Write()) > > Hi, >there is some issue in the code which can lead to crash for certain PDF >files. I didn't investigate it into more deep, I only managed to write >a workaround to not cause the crash and to not throw the above exception. > >You can find the workaround attached. I hesitate to commit it to PoDoFo >sources, but maybe I'll just do it for the time being. > >As I understand the issue, the incSign document stole the page >to its content fromt he underlying memDocument, which results into >the delayed load to use wrong owner, thus fails to load. As the page >is in both documents a double-free happens when both incSign and the >memDocument are freed after the signing. > >I've even written a patch to extend the incremental signing drawing, >to be more generic, but it changes API. > >The only correct way to fix this is to write complete incremental >editing for PoDoFo, but that's quite out of my hands at the moment. >As I wrote above, maybe I'll commit both changes for the time being, >thus the PoDoFo will be usable, until someone brave will implement >the full incremental editing. > Bye, > zyx > >P.S.: with the attached patch I can sign your simple.pdf Thank you for your efforts, the patch works fine! (I applied it to the latest version in the repository, rev 1779). Do you have any idea why the signature is not recognized by Adobe Reader if there are form fields inside the signed PDF? PDFs without any formfields are working fine now. Regards, Thomas -- ___ Podofo-users mailing list Podofo-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/podofo-users
Re: [Podofo-users] Incrementally sign PDF
On Thu, 2016-09-15 at 16:07 +, Thomas Szendefi wrote: > I have that code running with 0.9.4, but it prints the following > error message on the console for almost every PDF I try: > PoDoFo encounter an error. Error: 5 ePdfError_UnexpectedEOF > Error Description: End of file was reached unxexpectedly. > Callstack: > #0 Error Source: /proj/sc5/src/mu/components/libs/podofo- > 0.9.4/src/base/PdfParserObject.cpp:199 > Information: Expected variant. > > (Thrown in the very beginning inside PdfSigIncMemDocument::Write()) Hi, there is some issue in the code which can lead to crash for certain PDF files. I didn't investigate it into more deep, I only managed to write a workaround to not cause the crash and to not throw the above exception. You can find the workaround attached. I hesitate to commit it to PoDoFo sources, but maybe I'll just do it for the time being. As I understand the issue, the incSign document stole the page to its content fromt he underlying memDocument, which results into the delayed load to use wrong owner, thus fails to load. As the page is in both documents a double-free happens when both incSign and the memDocument are freed after the signing. I've even written a patch to extend the incremental signing drawing, to be more generic, but it changes API. The only correct way to fix this is to write complete incremental editing for PoDoFo, but that's quite out of my hands at the moment. As I wrote above, maybe I'll commit both changes for the time being, thus the PoDoFo will be usable, until someone brave will implement the full incremental editing. Bye, zyx P.S.: with the attached patch I can sign your simple.pdf -- http://www.litePDF.cz i...@litepdf.czIndex: src/doc/PdfSigIncMemDocument.cpp === --- src/doc/PdfSigIncMemDocument.cpp (revision 1771) +++ src/doc/PdfSigIncMemDocument.cpp (working copy) @@ -127,6 +127,7 @@ PdfSigIncMemDocument::PdfSigIncMemDocume m_n2XObj = NULL; m_pFont = NULL; m_bLinearized = false; + m_stolenPage = NULL; } PdfSigIncMemDocument::PdfSigIncMemDocument(const char* pszInpFilename) @@ -140,6 +141,7 @@ PdfSigIncMemDocument::PdfSigIncMemDocume m_n2XObj = NULL; m_pFont = NULL; m_bLinearized = false; + m_stolenPage = NULL; m_Document->Load(pszInpFilename); } @@ -152,6 +154,11 @@ PdfSigIncMemDocument::~PdfSigIncMemDocum m_pAcroForms = NULL; } + if (m_stolenPage && m_Document && m_stolenPage->GetOwner()) { + m_stolenPage->GetOwner()->RemoveObject(m_stolenPage->Reference()); + } + m_stolenPage = NULL; + if(m_InpFilename) podofo_free( m_InpFilename ); if(m_pSignField) @@ -188,6 +195,16 @@ void PdfSigIncMemDocument::Initialize() delete m_Document; m_Document = new PdfExMemDocument(inpDvc); } + + /* Preload whole file into the memory */ + TIVecObjects it, end = m_Document->GetObjects().end(); + for (it = m_Document->GetObjects().begin(); it != end; it++) { + PdfObject *obj = *it; + + if (obj) + obj->DelayedStreamLoad(); + } + CreateVisualSignRect(); m_LastXRefOffset = m_Document->GetXRefOffset(); @@ -481,6 +498,9 @@ bool PdfSigIncMemDocument::AddPageToIncD if(!obj) { this->GetObjects().push_back(objPage); this->GetObjects().Sort(); + if (objPage->GetOwner()) { + m_stolenPage = objPage; + } } } else bResult = false; Index: src/doc/PdfSigIncMemDocument.h === --- src/doc/PdfSigIncMemDocument.h (revision 1771) +++ src/doc/PdfSigIncMemDocument.h (working copy) @@ -89,6 +89,7 @@ class PODOFO_DOC_API PdfSigIncMemDocumen PdfSigIncSignatureField *m_pSignField; bool m_bLinearized; +PdfObject *m_stolenPage; protected: void CreateAnnotation(PdfSignOutputDevice* pDevice, PdfPage* pPage); -- ___ Podofo-users mailing list Podofo-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/podofo-users
Re: [Podofo-users] Incrementally sign PDF
I have that code running with 0.9.4, but it prints the following error message on the console for almost every PDF I try: PoDoFo encounter an error. Error: 5 ePdfError_UnexpectedEOF Error Description: End of file was reached unxexpectedly. Callstack: #0 Error Source: /proj/sc5/src/mu/components/libs/podofo-0.9.4/src/base/PdfParserObject.cpp:199 Information: Expected variant. (Thrown in the very beginning inside PdfSigIncMemDocument::Write()) I have got the feeling this happens for files bigger than ~25K. I appended one very simple PDF to this post I made with Libre Office for testing purposes which doesn´t work with this code. I tried lots of different PDFs from various sources. In only two cases it generated a result for me: ->One, where Adobe Reader said the signature is OK, but the whole PDF was shown in blank white (just like being empty). ->In the other case, everything was there (even the signature on the binary base) , but adobe reader didn't even try to validate it. My question is: Does this code work for you, especially with the PDF I provide as attachment? If yes, is the result viewable in Adobe Reader (with valid signature)? Regards simple.pdf Description: simple.pdf -- ___ Podofo-users mailing list Podofo-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/podofo-users
Re: [Podofo-users] Incrementally sign PDF
On Thu, 2015-03-05 at 13:12 -0800, Danny Liberty wrote: > Does anyone have a code example of how to use this new functionality > in PoDoFo 0.9.3? Hi, I know this is very late, but maybe someone will find this useful. The code is similar to usual signing and it uses Windows Crypto API. Bye, zyx -- http://www.litePDF.cz i...@litepdf.cz#include #include #include #include #include #include #include "podofo.h" using namespace PoDoFo; // Link with the crypt32.lib file #pragma comment (lib, "crypt32.lib") using namespace PoDoFo; static double MM_TO_POINTS(double mm) { double pts = (((mm) / 25.4) * 72.0); if (pts < 0) { pts -= 1e-6; } else { pts += 1e-6; } return pts; } class MPdfSigner { private: static PdfFont * createFont (PdfDocument *document, void *user_data) { return document->CreateFont("Helvetica", FALSE, PdfEncodingFactory::GlobalWinAnsiEncodingInstance()); } void loadCertificateStore(HANDLE *hStore) { BYTE *certBytes = NULL; unsigned int certBytesLength = 0; FILE *certFile = fopen("cert.pfx", "rb"); if (!certFile) { fprintf(stderr, "Failed to open cert.pfx\n"); PODOFO_RAISE_ERROR (ePdfError_FileNotFound); } fseek(certFile, 0, SEEK_END); certBytesLength = ftell(certFile); fseek(certFile, 0, SEEK_SET); certBytes = (BYTE *) malloc(sizeof(BYTE) * certBytesLength); if (!certBytes) { fprintf(stderr, "Failed to allocate memory for cert.pfx"); PODOFO_RAISE_ERROR (ePdfError_OutOfMemory); } fread(certBytes, sizeof(BYTE), certBytesLength, certFile); fclose(certFile); HMODULE lib = LoadLibrary("crypt32.dll"); if (lib != NULL) { /* PFXData... */ typedef HCERTSTORE (WINAPI *LPPFXImportCertStore) (CRYPT_DATA_BLOB *pPFX, LPCWSTR szPassword, DWORD dwFlags); typedef BOOL (WINAPI *LPPFXIsPFXBlob)(CRYPT_DATA_BLOB *pPFX); typedef BOOL (WINAPI *LPPFXVerifyPassword)(CRYPT_DATA_BLOB *pPFX, LPCWSTR szPassword, DWORD dwFlags); #ifndef CRYPT_USER_KEYSET #define CRYPT_USER_KEYSET 0x1000 #endif LPPFXImportCertStore libPFXImportCertStore = (LPPFXImportCertStore) GetProcAddress(lib,"PFXImportCertStore"); LPPFXIsPFXBlob libPFXIsPFXBlob = (LPPFXIsPFXBlob) GetProcAddress(lib, "PFXIsPFXBlob"); LPPFXVerifyPassword libPFXVerifyPassword = (LPPFXVerifyPassword) GetProcAddress(lib,"PFXVerifyPassword"); if (libPFXImportCertStore != NULL && libPFXIsPFXBlob != NULL && libPFXVerifyPassword != NULL) { CRYPT_DATA_BLOB blob; blob.cbData = certBytesLength; blob.pbData = certBytes; if (libPFXIsPFXBlob(&blob)) { *hStore = libPFXImportCertStore(&blob, L"", 0/*|CRYPT_USER_PROTECTED|CRYPT_USER_KEYSET*/); } } FreeLibrary(lib); } free(certBytes); } char *bytes; int bytes_len; void AddData(const char *pBytes, unsigned int pBytes_len) { bytes = (char *) realloc(bytes, sizeof(char) * (bytes_len + pBytes_len)); if (!bytes) { PODOFO_RAISE_ERROR (ePdfError_OutOfMemory); } memcpy(bytes + bytes_len, pBytes, pBytes_len); bytes_len += pBytes_len; } void Finish(char *signature, unsigned int *signature_len) { HANDLE hStore = NULL; PCCERT_CONTEXT pCertContext = NULL; const BYTE* MessageArray[] = {(const BYTE *) bytes}; DWORD MessageSizeArray[1]; MessageSizeArray[0] = bytes_len; CRYPT_SIGN_MESSAGE_PARA SigParams; loadCertificateStore(&hStore); if (!hStore) { fprintf (stderr, "Failed to open temporary store\n"); PODOFO_RAISE_ERROR (ePdfError_InvalidHandle); } pCertContext = CertFindCertificateInStore(hStore, PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, NULL); if (!pCertContext) { CertCloseStore(hStore, 0); fprintf (stderr, "Failed to find certificate in the store\n"); PODOFO_RAISE_ERROR (ePdfError_InvalidHandle); } memset(&SigParams,0,sizeof(CRYPT_SIGN_MESSAGE_PARA)); SigParams.cbSize = sizeof(CRYPT_SIGN_MESSAGE_PARA); SigParams.dwMsgEncodingType = PKCS_7_ASN_ENCODING | X509_ASN_ENCODING; SigParams.pSigningCert = pCertContext; SigParams.HashAlgorithm.pszObjId = szOID_RSA_SHA1RSA; SigParams.HashAlgorithm.Parameters.pbData = NULL; SigParams.HashAlgo