poppler/Annot.cc | 2 - poppler/Annot.h | 2 - poppler/PDFDoc.cc | 71 +++++++++++++++++++++++++++++++++++++++ poppler/PDFDoc.h | 3 + qt5/src/poppler-pdf-converter.cc | 70 +------------------------------------- qt6/src/poppler-pdf-converter.cc | 70 +------------------------------------- 6 files changed, 82 insertions(+), 136 deletions(-)
New commits: commit 5960933f6e22df200e4d6bc6edb799e38b06df42 Author: Albert Astals Cid <[email protected]> Date: Wed Sep 15 17:55:41 2021 +0200 Move the code to sign a document from the qt frontend to PDFDoc diff --git a/poppler/Annot.cc b/poppler/Annot.cc index dfa42596..f31e1533 100644 --- a/poppler/Annot.cc +++ b/poppler/Annot.cc @@ -792,7 +792,7 @@ Object AnnotColor::writeToObject(XRef *xref) const // DefaultAppearance //------------------------------------------------------------------------ -DefaultAppearance::DefaultAppearance(Object &&fontNameA, double fontPtSizeA, std::unique_ptr<AnnotColor> fontColorA) : fontName(std::move(fontNameA)), fontPtSize(fontPtSizeA), fontColor(std::move(fontColorA)) { } +DefaultAppearance::DefaultAppearance(Object &&fontNameA, double fontPtSizeA, std::unique_ptr<AnnotColor> &&fontColorA) : fontName(std::move(fontNameA)), fontPtSize(fontPtSizeA), fontColor(std::move(fontColorA)) { } DefaultAppearance::DefaultAppearance(const GooString *da) { diff --git a/poppler/Annot.h b/poppler/Annot.h index eedf9f79..745618db 100644 --- a/poppler/Annot.h +++ b/poppler/Annot.h @@ -377,7 +377,7 @@ private: class POPPLER_PRIVATE_EXPORT DefaultAppearance { public: - DefaultAppearance(Object &&fontNameA, double fontPtSizeA, std::unique_ptr<AnnotColor> fontColorA); + DefaultAppearance(Object &&fontNameA, double fontPtSizeA, std::unique_ptr<AnnotColor> &&fontColorA); explicit DefaultAppearance(const GooString *da); void setFontName(Object &&fontNameA); const Object &getFontName() const { return fontName; } diff --git a/poppler/PDFDoc.cc b/poppler/PDFDoc.cc index bd4dcde8..d7288bce 100644 --- a/poppler/PDFDoc.cc +++ b/poppler/PDFDoc.cc @@ -2119,3 +2119,74 @@ bool PDFDoc::hasJavascript() jsInfo.scanJS(getNumPages(), true); return jsInfo.containsJS(); } + +bool PDFDoc::sign(const char *saveFilename, const char *certNickname, const char *password, GooString *partialFieldName, int page, const PDFRectangle &rect, const GooString &signatureText, const GooString &signatureTextLeft, + double fontSize, std::unique_ptr<AnnotColor> &&fontColor, double borderWidth, std::unique_ptr<AnnotColor> &&borderColor, std::unique_ptr<AnnotColor> &&backgroundColor) +{ + ::Page *destPage = getPage(page + 1); + + const DefaultAppearance da { { objName, "SigFont" }, fontSize, std::move(fontColor) }; + + Object annotObj = Object(new Dict(getXRef())); + annotObj.dictSet("Type", Object(objName, "Annot")); + annotObj.dictSet("Subtype", Object(objName, "Widget")); + annotObj.dictSet("FT", Object(objName, "Sig")); + annotObj.dictSet("T", Object(partialFieldName)); + Array *rectArray = new Array(getXRef()); + rectArray->add(Object(rect.x1)); + rectArray->add(Object(rect.y1)); + rectArray->add(Object(rect.x2)); + rectArray->add(Object(rect.y2)); + annotObj.dictSet("Rect", Object(rectArray)); + + GooString *daStr = da.toAppearanceString(); + annotObj.dictSet("DA", Object(daStr)); + + const Ref ref = getXRef()->addIndirectObject(&annotObj); + catalog->addFormToAcroForm(ref); + + std::unique_ptr<::FormFieldSignature> field = std::make_unique<::FormFieldSignature>(this, Object(annotObj.getDict()), ref, nullptr, nullptr); + + field->setCustomAppearanceContent(signatureText); + field->setCustomAppearanceLeftContent(signatureTextLeft); + + Object refObj(ref); + AnnotWidget *signatureAnnot = new AnnotWidget(this, &annotObj, &refObj, field.get()); + signatureAnnot->setFlags(signatureAnnot->getFlags() | Annot::flagPrint | Annot::flagLocked | Annot::flagNoRotate); + Dict dummy(getXRef()); + auto appearCharacs = std::make_unique<AnnotAppearanceCharacs>(&dummy); + appearCharacs->setBorderColor(std::move(borderColor)); + appearCharacs->setBackColor(std::move(backgroundColor)); + signatureAnnot->setAppearCharacs(std::move(appearCharacs)); + + signatureAnnot->generateFieldAppearance(); + signatureAnnot->updateAppearanceStream(); + + FormWidget *formWidget = field->getWidget(field->getNumWidgets() - 1); + formWidget->setWidgetAnnotation(signatureAnnot); + + destPage->addAnnot(signatureAnnot); + + std::unique_ptr<AnnotBorder> border(new AnnotBorderArray()); + border->setWidth(borderWidth); + signatureAnnot->setBorder(std::move(border)); + + FormWidgetSignature *fws = dynamic_cast<FormWidgetSignature *>(formWidget); + if (fws) { + const bool res = fws->signDocument(saveFilename, certNickname, "SHA256", password); + + // Now remove the signature stuff in case the user wants to continue editing stuff + // So the document object is clean + const Object &vRefObj = annotObj.dictLookupNF("V"); + if (vRefObj.isRef()) { + getXRef()->removeIndirectObject(vRefObj.getRef()); + } + destPage->removeAnnot(signatureAnnot); + catalog->removeFormFromAcroForm(ref); + getXRef()->removeIndirectObject(ref); + + return res; + } + + return false; +} diff --git a/poppler/PDFDoc.h b/poppler/PDFDoc.h index 9f5b0bf4..cc223eb2 100644 --- a/poppler/PDFDoc.h +++ b/poppler/PDFDoc.h @@ -329,6 +329,9 @@ public: // scans the PDF and returns whether it contains any javascript bool hasJavascript(); + bool sign(const char *saveFilename, const char *certNickname, const char *password, GooString *partialFieldName, int page, const PDFRectangle &rect, const GooString &signatureText, const GooString &signatureTextLeft, double fontSize, + std::unique_ptr<AnnotColor> &&fontColor, double borderWidth, std::unique_ptr<AnnotColor> &&borderColor, std::unique_ptr<AnnotColor> &&backgroundColor); + private: // insert referenced objects in XRef void markDictionnary(Dict *dict, XRef *xRef, XRef *countRef, unsigned int numOffset, int oldRefNum, int newRefNum, std::set<Dict *> *alreadyMarkedDicts); diff --git a/qt5/src/poppler-pdf-converter.cc b/qt5/src/poppler-pdf-converter.cc index 7e25d23e..fe7d14cc 100644 --- a/qt5/src/poppler-pdf-converter.cc +++ b/qt5/src/poppler-pdf-converter.cc @@ -129,76 +129,12 @@ bool PDFConverter::sign(const NewSignatureData &data) ::PDFDoc *doc = d->document->doc; ::Page *destPage = doc->getPage(data.page() + 1); - - const DefaultAppearance da { { objName, "SigFont" }, data.fontSize(), std::unique_ptr<AnnotColor> { convertQColor(data.fontColor()) } }; - const PDFRectangle rect = boundaryToPdfRectangle(destPage, data.boundingRectangle(), Annotation::FixedRotation); - - Object annotObj = Object(new Dict(doc->getXRef())); - annotObj.dictSet("Type", Object(objName, "Annot")); - annotObj.dictSet("Subtype", Object(objName, "Widget")); - annotObj.dictSet("FT", Object(objName, "Sig")); - annotObj.dictSet("T", Object(QStringToGooString(data.fieldPartialName()))); - Array *rectArray = new Array(doc->getXRef()); - rectArray->add(Object(rect.x1)); - rectArray->add(Object(rect.y1)); - rectArray->add(Object(rect.x2)); - rectArray->add(Object(rect.y2)); - annotObj.dictSet("Rect", Object(rectArray)); - - GooString *daStr = da.toAppearanceString(); - annotObj.dictSet("DA", Object(daStr)); - - const Ref ref = doc->getXRef()->addIndirectObject(&annotObj); - Catalog *catalog = doc->getCatalog(); - catalog->addFormToAcroForm(ref); - - std::unique_ptr<::FormFieldSignature> field = std::make_unique<::FormFieldSignature>(doc, Object(annotObj.getDict()), ref, nullptr, nullptr); - std::unique_ptr<GooString> gSignatureText = std::unique_ptr<GooString>(QStringToUnicodeGooString(data.signatureText())); - field->setCustomAppearanceContent(*gSignatureText); - std::unique_ptr<GooString> gSignatureLeftText = std::unique_ptr<GooString>(QStringToUnicodeGooString(data.signatureLeftText())); - field->setCustomAppearanceLeftContent(*gSignatureLeftText); - - Object refObj(ref); - AnnotWidget *signatureAnnot = new AnnotWidget(doc, &annotObj, &refObj, field.get()); - signatureAnnot->setFlags(signatureAnnot->getFlags() | Annot::flagPrint | Annot::flagLocked | Annot::flagNoRotate); - Dict dummy(doc->getXRef()); - auto appearCharacs = std::make_unique<AnnotAppearanceCharacs>(&dummy); - appearCharacs->setBorderColor(std::unique_ptr<AnnotColor> { convertQColor(data.borderColor()) }); - appearCharacs->setBackColor(std::unique_ptr<AnnotColor> { convertQColor(data.backgroundColor()) }); - signatureAnnot->setAppearCharacs(std::move(appearCharacs)); - - signatureAnnot->generateFieldAppearance(); - signatureAnnot->updateAppearanceStream(); - - FormWidget *formWidget = field->getWidget(field->getNumWidgets() - 1); - formWidget->setWidgetAnnotation(signatureAnnot); - - destPage->addAnnot(signatureAnnot); - - std::unique_ptr<AnnotBorder> border(new AnnotBorderArray()); - border->setWidth(data.borderWidth()); - signatureAnnot->setBorder(std::move(border)); - - FormWidgetSignature *fws = dynamic_cast<FormWidgetSignature *>(formWidget); - if (fws) { - const bool res = fws->signDocument(d->outputFileName.toUtf8().constData(), data.certNickname().toUtf8().constData(), "SHA256", data.password().toUtf8().constData()); - - // Now remove the signature stuff in case the user wants to continue editing stuff - // So the document object is clean - const Object &vRefObj = annotObj.dictLookupNF("V"); - if (vRefObj.isRef()) { - doc->getXRef()->removeIndirectObject(vRefObj.getRef()); - } - destPage->removeAnnot(signatureAnnot); - catalog->removeFormFromAcroForm(ref); - doc->getXRef()->removeIndirectObject(ref); - - return res; - } - return false; + return doc->sign(d->outputFileName.toUtf8().constData(), data.certNickname().toUtf8().constData(), data.password().toUtf8().constData(), QStringToGooString(data.fieldPartialName()), data.page(), + boundaryToPdfRectangle(destPage, data.boundingRectangle(), Annotation::FixedRotation), *gSignatureText, *gSignatureLeftText, data.fontSize(), convertQColor(data.fontColor()), data.borderWidth(), + convertQColor(data.borderColor()), convertQColor(data.backgroundColor())); } struct PDFConverter::NewSignatureData::NewSignatureDataPrivate diff --git a/qt6/src/poppler-pdf-converter.cc b/qt6/src/poppler-pdf-converter.cc index 4046fc11..8f5a19d3 100644 --- a/qt6/src/poppler-pdf-converter.cc +++ b/qt6/src/poppler-pdf-converter.cc @@ -129,76 +129,12 @@ bool PDFConverter::sign(const NewSignatureData &data) ::PDFDoc *doc = d->document->doc; ::Page *destPage = doc->getPage(data.page() + 1); - - const DefaultAppearance da { { objName, "SigFont" }, data.fontSize(), std::unique_ptr<AnnotColor> { convertQColor(data.fontColor()) } }; - const PDFRectangle rect = boundaryToPdfRectangle(destPage, data.boundingRectangle(), Annotation::FixedRotation); - - Object annotObj = Object(new Dict(doc->getXRef())); - annotObj.dictSet("Type", Object(objName, "Annot")); - annotObj.dictSet("Subtype", Object(objName, "Widget")); - annotObj.dictSet("FT", Object(objName, "Sig")); - annotObj.dictSet("T", Object(QStringToGooString(data.fieldPartialName()))); - Array *rectArray = new Array(doc->getXRef()); - rectArray->add(Object(rect.x1)); - rectArray->add(Object(rect.y1)); - rectArray->add(Object(rect.x2)); - rectArray->add(Object(rect.y2)); - annotObj.dictSet("Rect", Object(rectArray)); - - GooString *daStr = da.toAppearanceString(); - annotObj.dictSet("DA", Object(daStr)); - - const Ref ref = doc->getXRef()->addIndirectObject(&annotObj); - Catalog *catalog = doc->getCatalog(); - catalog->addFormToAcroForm(ref); - - std::unique_ptr<::FormFieldSignature> field = std::make_unique<::FormFieldSignature>(doc, Object(annotObj.getDict()), ref, nullptr, nullptr); - std::unique_ptr<GooString> gSignatureText = std::unique_ptr<GooString>(QStringToUnicodeGooString(data.signatureText())); - field->setCustomAppearanceContent(*gSignatureText); - std::unique_ptr<GooString> gSignatureLeftText = std::unique_ptr<GooString>(QStringToUnicodeGooString(data.signatureLeftText())); - field->setCustomAppearanceLeftContent(*gSignatureLeftText); - - Object refObj(ref); - AnnotWidget *signatureAnnot = new AnnotWidget(doc, &annotObj, &refObj, field.get()); - signatureAnnot->setFlags(signatureAnnot->getFlags() | Annot::flagPrint | Annot::flagLocked | Annot::flagNoRotate); - Dict dummy(doc->getXRef()); - auto appearCharacs = std::make_unique<AnnotAppearanceCharacs>(&dummy); - appearCharacs->setBorderColor(std::unique_ptr<AnnotColor> { convertQColor(data.borderColor()) }); - appearCharacs->setBackColor(std::unique_ptr<AnnotColor> { convertQColor(data.backgroundColor()) }); - signatureAnnot->setAppearCharacs(std::move(appearCharacs)); - - signatureAnnot->generateFieldAppearance(); - signatureAnnot->updateAppearanceStream(); - - FormWidget *formWidget = field->getWidget(field->getNumWidgets() - 1); - formWidget->setWidgetAnnotation(signatureAnnot); - - destPage->addAnnot(signatureAnnot); - - std::unique_ptr<AnnotBorder> border(new AnnotBorderArray()); - border->setWidth(data.borderWidth()); - signatureAnnot->setBorder(std::move(border)); - - FormWidgetSignature *fws = dynamic_cast<FormWidgetSignature *>(formWidget); - if (fws) { - const bool res = fws->signDocument(d->outputFileName.toUtf8().constData(), data.certNickname().toUtf8().constData(), "SHA256", data.password().toUtf8().constData()); - - // Now remove the signature stuff in case the user wants to continue editing stuff - // So the document object is clean - const Object &vRefObj = annotObj.dictLookupNF("V"); - if (vRefObj.isRef()) { - doc->getXRef()->removeIndirectObject(vRefObj.getRef()); - } - destPage->removeAnnot(signatureAnnot); - catalog->removeFormFromAcroForm(ref); - doc->getXRef()->removeIndirectObject(ref); - - return res; - } - return false; + return doc->sign(d->outputFileName.toUtf8().constData(), data.certNickname().toUtf8().constData(), data.password().toUtf8().constData(), QStringToGooString(data.fieldPartialName()), data.page(), + boundaryToPdfRectangle(destPage, data.boundingRectangle(), Annotation::FixedRotation), *gSignatureText, *gSignatureLeftText, data.fontSize(), convertQColor(data.fontColor()), data.borderWidth(), + convertQColor(data.borderColor()), convertQColor(data.backgroundColor())); } struct PDFConverter::NewSignatureData::NewSignatureDataPrivate
