[poppler] 2 commits - poppler/Annot.cc poppler/Annot.h poppler/Form.cc poppler/Form.h qt5/src qt6/src utils/pdfsig.cc

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Mon Jan 24 12:01:08 UTC 2022


 poppler/Annot.cc        |   61 ++++++++++++++++++++++++++++++++++++++++++++++++
 poppler/Annot.h         |    7 +++++
 poppler/Form.cc         |   53 ++++++++++++++++++++++++++++++++++++++++-
 poppler/Form.h          |   10 +++++++
 qt5/src/poppler-form.cc |   34 +++++++++++++++++++++++++-
 qt5/src/poppler-form.h  |   25 ++++++++++++++++++-
 qt6/src/poppler-form.cc |   34 +++++++++++++++++++++++++-
 qt6/src/poppler-form.h  |   25 ++++++++++++++++++-
 utils/pdfsig.cc         |   13 +++++++---
 9 files changed, 249 insertions(+), 13 deletions(-)

New commits:
commit 277f5de9684b3392f0d585bd36ad1a5e9e9e9ed7
Author: Albert Astals Cid <aacid at kde.org>
Date:   Tue Jan 4 15:21:10 2022 +0100

    [qt] Add FormFieldSignature::sign

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 686d560f..8596e54e 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -598,6 +598,22 @@ AnnotBorderArray::AnnotBorderArray(Array *array)
     }
 }
 
+std::unique_ptr<AnnotBorder> AnnotBorderArray::copy() const
+{
+    AnnotBorderArray *res = new AnnotBorderArray();
+    res->type = type;
+    res->width = width;
+    res->dashLength = dashLength;
+    if (dashLength > 0) {
+        res->dash = (double *)gmallocn(dashLength, sizeof(double));
+        memcpy(res->dash, dash, dashLength * sizeof(double));
+    }
+    res->style = style;
+    res->horizontalCorner = horizontalCorner;
+    res->verticalCorner = verticalCorner;
+    return std::unique_ptr<AnnotBorder>(res);
+}
+
 Object AnnotBorderArray::writeToObject(XRef *xref) const
 {
     Array *borderArray = new Array(xref);
@@ -683,6 +699,20 @@ const char *AnnotBorderBS::getStyleName() const
     return "S";
 }
 
+std::unique_ptr<AnnotBorder> AnnotBorderBS::copy() const
+{
+    AnnotBorderBS *res = new AnnotBorderBS();
+    res->type = type;
+    res->width = width;
+    res->dashLength = dashLength;
+    if (dashLength > 0) {
+        res->dash = (double *)gmallocn(dashLength, sizeof(double));
+        memcpy(res->dash, dash, dashLength * sizeof(double));
+    }
+    res->style = style;
+    return std::unique_ptr<AnnotBorder>(res);
+}
+
 Object AnnotBorderBS::writeToObject(XRef *xref) const
 {
     Dict *dict = new Dict(xref);
@@ -1072,6 +1102,11 @@ AnnotAppearanceCharacs::AnnotAppearanceCharacs(Dict *dict)
 {
     Object obj1;
 
+    if (!dict) {
+        rotation = 0;
+        return;
+    }
+
     obj1 = dict->lookup("R");
     if (obj1.isInt()) {
         rotation = obj1.getInt();
@@ -1125,6 +1160,32 @@ AnnotAppearanceCharacs::AnnotAppearanceCharacs(Dict *dict)
 
 AnnotAppearanceCharacs::~AnnotAppearanceCharacs() = default;
 
+std::unique_ptr<AnnotAppearanceCharacs> AnnotAppearanceCharacs::copy() const
+{
+    AnnotAppearanceCharacs *res = new AnnotAppearanceCharacs(nullptr);
+    res->rotation = rotation;
+    if (borderColor) {
+        res->borderColor = std::make_unique<AnnotColor>(*borderColor);
+    }
+    if (backColor) {
+        res->backColor = std::make_unique<AnnotColor>(*backColor);
+    }
+    if (normalCaption) {
+        res->normalCaption = std::unique_ptr<GooString>(normalCaption->copy());
+    }
+    if (rolloverCaption) {
+        res->rolloverCaption = std::unique_ptr<GooString>(rolloverCaption->copy());
+    }
+    if (alternateCaption) {
+        res->alternateCaption = std::unique_ptr<GooString>(alternateCaption->copy());
+    }
+    if (iconFit) {
+        res->iconFit = std::make_unique<AnnotIconFit>(*iconFit);
+    }
+    res->position = position;
+    return std::unique_ptr<AnnotAppearanceCharacs>(res);
+}
+
 //------------------------------------------------------------------------
 // AnnotAppearanceBBox
 //------------------------------------------------------------------------
diff --git a/poppler/Annot.h b/poppler/Annot.h
index e1d211c4..b7a34bb3 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -279,6 +279,7 @@ public:
     virtual AnnotBorderStyle getStyle() const { return style; }
 
     virtual Object writeToObject(XRef *xref) const = 0;
+    virtual std::unique_ptr<AnnotBorder> copy() const = 0;
 
 protected:
     AnnotBorder();
@@ -309,6 +310,8 @@ public:
     double getHorizontalCorner() const { return horizontalCorner; }
     double getVerticalCorner() const { return verticalCorner; }
 
+    std::unique_ptr<AnnotBorder> copy() const override;
+
 private:
     AnnotBorderType getType() const override { return typeArray; }
     Object writeToObject(XRef *xref) const override;
@@ -334,6 +337,8 @@ private:
 
     const char *getStyleName() const;
 
+    std::unique_ptr<AnnotBorder> copy() const override;
+
     // double width;           // W  (Default 1)   (inherited from AnnotBorder)
     // AnnotBorderStyle style; // S  (Default S)   (inherited from AnnotBorder)
     // double *dash;           // D  (Default [3]) (inherited from AnnotBorder)
@@ -511,6 +516,8 @@ public:
     const AnnotIconFit *getIconFit() { return iconFit.get(); }
     AnnotAppearanceCharacsTextPos getPosition() const { return position; }
 
+    std::unique_ptr<AnnotAppearanceCharacs> copy() const;
+
 protected:
     int rotation; // R  (Default 0)
     std::unique_ptr<AnnotColor> borderColor; // BC
diff --git a/poppler/Form.cc b/poppler/Form.cc
index 7dd6f53f..c3624240 100644
--- a/poppler/Form.cc
+++ b/poppler/Form.cc
@@ -660,6 +660,49 @@ bool FormWidgetSignature::signDocument(const char *saveFilename, const char *cer
 #endif
 }
 
+bool FormWidgetSignature::signDocumentWithAppearance(const char *saveFilename, const char *certNickname, const char *digestName, const char *password, const GooString *reason, const GooString *location, const GooString *ownerPassword,
+                                                     const GooString *userPassword, 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)
+{
+    // Set the appearance
+    GooString *aux = getField()->getDefaultAppearance();
+    std::string originalDefaultAppearance = aux ? aux->toStr() : std::string();
+
+    const DefaultAppearance da { { objName, "SigFont" }, fontSize, std::move(fontColor) };
+    getField()->setDefaultAppearance(da.toAppearanceString());
+
+    std::unique_ptr<AnnotAppearanceCharacs> origAppearCharacs = getWidgetAnnotation()->getAppearCharacs() ? getWidgetAnnotation()->getAppearCharacs()->copy() : nullptr;
+    auto appearCharacs = std::make_unique<AnnotAppearanceCharacs>(nullptr);
+    appearCharacs->setBorderColor(std::move(borderColor));
+    appearCharacs->setBackColor(std::move(backgroundColor));
+    getWidgetAnnotation()->setAppearCharacs(std::move(appearCharacs));
+
+    std::unique_ptr<AnnotBorder> origBorderCopy = getWidgetAnnotation()->getBorder() ? getWidgetAnnotation()->getBorder()->copy() : nullptr;
+    std::unique_ptr<AnnotBorder> border(new AnnotBorderArray());
+    border->setWidth(borderWidth);
+    getWidgetAnnotation()->setBorder(std::move(border));
+
+    getWidgetAnnotation()->generateFieldAppearance();
+    getWidgetAnnotation()->updateAppearanceStream();
+
+    ::FormFieldSignature *ffs = static_cast<::FormFieldSignature *>(getField());
+    ffs->setCustomAppearanceContent(signatureText);
+    ffs->setCustomAppearanceLeftContent(signatureTextLeft);
+
+    const bool success = signDocument(saveFilename, certNickname, digestName, password, reason, location, ownerPassword, userPassword);
+
+    // Now bring back the annotation appearance back to what it was
+    ffs->setDefaultAppearance(originalDefaultAppearance);
+    ffs->setCustomAppearanceContent({});
+    ffs->setCustomAppearanceLeftContent({});
+    getWidgetAnnotation()->setAppearCharacs(std::move(origAppearCharacs));
+    getWidgetAnnotation()->setBorder(std::move(origBorderCopy));
+    getWidgetAnnotation()->generateFieldAppearance();
+    getWidgetAnnotation()->updateAppearanceStream();
+
+    return success;
+}
+
 // Get start and end file position of objNum in the PDF named filename.
 bool FormWidgetSignature::getObjectStartEnd(GooString *filename, int objNum, Goffset *objStart, Goffset *objEnd, const GooString *ownerPassword, const GooString *userPassword)
 {
@@ -956,6 +999,12 @@ FormField::FormField(PDFDoc *docA, Object &&aobj, const Ref aref, FormField *par
     }
 }
 
+void FormField::setDefaultAppearance(const std::string &appearance)
+{
+    delete defaultAppearance;
+    defaultAppearance = new GooString(appearance);
+}
+
 void FormField::setPartialName(const GooString &name)
 {
     delete partialName;
diff --git a/poppler/Form.h b/poppler/Form.h
index 0aaf1933..cef04150 100644
--- a/poppler/Form.h
+++ b/poppler/Form.h
@@ -315,6 +315,11 @@ public:
     bool signDocument(const char *filename, const char *certNickname, const char *digestName, const char *password, const GooString *reason = nullptr, const GooString *location = nullptr, const GooString *ownerPassword = nullptr,
                       const GooString *userPassword = nullptr);
 
+    // Same as above but adds text, font color, etc.
+    bool signDocumentWithAppearance(const char *filename, const char *certNickname, const char *digestName, const char *password, const GooString *reason = nullptr, const GooString *location = nullptr,
+                                    const GooString *ownerPassword = nullptr, const GooString *userPassword = nullptr, 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 = {});
+
     // checks the length encoding of the signature and returns the hex encoded signature
     // if the check passed (and the checked file size as output parameter in checkedFileSize)
     // otherwise a nullptr is returned
@@ -355,6 +360,8 @@ public:
     bool isStandAlone() const { return standAlone; }
 
     GooString *getDefaultAppearance() const { return defaultAppearance; }
+    void setDefaultAppearance(const std::string &appearance);
+
     bool hasTextQuadding() const { return hasQuadding; }
     VariableTextQuadding getTextQuadding() const { return quadding; }
 
diff --git a/qt5/src/poppler-form.cc b/qt5/src/poppler-form.cc
index 9c6042dc..620663fe 100644
--- a/qt5/src/poppler-form.cc
+++ b/qt5/src/poppler-form.cc
@@ -31,7 +31,7 @@
  * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
-#include "poppler-qt5.h"
+#include "poppler-form.h"
 
 #include <config.h>
 
@@ -47,7 +47,6 @@
 #    include <SignatureHandler.h>
 #endif
 
-#include "poppler-form.h"
 #include "poppler-page-private.h"
 #include "poppler-private.h"
 #include "poppler-annotation-helper.h"
@@ -1060,6 +1059,34 @@ SignatureValidationInfo FormFieldSignature::validate(int opt, const QDateTime &v
     return SignatureValidationInfo(priv);
 }
 
+FormFieldSignature::SigningResult FormFieldSignature::sign(const QString &outputFileName, const PDFConverter::NewSignatureData &data) const
+{
+    FormWidgetSignature *fws = static_cast<FormWidgetSignature *>(m_formData->fm);
+    if (fws->signatureType() != unsigned_signature_field) {
+        return FieldAlreadySigned;
+    }
+
+    Goffset file_size = 0;
+    const std::optional<GooString> sig = fws->getCheckedSignature(&file_size);
+    if (sig) {
+        // the above unsigned_signature_field check
+        // should already catch this, but double check
+        return FieldAlreadySigned;
+    }
+    const auto reason = std::unique_ptr<GooString>(data.reason().isEmpty() ? nullptr : QStringToUnicodeGooString(data.reason()));
+    const auto location = std::unique_ptr<GooString>(data.location().isEmpty() ? nullptr : QStringToUnicodeGooString(data.location()));
+    const auto ownerPwd = std::make_unique<GooString>(data.documentOwnerPassword().constData());
+    const auto userPwd = std::make_unique<GooString>(data.documentUserPassword().constData());
+    const auto gSignatureText = std::unique_ptr<GooString>(QStringToUnicodeGooString(data.signatureText()));
+    const auto gSignatureLeftText = std::unique_ptr<GooString>(QStringToUnicodeGooString(data.signatureLeftText()));
+
+    const bool success =
+            fws->signDocumentWithAppearance(outputFileName.toUtf8().constData(), data.certNickname().toUtf8().constData(), "SHA256", data.password().toUtf8().constData(), reason.get(), location.get(), ownerPwd.get(), userPwd.get(),
+                                            *gSignatureText, *gSignatureLeftText, data.fontSize(), convertQColor(data.fontColor()), data.borderWidth(), convertQColor(data.borderColor()), convertQColor(data.backgroundColor()));
+
+    return success ? SigningSuccess : GenericSigningError;
+}
+
 bool hasNSSSupport()
 {
 #ifdef ENABLE_NSS3
diff --git a/qt5/src/poppler-form.h b/qt5/src/poppler-form.h
index 600a604b..0e64f2ee 100644
--- a/qt5/src/poppler-form.h
+++ b/qt5/src/poppler-form.h
@@ -1,6 +1,6 @@
 /* poppler-form.h: qt interface to poppler
  * Copyright (C) 2007-2008, Pino Toscano <pino at kde.org>
- * Copyright (C) 2008, 2011, 2016, 2017, 2019-2021, Albert Astals Cid <aacid at kde.org>
+ * Copyright (C) 2008, 2011, 2016, 2017, 2019-2022, Albert Astals Cid <aacid at kde.org>
  * Copyright (C) 2012, Adam Reichold <adamreichold at myopera.com>
  * Copyright (C) 2016, Hanno Meyer-Thurow <h.mth at web.de>
  * Copyright (C) 2017, Hans-Ulrich Jüttner <huj at froreich-bioscientia.de>
@@ -43,6 +43,7 @@
 #include <QtCore/QSharedPointer>
 #include "poppler-export.h"
 #include "poppler-annotation.h"
+#include "poppler-qt5.h"
 
 class Object;
 class Page;
@@ -822,6 +823,25 @@ public:
      */
     SignatureValidationInfo validate(int opt, const QDateTime &validationTime) const;
 
+    /**
+     * \since 22.02
+     */
+    enum SigningResult
+    {
+        FieldAlreadySigned, ///< Trying to sign a field that is already signed
+        GenericSigningError,
+        SigningSuccess
+    };
+
+    /**
+      Signs a field of UnsignedSignature type.
+
+      Ignores data.page(), data.fieldPartialName() and data.boundingRectangle()
+
+      \since 22.02
+     */
+    SigningResult sign(const QString &outputFileName, const PDFConverter::NewSignatureData &data) const;
+
 private:
     Q_DISABLE_COPY(FormFieldSignature)
 };
diff --git a/qt6/src/poppler-form.cc b/qt6/src/poppler-form.cc
index 2604cfd0..28a1e565 100644
--- a/qt6/src/poppler-form.cc
+++ b/qt6/src/poppler-form.cc
@@ -31,7 +31,7 @@
  * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
-#include "poppler-qt6.h"
+#include "poppler-form.h"
 
 #include <config.h>
 
@@ -47,7 +47,6 @@
 #    include <SignatureHandler.h>
 #endif
 
-#include "poppler-form.h"
 #include "poppler-page-private.h"
 #include "poppler-private.h"
 #include "poppler-annotation-helper.h"
@@ -1060,6 +1059,34 @@ SignatureValidationInfo FormFieldSignature::validate(int opt, const QDateTime &v
     return SignatureValidationInfo(priv);
 }
 
+FormFieldSignature::SigningResult FormFieldSignature::sign(const QString &outputFileName, const PDFConverter::NewSignatureData &data) const
+{
+    FormWidgetSignature *fws = static_cast<FormWidgetSignature *>(m_formData->fm);
+    if (fws->signatureType() != unsigned_signature_field) {
+        return FieldAlreadySigned;
+    }
+
+    Goffset file_size = 0;
+    const std::optional<GooString> sig = fws->getCheckedSignature(&file_size);
+    if (sig) {
+        // the above unsigned_signature_field check
+        // should already catch this, but double check
+        return FieldAlreadySigned;
+    }
+    const auto reason = std::unique_ptr<GooString>(data.reason().isEmpty() ? nullptr : QStringToUnicodeGooString(data.reason()));
+    const auto location = std::unique_ptr<GooString>(data.location().isEmpty() ? nullptr : QStringToUnicodeGooString(data.location()));
+    const auto ownerPwd = std::make_unique<GooString>(data.documentOwnerPassword().constData());
+    const auto userPwd = std::make_unique<GooString>(data.documentUserPassword().constData());
+    const auto gSignatureText = std::unique_ptr<GooString>(QStringToUnicodeGooString(data.signatureText()));
+    const auto gSignatureLeftText = std::unique_ptr<GooString>(QStringToUnicodeGooString(data.signatureLeftText()));
+
+    const bool success =
+            fws->signDocumentWithAppearance(outputFileName.toUtf8().constData(), data.certNickname().toUtf8().constData(), "SHA256", data.password().toUtf8().constData(), reason.get(), location.get(), ownerPwd.get(), userPwd.get(),
+                                            *gSignatureText, *gSignatureLeftText, data.fontSize(), convertQColor(data.fontColor()), data.borderWidth(), convertQColor(data.borderColor()), convertQColor(data.backgroundColor()));
+
+    return success ? SigningSuccess : GenericSigningError;
+}
+
 bool hasNSSSupport()
 {
 #ifdef ENABLE_NSS3
diff --git a/qt6/src/poppler-form.h b/qt6/src/poppler-form.h
index a5f53c48..beba9fca 100644
--- a/qt6/src/poppler-form.h
+++ b/qt6/src/poppler-form.h
@@ -1,6 +1,6 @@
 /* poppler-form.h: qt interface to poppler
  * Copyright (C) 2007-2008, Pino Toscano <pino at kde.org>
- * Copyright (C) 2008, 2011, 2016, 2017, 2019-2021, Albert Astals Cid <aacid at kde.org>
+ * Copyright (C) 2008, 2011, 2016, 2017, 2019-2022, Albert Astals Cid <aacid at kde.org>
  * Copyright (C) 2012, Adam Reichold <adamreichold at myopera.com>
  * Copyright (C) 2016, Hanno Meyer-Thurow <h.mth at web.de>
  * Copyright (C) 2017, Hans-Ulrich Jüttner <huj at froreich-bioscientia.de>
@@ -43,6 +43,7 @@
 #include <QtCore/QSharedPointer>
 #include "poppler-export.h"
 #include "poppler-annotation.h"
+#include "poppler-qt6.h"
 
 class Object;
 class Page;
@@ -771,6 +772,25 @@ public:
      */
     SignatureValidationInfo validate(int opt, const QDateTime &validationTime) const;
 
+    /**
+     * \since 22.02
+     */
+    enum SigningResult
+    {
+        FieldAlreadySigned, ///< Trying to sign a field that is already signed
+        GenericSigningError,
+        SigningSuccess
+    };
+
+    /**
+      Signs a field of UnsignedSignature type.
+
+      Ignores data.page(), data.fieldPartialName() and data.boundingRectangle()
+
+      \since 22.02
+     */
+    SigningResult sign(const QString &outputFileName, const PDFConverter::NewSignatureData &data) const;
+
 private:
     Q_DISABLE_COPY(FormFieldSignature)
 };
commit 5e7f4bd726f82e632f14c21261277f9f944fd918
Author: Albert Astals Cid <aacid at kde.org>
Date:   Mon Jan 3 14:40:10 2022 +0100

    Add a way to detect unsigned FormFieldSignature
    
    Adobe Acrobat creates those when you're creating a field to ask
    someone else to sign the document

diff --git a/poppler/Form.cc b/poppler/Form.cc
index f2b4815a..7dd6f53f 100644
--- a/poppler/Form.cc
+++ b/poppler/Form.cc
@@ -1986,7 +1986,7 @@ void FormFieldChoice::reset(const std::vector<std::string> &excludedFields)
 // FormFieldSignature
 //------------------------------------------------------------------------
 FormFieldSignature::FormFieldSignature(PDFDoc *docA, Object &&dict, const Ref refA, FormField *parentA, std::set<int> *usedParents)
-    : FormField(docA, std::move(dict), refA, parentA, usedParents, formSignature), signature_type(unknown_signature_type), signature(nullptr)
+    : FormField(docA, std::move(dict), refA, parentA, usedParents, formSignature), signature_type(unsigned_signature_field), signature(nullptr)
 {
     signature_info = new SignatureInfo();
     parseInfo();
@@ -2107,6 +2107,8 @@ void FormFieldSignature::parseInfo()
     } else if (subfilterName.isName("ETSI.CAdES.detached")) {
         signature_type = ETSI_CAdES_detached;
         signature_info->setSubFilterSupport(true);
+    } else {
+        signature_type = unknown_signature_type;
     }
 }
 
diff --git a/poppler/Form.h b/poppler/Form.h
index a5ca8fdf..0aaf1933 100644
--- a/poppler/Form.h
+++ b/poppler/Form.h
@@ -83,7 +83,8 @@ enum FormSignatureType
     adbe_pkcs7_sha1,
     adbe_pkcs7_detached,
     ETSI_CAdES_detached,
-    unknown_signature_type
+    unknown_signature_type,
+    unsigned_signature_field
 };
 
 enum FillValueType
diff --git a/qt5/src/poppler-form.cc b/qt5/src/poppler-form.cc
index 36f7b451..9c6042dc 100644
--- a/qt5/src/poppler-form.cc
+++ b/qt5/src/poppler-form.cc
@@ -925,6 +925,9 @@ FormFieldSignature::SignatureType FormFieldSignature::signatureType() const
     case unknown_signature_type:
         sigType = UnknownSignatureType;
         break;
+    case unsigned_signature_field:
+        sigType = UnsignedSignature;
+        break;
     }
     return sigType;
 }
diff --git a/qt5/src/poppler-form.h b/qt5/src/poppler-form.h
index b7197f0f..600a604b 100644
--- a/qt5/src/poppler-form.h
+++ b/qt5/src/poppler-form.h
@@ -778,7 +778,8 @@ public:
         AdbePkcs7sha1,
         AdbePkcs7detached,
         EtsiCAdESdetached,
-        UnknownSignatureType ///< \since 0.90
+        UnknownSignatureType, ///< \since 0.90
+        UnsignedSignature ///< \since 22.02
     };
 
     /**
diff --git a/qt6/src/poppler-form.cc b/qt6/src/poppler-form.cc
index d24e3892..2604cfd0 100644
--- a/qt6/src/poppler-form.cc
+++ b/qt6/src/poppler-form.cc
@@ -925,6 +925,9 @@ FormFieldSignature::SignatureType FormFieldSignature::signatureType() const
     case unknown_signature_type:
         sigType = UnknownSignatureType;
         break;
+    case unsigned_signature_field:
+        sigType = UnsignedSignature;
+        break;
     }
     return sigType;
 }
diff --git a/qt6/src/poppler-form.h b/qt6/src/poppler-form.h
index c77b0879..a5f53c48 100644
--- a/qt6/src/poppler-form.h
+++ b/qt6/src/poppler-form.h
@@ -730,7 +730,8 @@ public:
         UnknownSignatureType,
         AdbePkcs7sha1,
         AdbePkcs7detached,
-        EtsiCAdESdetached
+        EtsiCAdESdetached,
+        UnsignedSignature ///< \since 22.02
     };
 
     /**
diff --git a/utils/pdfsig.cc b/utils/pdfsig.cc
index 7908ac05..fbba2505 100644
--- a/utils/pdfsig.cc
+++ b/utils/pdfsig.cc
@@ -420,8 +420,15 @@ int main(int argc, char *argv[])
     }
 
     for (unsigned int i = 0; i < sigCount; i++) {
-        const SignatureInfo *sig_info = signatures.at(i)->validateSignature(!dontVerifyCert, false, -1 /* now */, !noOCSPRevocationCheck, useAIACertFetch);
+        FormFieldSignature *ffs = signatures.at(i);
         printf("Signature #%u:\n", i + 1);
+
+        if (ffs->getSignatureType() == unsigned_signature_field) {
+            printf("  The signature form field is not signed.\n");
+            continue;
+        }
+
+        const SignatureInfo *sig_info = ffs->validateSignature(!dontVerifyCert, false, -1 /* now */, !noOCSPRevocationCheck, useAIACertFetch);
         printf("  - Signer Certificate Common Name: %s\n", sig_info->getSignerName());
         printf("  - Signer full Distinguished Name: %s\n", sig_info->getSubjectDN());
         printf("  - Signing Time: %s\n", time_str = getReadableTime(sig_info->getSigningTime()));
@@ -452,7 +459,7 @@ int main(int argc, char *argv[])
             printf("unknown\n");
         }
         printf("  - Signature Type: ");
-        switch (signatures.at(i)->getSignatureType()) {
+        switch (ffs->getSignatureType()) {
         case adbe_pkcs7_sha1:
             printf("adbe.pkcs7.sha1\n");
             break;
@@ -465,7 +472,7 @@ int main(int argc, char *argv[])
         default:
             printf("unknown\n");
         }
-        std::vector<Goffset> ranges = signatures.at(i)->getSignedRangeBounds();
+        const std::vector<Goffset> ranges = ffs->getSignedRangeBounds();
         if (ranges.size() == 4) {
             printf("  - Signed Ranges: [%lld - %lld], [%lld - %lld]\n", ranges[0], ranges[1], ranges[2], ranges[3]);
             Goffset checked_file_size;


More information about the poppler mailing list