Comment on attachment 37425 Initial patch for parsing digitally signed PDFs >diff --git a/poppler/Form.cc b/poppler/Form.cc >index 4df8a7d..1da9776 100644 >--- a/poppler/Form.cc >+++ b/poppler/Form.cc >@@ -1107,11 +1107,28 @@ void FormFieldChoice::_createChoicesTab () > FormFieldSignature::FormFieldSignature(XRef *xrefA, Object *dict, const Ref& ref) > : FormField(xrefA, dict, ref, formSignature) > { >+ Object v, contents; >+ >+ if (dict->dictLookup("V", &v)->isDict()) { >+ if (v.dictLookup("Contents", &contents)->isString()) { >+ this->contents = contents.getString()->copy(); >+ v.dictLookup("ByteRange", &byteRange); >+ v.dictLookup("Filter", &filter); >+ v.dictLookup("SubFilter", &subFilter); >+ } >+ contents.free(); >+ } >+ v.free(); > } > > FormFieldSignature::~FormFieldSignature() > { >- >+ if(contents) { >+ delete contents; >+} >+ byteRange.free(); >+ filter.free(); >+ subFilter.free(); > } > > //------------------------------------------------------------------------ >diff --git a/poppler/Form.h b/poppler/Form.h >index 35d66af..e5d1a1f 100644 >--- a/poppler/Form.h >+++ b/poppler/Form.h >@@ -418,6 +418,18 @@ public: > FormFieldSignature(XRef *xrefA, Object *dict, const Ref& ref); > > virtual ~FormFieldSignature(); >+ >+ Array* GetByteRange() { return byteRange.getArray(); } >+ GooString* GetContents() const { return contents; } >+ char* GetFilter() { return filter.getName(); } >+ char* GetSubFilter() { return subFilter.getName();} >+ >+protected: >+ GooString* contents; >+ Object byteRange; >+ Object filter; >+ Object subFilter; >+ > }; > > //------------------------------------------------------------------------ >diff --git a/poppler/PDFDoc.cc b/poppler/PDFDoc.cc >index ade5fe4..80b5f6c 100644 >--- a/poppler/PDFDoc.cc >+++ b/poppler/PDFDoc.cc >@@ -358,6 +358,25 @@ GBool PDFDoc::checkEncryption(GooString *ownerPassword, GooString *userPassword) > return ret; > } > >+#define SIGFLAGS_SIGNATURES_EXIST 0x1 >+#define SIGFLAGS_APPEND_ONLY 0x2 >+ >+GBool PDFDoc::isSigned() { >+ GBool ret; >+ Object sigFlags; >+ >+ getCatalog()->getAcroForm()->dictLookup("SigFlags", &sigFlags); >+ >+ if (sigFlags.isInt()) { >+ ret = sigFlags.getInt() & SIGFLAGS_SIGNATURES_EXIST; >+ } else { >+ ret = gFalse; >+ } >+ sigFlags.free(); >+ >+ return ret; >+} >+ > void PDFDoc::displayPage(OutputDev *out, int page, > double hDPI, double vDPI, int rotate, > GBool useMediaBox, GBool crop, GBool printing, >diff --git a/poppler/PDFDoc.h b/poppler/PDFDoc.h >index 6d7dea2..22fdb40 100644 >--- a/poppler/PDFDoc.h >+++ b/poppler/PDFDoc.h >@@ -176,6 +176,9 @@ public: > // Is the file encrypted? > GBool isEncrypted() { return xref->isEncrypted(); } > >+ // Is the file signed? >+ GBool isSigned(); >+ > // Check various permissions. > GBool okToPrint(GBool ignoreOwnerPW = gFalse) > { return xref->okToPrint(ignoreOwnerPW); } >diff --git a/utils/pdfinfo.cc b/utils/pdfinfo.cc >index 2abe8b4..b4b2233 100644 >--- a/utils/pdfinfo.cc >+++ b/utils/pdfinfo.cc >@@ -49,6 +49,7 @@ > #include "PDFDocEncoding.h" > #include "Error.h" > #include "DateInfo.h" >+#include "Form.h" > > static void printInfoString(Dict *infoDict, char *key, char *text, > UnicodeMap *uMap); >@@ -111,6 +112,8 @@ int main(int argc, char *argv[]) { > int exitCode; > int pg, i; > GBool multiPage; >+ Form *form; >+ FormField *formField; > > exitCode = 99; > >@@ -225,6 +228,61 @@ int main(int argc, char *argv[]) { > printf("no\n"); > } > >+ // print signature info >+ printf("Signed: "); >+ if (doc->isSigned()) { >+ printf("yes ("); >+ >+ form = doc->getCatalog()->getForm(); >+ int sigCounter = 0; >+ >+ for (int i = 0; i < form->getNumFields(); i++) { >+ formField = form->getRootField(i); >+ if (formField->getType() == formSignature) { >+ FormFieldSignature* formFieldSig >+ = static_cast (formField); >+ >+ GooString* contents = formFieldSig->GetContents(); >+ >+ if (i != 0) { >+ printf("\n "); >+ } >+ >+ printf("Signature %d: encoding:%s length:%d", >+ ++sigCounter, >+ formFieldSig->GetSubFilter(), >+ contents->getLength()); >+ >+// for (int i = 0; i < contents->getLength(); i++) { >+// printf("%x ", contents->getChar(i) & 0xff); >+// } >+// printf("\n"); >+ >+ Array *byteRange = formFieldSig->GetByteRange(); >+ >+ for (int i = 0; i < byteRange->getLength(); i+=2) { >+ Object start, length; >+ byteRange->get(i, &start); >+ byteRange->get(i+1, &length); >+ printf(" bytes: %d-%d", >+ start.getInt(), start.getInt() + length.getInt()); >+ >+ int oldPos = doc->getBaseStream()->getPos(); >+ doc->getBaseStream()->setPos(start.getInt()); >+// for (int j = 0; j < length.getInt(); j++) { >+// printf("%x ", doc->getBaseStream()->getChar() & 0xff); >+// } >+ doc->getBaseStream()->setPos(oldPos); >+ start.free(); >+ length.free(); >+ } >+ } >+ } >+ printf(")\n"); >+ } else { >+ printf("no\n"); >+ } >+ > // print page size > for (pg = firstPage; pg <= lastPage; ++pg) { > w = doc->getPageCropWidth(pg);