[poppler] qt6/src
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Fri Dec 18 12:50:06 UTC 2020
qt6/src/poppler-annotation-private.h | 4
qt6/src/poppler-annotation-private.h.orig | 115 ---------------
qt6/src/poppler-annotation.cc | 18 +-
qt6/src/poppler-annotation.h | 2
qt6/src/poppler-document.cc | 2
qt6/src/poppler-form.cc | 119 +++++++++++++++-
qt6/src/poppler-form.h | 55 +++++++
qt6/src/poppler-pdf-converter.cc | 220 +++++++++++++++++++++++++++++-
qt6/src/poppler-qt6.h | 83 +++++++++++
9 files changed, 489 insertions(+), 129 deletions(-)
New commits:
commit fbc4d13d075ff30d6fccb5b81d8f3b8b19d673cb
Author: Albert Astals Cid <aacid at kde.org>
Date: Fri Dec 18 13:40:49 2020 +0100
qt6: Port the signing code from qt5
diff --git a/qt6/src/poppler-annotation-private.h b/qt6/src/poppler-annotation-private.h
index 288ab6f1..1e8b6d32 100644
--- a/qt6/src/poppler-annotation-private.h
+++ b/qt6/src/poppler-annotation-private.h
@@ -3,6 +3,7 @@
* Copyright (C) 2012, Tobias Koenig <tokoe at kdab.com>
* Copyright (C) 2012, 2013 Fabio D'Urso <fabiodurso at hotmail.it>
* Copyright (C) 2012, 2014, 2018-2020, Albert Astals Cid <aacid at kde.org>
+ * Copyright (C) 2020, Klarälvdalens Datakonsult AB, a KDAB Group company, <info at kdab.com>. Work sponsored by Technische Universität Dresden
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -37,6 +38,8 @@ class PDFRectangle;
namespace Poppler {
class DocumentData;
+PDFRectangle boundaryToPdfRectangle(::Page *pdfPage, const QRectF &r, int flags);
+
class AnnotationPrivate : public QSharedData
{
public:
@@ -87,7 +90,6 @@ public:
/* The following helpers only work if pdfPage is set */
void flushBaseAnnotationProperties();
- void fillNormalizationMTX(double MTX[6], int pageRotation) const;
void fillTransformationMTX(double MTX[6]) const;
QRectF fromPdfRectangle(const PDFRectangle &r) const;
PDFRectangle boundaryToPdfRectangle(const QRectF &r, int flags) const;
diff --git a/qt6/src/poppler-annotation-private.h.orig b/qt6/src/poppler-annotation-private.h.orig
deleted file mode 100644
index 937edad4..00000000
--- a/qt6/src/poppler-annotation-private.h.orig
+++ /dev/null
@@ -1,115 +0,0 @@
-/* poppler-annotation-private.h: qt interface to poppler
- * Copyright (C) 2007, Pino Toscano <pino at kde.org>
- * Copyright (C) 2012, Tobias Koenig <tokoe at kdab.com>
- * Copyright (C) 2012, 2013 Fabio D'Urso <fabiodurso at hotmail.it>
- * Copyright (C) 2012, 2014, 2018, Albert Astals Cid <aacid at kde.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#ifndef _POPPLER_ANNOTATION_PRIVATE_H_
-#define _POPPLER_ANNOTATION_PRIVATE_H_
-
-#include <QtCore/QLinkedList>
-#include <QtCore/QPointF>
-#include <QtCore/QSharedDataPointer>
-
-#include "poppler-annotation.h"
-
-#include <Object.h>
-
-class Annot;
-class AnnotPath;
-class Link;
-class Page;
-class PDFRectangle;
-
-namespace Poppler
-{
-class DocumentData;
-
-class AnnotationPrivate : public QSharedData
-{
- public:
- AnnotationPrivate();
- virtual ~AnnotationPrivate();
-
- AnnotationPrivate(const AnnotationPrivate &) = delete;
- AnnotationPrivate& operator=(const AnnotationPrivate &) = delete;
-
- void addRevision(Annotation *ann, Annotation::RevScope scope, Annotation::RevType type);
-
- /* Returns an Annotation of the right subclass whose d_ptr points to
- * this AnnotationPrivate */
- virtual Annotation * makeAlias() = 0;
-
- /* properties: contents related */
- QString author;
- QString contents;
- QString uniqueName;
- QDateTime modDate; // before or equal to currentDateTime()
- QDateTime creationDate; // before or equal to modifyDate
-
- /* properties: look/interaction related */
- int flags;
- QRectF boundary;
-
- /* style and popup */
- Annotation::Style style;
- Annotation::Popup popup;
-
- /* revisions */
- Annotation::RevScope revisionScope;
- Annotation::RevType revisionType;
- QList<Annotation*> revisions;
-
- /* After this call, the Annotation object will behave like a wrapper for
- * the specified Annot object. All cached values are discarded */
- void tieToNativeAnnot(Annot *ann, ::Page *page, DocumentData *doc);
-
- /* Creates a new Annot object on the specified page, flushes current
- * values to that object and ties this Annotation to that object */
- virtual Annot* createNativeAnnot(::Page *destPage, DocumentData *doc) = 0;
-
- /* Inited to 0 (i.e. untied annotation) */
- Annot *pdfAnnot;
- ::Page *pdfPage;
- DocumentData * parentDoc;
-
- /* The following helpers only work if pdfPage is set */
- void flushBaseAnnotationProperties();
- void fillNormalizationMTX(double MTX[6], int pageRotation) const;
- void fillTransformationMTX(double MTX[6]) const;
- QRectF fromPdfRectangle(const PDFRectangle &r) const;
- PDFRectangle boundaryToPdfRectangle(const QRectF &r, int flags) const;
- AnnotPath * toAnnotPath(const QLinkedList<QPointF> &l) const;
-
- /* Scan page for annotations, parentId=0 searches for root annotations, subtypes empty means all subtypes */
- static QList<Annotation*> findAnnotations(::Page *pdfPage, DocumentData *doc, const QSet<Annotation::SubType> &subtypes, int parentId = -1);
-
- /* Add given annotation to given page */
- static void addAnnotationToPage(::Page *pdfPage, DocumentData *doc, const Annotation * ann);
-
- /* Remove annotation from page and destroy ann */
- static void removeAnnotationFromPage(::Page *pdfPage, const Annotation * ann);
-
- Ref pdfObjectReference() const;
-
- Link* additionalAction( Annotation::AdditionalActionType type ) const;
-};
-
-}
-
-#endif
diff --git a/qt6/src/poppler-annotation.cc b/qt6/src/poppler-annotation.cc
index 9724e2df..609130b6 100644
--- a/qt6/src/poppler-annotation.cc
+++ b/qt6/src/poppler-annotation.cc
@@ -11,6 +11,9 @@
* Copyright (C) 2018, 2019 Tobias Deiminger <haxtibal at posteo.de>
* Copyright (C) 2018 Carlos Garcia Campos <carlosgc at gnome.org>
* Copyright (C) 2020 Oliver Sander <oliver.sander at tu-dresden.de>
+ * Copyright (C) 2020 Katarina Behrens <Katarina.Behrens at cib.de>
+ * Copyright (C) 2020 Thorsten Behrens <Thorsten.Behrens at CIB.de>
+ * Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, <info at kdab.com>. Work sponsored by Technische Universität Dresden
* Adapting code from
* Copyright (C) 2004 by Enrico Ros <eros.kde at email.it>
*
@@ -133,7 +136,7 @@ void AnnotationPrivate::flushBaseAnnotationProperties()
// Returns matrix to convert from user space coords (oriented according to the
// specified rotation) to normalized coords
-void AnnotationPrivate::fillNormalizationMTX(double MTX[6], int pageRotation) const
+void fillNormalizationMTX(::Page *pdfPage, double MTX[6], int pageRotation)
{
Q_ASSERT(pdfPage);
@@ -171,7 +174,7 @@ void AnnotationPrivate::fillTransformationMTX(double MTX[6]) const
if (pageRotate == 0 || (pdfAnnot->getFlags() & Annot::flagNoRotate) == 0) {
// Use the normalization matrix for this page's rotation
- fillNormalizationMTX(MTX, pageRotate);
+ fillNormalizationMTX(pdfPage, MTX, pageRotate);
} else {
// Clients expect coordinates relative to this page's rotation, but
// FixedRotation annotations internally use unrotated coordinates:
@@ -179,7 +182,7 @@ void AnnotationPrivate::fillTransformationMTX(double MTX[6]) const
// top-left corner as rotation pivot
double MTXnorm[6];
- fillNormalizationMTX(MTXnorm, pageRotate);
+ fillNormalizationMTX(pdfPage, MTXnorm, pageRotate);
QTransform transform(MTXnorm[0], MTXnorm[1], MTXnorm[2], MTXnorm[3], MTXnorm[4], MTXnorm[5]);
transform.translate(+pdfAnnot->getXMin(), +pdfAnnot->getYMax());
@@ -230,14 +233,14 @@ QRectF AnnotationPrivate::fromPdfRectangle(const PDFRectangle &r) const
// the transformation produced by fillTransformationMTX, but we can't use
// fillTransformationMTX here because it relies on the native annotation
// object's boundary rect to be already set up.
-PDFRectangle AnnotationPrivate::boundaryToPdfRectangle(const QRectF &r, int rFlags) const
+PDFRectangle boundaryToPdfRectangle(::Page *pdfPage, const QRectF &r, int rFlags)
{
Q_ASSERT(pdfPage);
const int pageRotate = pdfPage->getRotate();
double MTX[6];
- fillNormalizationMTX(MTX, pageRotate);
+ fillNormalizationMTX(pdfPage, MTX, pageRotate);
double tl_x, tl_y, br_x, br_y, swp;
XPDFReader::invTransform(MTX, r.topLeft(), tl_x, tl_y);
@@ -269,6 +272,11 @@ PDFRectangle AnnotationPrivate::boundaryToPdfRectangle(const QRectF &r, int rFla
return PDFRectangle(br_x, br_y - width, br_x + height, br_y);
}
+PDFRectangle AnnotationPrivate::boundaryToPdfRectangle(const QRectF &r, int rFlags) const
+{
+ return Poppler::boundaryToPdfRectangle(pdfPage, r, rFlags);
+}
+
AnnotPath *AnnotationPrivate::toAnnotPath(const QVector<QPointF> &list) const
{
const int count = list.size();
diff --git a/qt6/src/poppler-annotation.h b/qt6/src/poppler-annotation.h
index 6fad7e3e..857b0f19 100644
--- a/qt6/src/poppler-annotation.h
+++ b/qt6/src/poppler-annotation.h
@@ -8,6 +8,8 @@
* Copyright (C) 2012, 2013 Fabio D'Urso <fabiodurso at hotmail.it>
* Copyright (C) 2013, Anthony Granger <grangeranthony at gmail.com>
* Copyright (C) 2018, Dileep Sankhla <sankhla.dileep96 at gmail.com>
+ * Copyright (C) 2020, Katarina Behrens <Katarina.Behrens at cib.de>
+ * Copyright (C) 2020, Klarälvdalens Datakonsult AB, a KDAB Group company, <info at kdab.com>. Work sponsored by Technische Universität Dresden
* Adapting code from
* Copyright (C) 2004 by Enrico Ros <eros.kde at email.it>
*
diff --git a/qt6/src/poppler-document.cc b/qt6/src/poppler-document.cc
index 65077e6f..9b5edc62 100644
--- a/qt6/src/poppler-document.cc
+++ b/qt6/src/poppler-document.cc
@@ -16,6 +16,8 @@
* Copyright (C) 2019, 2020 Oliver Sander <oliver.sander at tu-dresden.de>
* Copyright (C) 2019 Alexander Volkov <a.volkov at rusbitech.ru>
* Copyright (C) 2020 Philipp Knechtges <philipp-dev at knechtges.com>
+ * Copyright (C) 2020 Katarina Behrens <Katarina.Behrens at cib.de>
+ * Copyright (C) 2020 Thorsten Behrens <Thorsten.Behrens at CIB.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/qt6/src/poppler-form.cc b/qt6/src/poppler-form.cc
index de0b540c..f70cea84 100644
--- a/qt6/src/poppler-form.cc
+++ b/qt6/src/poppler-form.cc
@@ -11,6 +11,8 @@
* Copyright (C) 2018, 2020 Oliver Sander <oliver.sander at tu-dresden.de>
* Copyright (C) 2019 João Netto <joaonetto901 at gmail.com>
* Copyright (C) 2020 David García Garzón <voki at canvoki.net>
+ * Copyright (C) 2020 Thorsten Behrens <Thorsten.Behrens at CIB.de>
+ * Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, <info at kdab.com>. Work sponsored by Technische Universität Dresden
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -29,13 +31,19 @@
#include "poppler-qt6.h"
+#include <config.h>
+
#include <QtCore/QSizeF>
+#include <QUrl>
#include <Form.h>
#include <Object.h>
#include <Link.h>
#include <SignatureInfo.h>
#include <CertificateInfo.h>
+#ifdef ENABLE_NSS3
+# include <SignatureHandler.h>
+#endif
#include "poppler-form.h"
#include "poppler-page-private.h"
@@ -571,6 +579,7 @@ public:
EntityInfo issuer_info;
EntityInfo subject_info;
+ QString nick_name;
QByteArray certificate_der;
QByteArray serial_number;
QByteArray public_key;
@@ -584,6 +593,11 @@ public:
bool is_null;
};
+CertificateInfo::CertificateInfo() : d_ptr(new CertificateInfoPrivate())
+{
+ d_ptr->is_null = true;
+}
+
CertificateInfo::CertificateInfo(CertificateInfoPrivate *priv) : d_ptr(priv) { }
CertificateInfo::CertificateInfo(const CertificateInfo &other) : d_ptr(other.d_ptr) { }
@@ -650,6 +664,12 @@ QString CertificateInfo::subjectInfo(EntityInfoKey key) const
}
}
+QString CertificateInfo::nickName() const
+{
+ Q_D(const CertificateInfo);
+ return d->nick_name;
+}
+
QDateTime CertificateInfo::validityStart() const
{
Q_D(const CertificateInfo);
@@ -726,6 +746,21 @@ QByteArray CertificateInfo::certificateData() const
return d->certificate_der;
}
+bool CertificateInfo::checkPassword(const QString &password) const
+{
+#ifdef ENABLE_NSS3
+ Q_D(const CertificateInfo);
+ SignatureHandler sigHandler(d->nick_name.toUtf8().constData(), SEC_OID_SHA256);
+ unsigned char buffer[5];
+ memcpy(buffer, "test", 5);
+ sigHandler.updateHash(buffer, 5);
+ std::unique_ptr<GooString> tmpSignature = sigHandler.signDetached(password.toUtf8().constData());
+ return tmpSignature.get() != nullptr;
+#else
+ return false;
+#endif
+}
+
class SignatureValidationInfoPrivate
{
public:
@@ -897,14 +932,8 @@ SignatureValidationInfo FormFieldSignature::validate(ValidateOptions opt) const
return validate(opt, QDateTime());
}
-SignatureValidationInfo FormFieldSignature::validate(int opt, const QDateTime &validationTime) const
+static CertificateInfoPrivate *createCertificateInfoPrivate(const X509CertificateInfo *ci)
{
- FormWidgetSignature *fws = static_cast<FormWidgetSignature *>(m_formData->fm);
- const time_t validationTimeT = validationTime.isValid() ? validationTime.toSecsSinceEpoch() : -1;
- SignatureInfo *si = fws->validateSignature(opt & ValidateVerifyCertificate, opt & ValidateForceRevalidation, validationTimeT);
-
- // get certificate info
- const X509CertificateInfo *ci = si->getCertificateInfo();
CertificateInfoPrivate *certPriv = new CertificateInfoPrivate;
certPriv->is_null = true;
if (ci) {
@@ -926,6 +955,8 @@ SignatureValidationInfo FormFieldSignature::validate(int opt, const QDateTime &v
certPriv->subject_info.email_address = subjectInfo.email.c_str();
certPriv->subject_info.org_name = subjectInfo.organization.c_str();
+ certPriv->nick_name = ci->getNickName().c_str();
+
X509CertificateInfo::Validity certValidity = ci->getValidity();
certPriv->validity_start = QDateTime::fromSecsSinceEpoch(certValidity.notBefore, Qt::UTC);
certPriv->validity_end = QDateTime::fromSecsSinceEpoch(certValidity.notAfter, Qt::UTC);
@@ -941,6 +972,19 @@ SignatureValidationInfo FormFieldSignature::validate(int opt, const QDateTime &v
certPriv->is_null = false;
}
+ return certPriv;
+}
+
+SignatureValidationInfo FormFieldSignature::validate(int opt, const QDateTime &validationTime) const
+{
+ FormWidgetSignature *fws = static_cast<FormWidgetSignature *>(m_formData->fm);
+ const time_t validationTimeT = validationTime.isValid() ? validationTime.toSecsSinceEpoch() : -1;
+ SignatureInfo *si = fws->validateSignature(opt & ValidateVerifyCertificate, opt & ValidateForceRevalidation, validationTimeT);
+
+ // get certificate info
+ const X509CertificateInfo *ci = si->getCertificateInfo();
+ CertificateInfoPrivate *certPriv = createCertificateInfoPrivate(ci);
+
SignatureValidationInfoPrivate *priv = new SignatureValidationInfoPrivate(CertificateInfo(certPriv));
switch (si->getSignatureValStatus()) {
case SIGNATURE_VALID:
@@ -1012,4 +1056,65 @@ SignatureValidationInfo FormFieldSignature::validate(int opt, const QDateTime &v
return SignatureValidationInfo(priv);
}
+bool hasNSSSupport()
+{
+#ifdef ENABLE_NSS3
+ return true;
+#else
+ return false;
+#endif
+}
+
+QVector<CertificateInfo> getAvailableSigningCertificates()
+{
+ QVector<CertificateInfo> vReturnCerts;
+
+#ifdef ENABLE_NSS3
+ std::vector<std::unique_ptr<X509CertificateInfo>> vCerts = SignatureHandler::getAvailableSigningCertificates();
+
+ for (auto &cert : vCerts) {
+ CertificateInfoPrivate *certPriv = createCertificateInfoPrivate(cert.get());
+ vReturnCerts.append(CertificateInfo(certPriv));
+ }
+#endif
+
+ return vReturnCerts;
+}
+
+QString POPPLER_QT6_EXPORT getNSSDir()
+{
+#ifdef ENABLE_NSS3
+ return QString::fromLocal8Bit(SignatureHandler::getNSSDir().c_str());
+#else
+ return QString();
+#endif
+}
+
+void setNSSDir(const QString &path)
+{
+#ifdef ENABLE_NSS3
+ if (path.isEmpty())
+ return;
+
+ GooString *goo = QStringToGooString(path);
+ SignatureHandler::setNSSDir(*goo);
+ delete goo;
+#else
+ (void)path;
+#endif
+}
+
+namespace {
+std::function<QString(const QString &)> nssPasswordCall;
+}
+
+void setNSSPasswordCallback(const std::function<char *(const char *)> &f)
+{
+#ifdef ENABLE_NSS3
+ SignatureHandler::setNSSPasswordCallback(f);
+#else
+ qWarning() << "setNSSPasswordCallback called but this poppler is built without NSS support";
+ (void)f;
+#endif
+}
}
diff --git a/qt6/src/poppler-form.h b/qt6/src/poppler-form.h
index cfb72d9b..dfc8142a 100644
--- a/qt6/src/poppler-form.h
+++ b/qt6/src/poppler-form.h
@@ -9,6 +9,9 @@
* Copyright (C) 2018, Chinmoy Ranjan Pradhan <chinmoyrp65 at protonmail.com>
* Copyright (C) 2018, Oliver Sander <oliver.sander at tu-dresden.de>
* Copyright (C) 2019 João Netto <joaonetto901 at gmail.com>
+ * Copyright (C) 2019, Adrian Johnson <ajohnson at redneon.com>
+ * Copyright (C) 2020, Thorsten Behrens <Thorsten.Behrens at CIB.de>
+ * Copyright (C) 2020, Klarälvdalens Datakonsult AB, a KDAB Group company, <info at kdab.com>. Work sponsored by Technische Universität Dresden
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -28,9 +31,11 @@
#ifndef _POPPLER_QT6_FORM_H_
#define _POPPLER_QT6_FORM_H_
+#include <functional>
#include <memory>
#include <ctime>
#include <QtCore/QDateTime>
+#include <QtCore/QVector>
#include <QtCore/QList>
#include <QtCore/QRectF>
#include <QtCore/QStringList>
@@ -38,6 +43,7 @@
#include "poppler-export.h"
#include "poppler-annotation.h"
+class Object;
class Page;
class FormWidget;
class FormWidgetButton;
@@ -491,6 +497,7 @@ public:
Organization,
};
+ CertificateInfo();
CertificateInfo(CertificateInfoPrivate *priv);
~CertificateInfo();
@@ -519,6 +526,13 @@ public:
*/
QString subjectInfo(EntityInfoKey key) const;
+ /**
+ The certificate internal database nickname
+
+ \since 20.12
+ */
+ QString nickName() const;
+
/**
The date-time when certificate becomes valid.
*/
@@ -559,6 +573,13 @@ public:
*/
QByteArray certificateData() const;
+ /**
+ Checks if the given password is the correct one for this certificate
+
+ \since 20.12
+ */
+ bool checkPassword(const QString &password) const;
+
CertificateInfo(const CertificateInfo &other);
CertificateInfo &operator=(const CertificateInfo &other);
@@ -750,6 +771,40 @@ private:
Q_DISABLE_COPY(FormFieldSignature)
};
+/**
+ Returns is poppler was compiled with NSS support
+
+ \since 20.12
+*/
+bool POPPLER_QT6_EXPORT hasNSSSupport();
+
+/**
+ Return vector of suitable signing certificates
+
+ \since 20.12
+*/
+QVector<CertificateInfo> POPPLER_QT6_EXPORT getAvailableSigningCertificates();
+
+/**
+ Gets the current NSS CertDB directory
+
+ \since 20.12
+*/
+QString POPPLER_QT6_EXPORT getNSSDir();
+
+/**
+ Set a custom NSS CertDB directory. Needs to be called before doing any other signature operation
+
+ \since 20.12
+*/
+void POPPLER_QT6_EXPORT setNSSDir(const QString &pathURL);
+
+/**
+ Sets the callback for NSS password requests
+
+ \since 20.12
+*/
+void POPPLER_QT6_EXPORT setNSSPasswordCallback(const std::function<char *(const char *)> &f);
}
#endif
diff --git a/qt6/src/poppler-pdf-converter.cc b/qt6/src/poppler-pdf-converter.cc
index fe6ac4e2..91705f6e 100644
--- a/qt6/src/poppler-pdf-converter.cc
+++ b/qt6/src/poppler-pdf-converter.cc
@@ -1,6 +1,8 @@
/* poppler-pdf-converter.cc: qt interface to poppler
* Copyright (C) 2008, Pino Toscano <pino at kde.org>
* Copyright (C) 2008, 2009, 2020, Albert Astals Cid <aacid at kde.org>
+ * Copyright (C) 2020, Thorsten Behrens <Thorsten.Behrens at CIB.de>
+ * Copyright (C) 2020, Klarälvdalens Datakonsult AB, a KDAB Group company, <info at kdab.com>. Work sponsored by Technische Universität Dresden
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,12 +21,17 @@
#include "poppler-qt6.h"
+#include "poppler-annotation-helper.h"
+#include "poppler-annotation-private.h"
#include "poppler-private.h"
#include "poppler-converter-private.h"
#include "poppler-qiodeviceoutstream-private.h"
-#include <QtCore/QFile>
+#include <QFile>
+#include <QUuid>
+#include "Array.h"
+#include "Form.h"
#include <ErrorCodes.h>
namespace Poppler {
@@ -103,4 +110,215 @@ bool PDFConverter::convert()
return (errorCode == errNone);
}
+bool PDFConverter::sign(const NewSignatureData &data)
+{
+ Q_D(PDFConverter);
+ d->lastError = NoError;
+
+ if (d->document->locked) {
+ d->lastError = FileLockedError;
+ return false;
+ }
+
+ if (data.signatureText().isEmpty()) {
+ qWarning() << "No signature text given";
+ return false;
+ }
+
+ ::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(), 0 /* no flags */);
+
+ 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);
+
+ Object refObj(ref);
+ AnnotWidget *signatureAnnot = new AnnotWidget(doc, &annotObj, &refObj, field.get());
+ signatureAnnot->setFlags(signatureAnnot->getFlags() | Annot::flagPrint | Annot::flagLocked);
+ 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));
+
+ bool dummyAddDingbatsResource = false; // This is only update so if we didn't need to add
+ // the dingbats resource we should not need it now
+ signatureAnnot->generateFieldAppearance(&dummyAddDingbatsResource);
+ signatureAnnot->updateAppearanceStream();
+
+ FormWidget *formWidget = field->getWidget(field->getNumWidgets() - 1);
+ formWidget->setWidgetAnnotation(signatureAnnot);
+
+ destPage->addAnnot(signatureAnnot);
+
+ std::unique_ptr<AnnotBorder> border(new AnnotBorderArray());
+ border->setWidth(1.5);
+ 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;
+}
+
+struct PDFConverter::NewSignatureData::NewSignatureDataPrivate
+{
+ NewSignatureDataPrivate() = default;
+
+ QString certNickname;
+ QString password;
+ int page;
+ QRectF boundingRectangle;
+ QString signatureText;
+ double fontSize = 10.0;
+ QColor fontColor = Qt::red;
+ QColor borderColor = Qt::red;
+ QColor backgroundColor = QColor(240, 240, 240);
+
+ QString partialName = QUuid::createUuid().toString();
+};
+
+PDFConverter::NewSignatureData::NewSignatureData() : d(new NewSignatureDataPrivate()) { }
+
+PDFConverter::NewSignatureData::~NewSignatureData()
+{
+ delete d;
+}
+
+QString PDFConverter::NewSignatureData::certNickname() const
+{
+ return d->certNickname;
+}
+
+void PDFConverter::NewSignatureData::setCertNickname(const QString &certNickname)
+{
+ d->certNickname = certNickname;
+}
+
+QString PDFConverter::NewSignatureData::password() const
+{
+ return d->password;
+}
+
+void PDFConverter::NewSignatureData::setPassword(const QString &password)
+{
+ d->password = password;
+}
+
+int PDFConverter::NewSignatureData::page() const
+{
+ return d->page;
+}
+
+void PDFConverter::NewSignatureData::setPage(int page)
+{
+ d->page = page;
+}
+
+QRectF PDFConverter::NewSignatureData::boundingRectangle() const
+{
+ return d->boundingRectangle;
+}
+
+void PDFConverter::NewSignatureData::setBoundingRectangle(const QRectF &rect)
+{
+ d->boundingRectangle = rect;
+}
+
+QString PDFConverter::NewSignatureData::signatureText() const
+{
+ return d->signatureText;
+}
+
+void PDFConverter::NewSignatureData::setSignatureText(const QString &text)
+{
+ d->signatureText = text;
+}
+
+double PDFConverter::NewSignatureData::fontSize() const
+{
+ return d->fontSize;
+}
+
+void PDFConverter::NewSignatureData::setFontSize(double fontSize)
+{
+ d->fontSize = fontSize;
+}
+
+QColor PDFConverter::NewSignatureData::fontColor() const
+{
+ return d->fontColor;
+}
+
+void PDFConverter::NewSignatureData::setFontColor(const QColor &color)
+{
+ d->fontColor = color;
+}
+
+QColor PDFConverter::NewSignatureData::borderColor() const
+{
+ return d->borderColor;
+}
+
+void PDFConverter::NewSignatureData::setBorderColor(const QColor &color)
+{
+ d->borderColor = color;
+}
+
+QColor PDFConverter::NewSignatureData::backgroundColor() const
+{
+ return d->backgroundColor;
+}
+
+void PDFConverter::NewSignatureData::setBackgroundColor(const QColor &color)
+{
+ d->backgroundColor = color;
+}
+
+QString PDFConverter::NewSignatureData::fieldPartialName() const
+{
+ return d->partialName;
+}
+
+void PDFConverter::NewSignatureData::setFieldPartialName(const QString &name)
+{
+ d->partialName = name;
+}
}
diff --git a/qt6/src/poppler-qt6.h b/qt6/src/poppler-qt6.h
index c3c3f631..229f6c93 100644
--- a/qt6/src/poppler-qt6.h
+++ b/qt6/src/poppler-qt6.h
@@ -22,6 +22,9 @@
* Copyright (C) 2019 Jan Grulich <jgrulich at redhat.com>
* Copyright (C) 2019 Alexander Volkov <a.volkov at rusbitech.ru>
* Copyright (C) 2020 Philipp Knechtges <philipp-dev at knechtges.com>
+ * Copyright (C) 2020 Katarina Behrens <Katarina.Behrens at cib.de>
+ * Copyright (C) 2020 Thorsten Behrens <Thorsten.Behrens at CIB.de>
+ * Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, <info at kdab.com>. Work sponsored by Technische Universität Dresden
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -1944,6 +1947,86 @@ public:
*/
PDFOptions pdfOptions() const;
+ /**
+ * Holds data for a new signature
+ * - Common Name of cert to sign (aka nickname)
+ * - password for the cert
+ * - page where to add the signature
+ * - rect for the signature annotation
+ * - text that will be shown inside the rect
+ * - font size and color
+ * - border and background color
+ * \since 20.12
+ */
+ class NewSignatureData
+ {
+ public:
+ NewSignatureData();
+ ~NewSignatureData();
+ NewSignatureData(const NewSignatureData &) = delete;
+ NewSignatureData &operator=(const NewSignatureData &) = delete;
+
+ QString certNickname() const;
+ void setCertNickname(const QString &certNickname);
+
+ QString password() const;
+ void setPassword(const QString &password);
+
+ int page() const;
+ void setPage(int page);
+
+ QRectF boundingRectangle() const;
+ void setBoundingRectangle(const QRectF &rect);
+
+ QString signatureText() const;
+ void setSignatureText(const QString &text);
+
+ /**
+ * Default: 10
+ */
+ double fontSize() const;
+ void setFontSize(double fontSize);
+
+ /**
+ * Default: red
+ */
+ QColor fontColor() const;
+ void setFontColor(const QColor &color);
+
+ /**
+ * Default: red
+ */
+ QColor borderColor() const;
+ void setBorderColor(const QColor &color);
+
+ /**
+ * Default: QColor(240, 240, 240)
+ */
+ QColor backgroundColor() const;
+ void setBackgroundColor(const QColor &color);
+
+ /**
+ * Default: QUuid::createUuid().toString()
+ */
+ QString fieldPartialName() const;
+ void setFieldPartialName(const QString &name);
+
+ private:
+ struct NewSignatureDataPrivate;
+ NewSignatureDataPrivate *const d;
+ };
+
+ /**
+ Sign PDF at given Annotation / signature form
+
+ \param data new signature data
+
+ \return whether the signing succeeded
+
+ \since 20.12
+ */
+ bool sign(const NewSignatureData &data);
+
bool convert() override;
private:
More information about the poppler
mailing list