Add FPDF_GetSignatureCount() API [pdfium : master]

2 views
Skip to first unread message

Miklos V (Gerrit)

unread,
Jun 23, 2020, 9:23:24 AM6/23/20
to Lei Zhang, Tom Sepez, pdfium-...@googlegroups.com

Lei: could you please take a look? Thanks. :-)

If this is fine, then I guess the next step would be actually exposing some "pdf signature" object, so you can get the Nth object when the API added in this change says there are such objects.

View Change

    To view, visit change 70830. To unsubscribe, or for help writing mail filters, visit settings.

    Gerrit-Project: pdfium
    Gerrit-Branch: master
    Gerrit-Change-Id: I9b913521bd700bfadd8ca02f5c6fe49f7b63e31e
    Gerrit-Change-Number: 70830
    Gerrit-PatchSet: 1
    Gerrit-Owner: Miklos V <vmi...@collabora.co.uk>
    Gerrit-CC: Lei Zhang <the...@chromium.org>
    Gerrit-CC: Tom Sepez <tse...@chromium.org>
    Gerrit-Comment-Date: Tue, 23 Jun 2020 13:23:21 +0000
    Gerrit-HasComments: No
    Gerrit-Has-Labels: No
    Gerrit-MessageType: comment

    Lei Zhang (Gerrit)

    unread,
    Jun 23, 2020, 3:36:07 PM6/23/20
    to Miklos V, Lei Zhang, Tom Sepez, pdfium-...@googlegroups.com

    Is this going to lead into having a family of APIs for digital signatures? Do we want put them in a separate header in the public/ directory?

    Can two_signatures.pdf be smaller and still have all the document features needed to test digital signatures like the current ~100 KB one?

    I imagine trying to handwrite two_signatures.pdf is way too difficult. If we are checking in a PDF, can the CL description explain how it's generated?

    View Change

      To view, visit change 70830. To unsubscribe, or for help writing mail filters, visit settings.

      Gerrit-Project: pdfium
      Gerrit-Branch: master
      Gerrit-Change-Id: I9b913521bd700bfadd8ca02f5c6fe49f7b63e31e
      Gerrit-Change-Number: 70830
      Gerrit-PatchSet: 1
      Gerrit-Owner: Miklos V <vmi...@collabora.co.uk>
      Gerrit-CC: Lei Zhang <the...@chromium.org>
      Gerrit-CC: Tom Sepez <tse...@chromium.org>
      Gerrit-Comment-Date: Tue, 23 Jun 2020 19:36:04 +0000

      Miklos V (Gerrit)

      unread,
      Jun 24, 2020, 4:26:16 AM6/24/20
      to Lei Zhang, Tom Sepez, pdfium-...@googlegroups.com

      Is this going to lead into having a family of APIs for digital signatures? Do we want put them in a separate header in the public/ directory?

      Yes, I imagine some 5 more functions till signatures can be verified by client code. One to get the Nth signature, then to access a few properties. Done.

      Can two_signatures.pdf be smaller and still have all the document features needed to test digital signatures like the current ~100 KB one?

      I had integration testing in mind, in which case a hexdump of a PKCS#7 signature blob is around 50KB. I tested with Acrobat and LibreOffice, both create signatures with around that size.

      I imagine trying to handwrite two_signatures.pdf is way too difficult. If we are checking in a PDF, can the CL description explain how it's generated?

      Actually we can handwrite it for unit testing purposes, given that the PKCS#7 blob can be simply a stub. This instantly solves the size concern as well. Done.

      For the reference, I created a self-signed CA + two x509 signing certificates using the openssl commandline tool, then signed an empty PDF with LibreOffice, that's how I created the test file in patch set 1. (Could do the same with Acrobat as well, the output would be quite similar.) But based on the above, this is not needed after all.

      Also, FPDF_GetSignatureCount() now returns -1 if the document argument is nullptr.

      View Change

        To view, visit change 70830. To unsubscribe, or for help writing mail filters, visit settings.

        Gerrit-Project: pdfium
        Gerrit-Branch: master
        Gerrit-Change-Id: I9b913521bd700bfadd8ca02f5c6fe49f7b63e31e
        Gerrit-Change-Number: 70830
        Gerrit-PatchSet: 1
        Gerrit-Owner: Miklos V <vmi...@collabora.co.uk>
        Gerrit-CC: Lei Zhang <the...@chromium.org>
        Gerrit-CC: Tom Sepez <tse...@chromium.org>
        Gerrit-Comment-Date: Wed, 24 Jun 2020 08:26:10 +0000

        Lei Zhang (Gerrit)

        unread,
        Jun 24, 2020, 4:46:39 AM6/24/20
        to Miklos V, Lei Zhang, Tom Sepez, pdfium-...@googlegroups.com

        Patch Set 1:


        > I imagine trying to handwrite two_signatures.pdf is way too difficult. If we are checking in a PDF, can the CL description explain how it's generated?

        Actually we can handwrite it for unit testing purposes, given that the PKCS#7 blob can be simply a stub. This instantly solves the size concern as well. Done.

        Nice. This is definitely one of the fancier .in files. Glad it works.

        Also, FPDF_GetSignatureCount() now returns -1 if the document argument is nullptr.

        Make sense. Thanks.

        Patch set 2:Commit-Queue +1

        View Change

        9 comments:

        To view, visit change 70830. To unsubscribe, or for help writing mail filters, visit settings.

        Gerrit-Project: pdfium
        Gerrit-Branch: master
        Gerrit-Change-Id: I9b913521bd700bfadd8ca02f5c6fe49f7b63e31e
        Gerrit-Change-Number: 70830
        Gerrit-PatchSet: 2
        Gerrit-Owner: Miklos V <vmi...@collabora.co.uk>
        Gerrit-Reviewer: Lei Zhang <the...@chromium.org>
        Gerrit-CC: Tom Sepez <tse...@chromium.org>
        Gerrit-Comment-Date: Wed, 24 Jun 2020 08:46:35 +0000
        Gerrit-HasComments: Yes
        Gerrit-Has-Labels: Yes
        Gerrit-MessageType: comment

        Miklos V (Gerrit)

        unread,
        Jun 24, 2020, 5:25:50 AM6/24/20
        to Chromium commit bot, Lei Zhang, Tom Sepez, pdfium-...@googlegroups.com

        I think I addressed all of your points, please let me know if something is still missing. Thanks.

        View Change

        9 comments:

          • Patch Set #2, Line 486: TEST_F(FPDFDocEmbedderTest, GetSignatureCount) {

            I would similarly move these into its own test file.

          • Patch Set #2, Line 298: FPDF_EXPORT int FPDF_CALLCONV FPDF_GetSignatureCount(FPDF_DOCUMENT document) {

            And separate fpdfsdk/fpdf_signature.cpp.

          • Done

          • Patch Set #2, Line 322: GetStringFor

            BTW, I'm hoping to add GetNameFor() later this week. Then we can switch to that here.

          • This comment is a bit mysterious. […]

            What I meant to point out is that these are start offset + length pairs, not start offset + end offset ones. It's in the spec, but it can confusing if you just read the .in file. I've updated the comment to be more explicit.

          • Not really. I just added the new objects, then went up the parents chain and updated the old objects to refer to the new ones. Sorted now.

          • Patch Set #2, Line 48: /Type/Sig

            I would put /Type, /Filter, and /SubFilter first, and then just sort the rest.

          • Done for both signature objects.

          • Done for both.

          • Done for both.

        To view, visit change 70830. To unsubscribe, or for help writing mail filters, visit settings.

        Gerrit-Project: pdfium
        Gerrit-Branch: master
        Gerrit-Change-Id: I9b913521bd700bfadd8ca02f5c6fe49f7b63e31e
        Gerrit-Change-Number: 70830
        Gerrit-PatchSet: 2
        Gerrit-Owner: Miklos V <vmi...@collabora.co.uk>
        Gerrit-Reviewer: Lei Zhang <the...@chromium.org>
        Gerrit-CC: Chromium commit bot <commi...@chromium.org>
        Gerrit-CC: Tom Sepez <tse...@chromium.org>
        Gerrit-Comment-Date: Wed, 24 Jun 2020 09:25:46 +0000
        Gerrit-HasComments: Yes
        Gerrit-Has-Labels: No
        Comment-In-Reply-To: Lei Zhang <the...@chromium.org>
        Gerrit-MessageType: comment

        Lei Zhang (Gerrit)

        unread,
        Jun 25, 2020, 4:46:57 AM6/25/20
        to Miklos V, Chromium commit bot, Lei Zhang, Tom Sepez, pdfium-...@googlegroups.com

        Mostly good. Just nit picking.

        View Change

        9 comments:

        To view, visit change 70830. To unsubscribe, or for help writing mail filters, visit settings.

        Gerrit-Project: pdfium
        Gerrit-Branch: master
        Gerrit-Change-Id: I9b913521bd700bfadd8ca02f5c6fe49f7b63e31e
        Gerrit-Change-Number: 70830
        Gerrit-PatchSet: 3
        Gerrit-Owner: Miklos V <vmi...@collabora.co.uk>
        Gerrit-Reviewer: Lei Zhang <the...@chromium.org>
        Gerrit-CC: Chromium commit bot <commi...@chromium.org>
        Gerrit-CC: Tom Sepez <tse...@chromium.org>
        Gerrit-Comment-Date: Thu, 25 Jun 2020 08:46:53 +0000
        Gerrit-HasComments: Yes
        Gerrit-Has-Labels: No
        Comment-In-Reply-To: Lei Zhang <the...@chromium.org>
        Comment-In-Reply-To: Miklos V <vmi...@collabora.co.uk>
        Gerrit-MessageType: comment

        Miklos V (Gerrit)

        unread,
        Jun 25, 2020, 6:29:49 AM6/25/20
        to Chromium commit bot, Lei Zhang, Tom Sepez, pdfium-...@googlegroups.com

        I think I addressed all nits now.

        View Change

        9 comments:

          • Patch Set #3, Line 13: pDoc

            BTW, I would recommend avoiding Hungarian notation in new code. Just go with Chromium style.

          • Patch Set #3, Line 45: {{object 1 0}} <<

            It'll be helpful to add a comment here and on line 103 to explain why there are repeated objects.

          • Done

          • Expand this out as well? […]

            Done

          • I assume you mean avoid empty lines inside the two incremental updates, I did that now.

          • Done

          • I think I fixed all cases where / was not preceded by a space and broke up all lines with <<.*>> in them.

        To view, visit change 70830. To unsubscribe, or for help writing mail filters, visit settings.

        Gerrit-Project: pdfium
        Gerrit-Branch: master
        Gerrit-Change-Id: I9b913521bd700bfadd8ca02f5c6fe49f7b63e31e
        Gerrit-Change-Number: 70830
        Gerrit-PatchSet: 3
        Gerrit-Owner: Miklos V <vmi...@collabora.co.uk>
        Gerrit-Reviewer: Lei Zhang <the...@chromium.org>
        Gerrit-CC: Chromium commit bot <commi...@chromium.org>
        Gerrit-CC: Tom Sepez <tse...@chromium.org>
        Gerrit-Comment-Date: Thu, 25 Jun 2020 10:29:44 +0000

        Lei Zhang (Gerrit)

        unread,
        Jun 25, 2020, 1:25:02 PM6/25/20
        to Miklos V, Chromium commit bot, Lei Zhang, Tom Sepez, pdfium-...@googlegroups.com

        Hopefully the last round of nits.

        View Change

        8 comments:

        To view, visit change 70830. To unsubscribe, or for help writing mail filters, visit settings.

        Gerrit-Project: pdfium
        Gerrit-Branch: master
        Gerrit-Change-Id: I9b913521bd700bfadd8ca02f5c6fe49f7b63e31e
        Gerrit-Change-Number: 70830
        Gerrit-PatchSet: 4
        Gerrit-Owner: Miklos V <vmi...@collabora.co.uk>
        Gerrit-Reviewer: Lei Zhang <the...@chromium.org>
        Gerrit-CC: Chromium commit bot <commi...@chromium.org>
        Gerrit-CC: Tom Sepez <tse...@chromium.org>
        Gerrit-Comment-Date: Thu, 25 Jun 2020 17:24:59 +0000
        Gerrit-HasComments: Yes
        Gerrit-Has-Labels: No
        Gerrit-MessageType: comment

        Tom Sepez (Gerrit)

        unread,
        Jun 25, 2020, 2:03:48 PM6/25/20
        to Miklos V, Chromium commit bot, Lei Zhang, pdfium-...@googlegroups.com

        View Change

        1 comment:

        • File fpdfsdk/fpdf_signature.cpp:

          • Patch Set #4, Line 33:

             if (!fieldDict)
            continue;

            if (fieldDict->GetNameFor("FT") != "Sig")
            continue;

            ++signatureCount;

            drive-by nit: As much as we like |continue| to avoid deep nesting, its probably clearer when written as

              if (field_dict && field_dict->GetNameFor("FT") == "Sig")
            ++count;

        To view, visit change 70830. To unsubscribe, or for help writing mail filters, visit settings.

        Gerrit-Project: pdfium
        Gerrit-Branch: master
        Gerrit-Change-Id: I9b913521bd700bfadd8ca02f5c6fe49f7b63e31e
        Gerrit-Change-Number: 70830
        Gerrit-PatchSet: 4
        Gerrit-Owner: Miklos V <vmi...@collabora.co.uk>
        Gerrit-Reviewer: Lei Zhang <the...@chromium.org>
        Gerrit-CC: Chromium commit bot <commi...@chromium.org>
        Gerrit-CC: Tom Sepez <tse...@chromium.org>
        Gerrit-Comment-Date: Thu, 25 Jun 2020 18:03:45 +0000

        Miklos V (Gerrit)

        unread,
        Jun 25, 2020, 4:28:21 PM6/25/20
        to Chromium commit bot, Lei Zhang, Tom Sepez, pdfium-...@googlegroups.com

        Hopefully the last round of nits.

        All done, I believe.

        View Change

        9 comments:

          • With a lowercase 'f' please, or acro_form.

          • Done

          • Maybe just go with "i" since there are no other indices. […]

            invalid range expression of type 'const CPDF_Array *'; no viable 'begin' function available

            So I went with "i" for now.

          • Patch Set #4, Line 33:

             if (!fieldDict)
            continue;

            if (fieldDict->GetNameFor("FT") != "Sig")
            continue;

            ++signatureCount;

          • Patch Set #4, Line 45: %% First incremental update adds an initial signature and update objects to refer to it.

            Wrap at 80 columns.

          • Done

          • Done

          • Done

          • Done

          • Done

        To view, visit change 70830. To unsubscribe, or for help writing mail filters, visit settings.

        Gerrit-Project: pdfium
        Gerrit-Branch: master
        Gerrit-Change-Id: I9b913521bd700bfadd8ca02f5c6fe49f7b63e31e
        Gerrit-Change-Number: 70830
        Gerrit-PatchSet: 5
        Gerrit-Owner: Miklos V <vmi...@collabora.co.uk>
        Gerrit-Reviewer: Lei Zhang <the...@chromium.org>
        Gerrit-CC: Chromium commit bot <commi...@chromium.org>
        Gerrit-CC: Tom Sepez <tse...@chromium.org>
        Gerrit-Comment-Date: Thu, 25 Jun 2020 20:28:18 +0000
        Gerrit-HasComments: Yes
        Gerrit-Has-Labels: No
        Comment-In-Reply-To: Lei Zhang <the...@chromium.org>
        Comment-In-Reply-To: Tom Sepez <tse...@chromium.org>
        Gerrit-MessageType: comment

        Lei Zhang (Gerrit)

        unread,
        Jun 25, 2020, 4:51:04 PM6/25/20
        to Miklos V, Chromium commit bot, Lei Zhang, Tom Sepez, pdfium-...@googlegroups.com

        View Change

        3 comments:

        To view, visit change 70830. To unsubscribe, or for help writing mail filters, visit settings.

        Gerrit-Project: pdfium
        Gerrit-Branch: master
        Gerrit-Change-Id: I9b913521bd700bfadd8ca02f5c6fe49f7b63e31e
        Gerrit-Change-Number: 70830
        Gerrit-PatchSet: 5
        Gerrit-Owner: Miklos V <vmi...@collabora.co.uk>
        Gerrit-Reviewer: Lei Zhang <the...@chromium.org>
        Gerrit-CC: Chromium commit bot <commi...@chromium.org>
        Gerrit-CC: Tom Sepez <tse...@chromium.org>
        Gerrit-Comment-Date: Thu, 25 Jun 2020 20:51:01 +0000
        Gerrit-HasComments: Yes
        Gerrit-Has-Labels: No
        Comment-In-Reply-To: Lei Zhang <the...@chromium.org>

        Miklos V (Gerrit)

        unread,
        Jun 25, 2020, 5:04:21 PM6/25/20
        to Chromium commit bot, Lei Zhang, Tom Sepez, pdfium-...@googlegroups.com

        View Change

        3 comments:

          • Done here and for the other Widget as well.

        To view, visit change 70830. To unsubscribe, or for help writing mail filters, visit settings.

        Gerrit-Project: pdfium
        Gerrit-Branch: master
        Gerrit-Change-Id: I9b913521bd700bfadd8ca02f5c6fe49f7b63e31e
        Gerrit-Change-Number: 70830
        Gerrit-PatchSet: 5
        Gerrit-Owner: Miklos V <vmi...@collabora.co.uk>
        Gerrit-Reviewer: Lei Zhang <the...@chromium.org>
        Gerrit-CC: Chromium commit bot <commi...@chromium.org>
        Gerrit-CC: Tom Sepez <tse...@chromium.org>
        Gerrit-Comment-Date: Thu, 25 Jun 2020 21:04:18 +0000

        Lei Zhang (Gerrit)

        unread,
        Jun 25, 2020, 5:05:40 PM6/25/20
        to Miklos V, Lei Zhang, Chromium commit bot, Tom Sepez, pdfium-...@googlegroups.com

        LGTM! Thanks for addressing all the comments.

        Patch set 6:Code-Review +1

        View Change

          To view, visit change 70830. To unsubscribe, or for help writing mail filters, visit settings.

          Gerrit-Project: pdfium
          Gerrit-Branch: master
          Gerrit-Change-Id: I9b913521bd700bfadd8ca02f5c6fe49f7b63e31e
          Gerrit-Change-Number: 70830
          Gerrit-PatchSet: 6
          Gerrit-Owner: Miklos V <vmi...@collabora.co.uk>
          Gerrit-Reviewer: Lei Zhang <the...@chromium.org>
          Gerrit-CC: Chromium commit bot <commi...@chromium.org>
          Gerrit-CC: Tom Sepez <tse...@chromium.org>
          Gerrit-Comment-Date: Thu, 25 Jun 2020 21:05:38 +0000
          Gerrit-HasComments: No
          Gerrit-Has-Labels: Yes
          Gerrit-MessageType: comment

          Lei Zhang (Gerrit)

          unread,
          Jun 25, 2020, 5:31:47 PM6/25/20
          to Miklos V, Lei Zhang, Chromium commit bot, Tom Sepez, pdfium-...@googlegroups.com

          Patch set 6:Commit-Queue +2

          View Change

            To view, visit change 70830. To unsubscribe, or for help writing mail filters, visit settings.

            Gerrit-Project: pdfium
            Gerrit-Branch: master
            Gerrit-Change-Id: I9b913521bd700bfadd8ca02f5c6fe49f7b63e31e
            Gerrit-Change-Number: 70830
            Gerrit-PatchSet: 6
            Gerrit-Owner: Miklos V <vmi...@collabora.co.uk>
            Gerrit-Reviewer: Lei Zhang <the...@chromium.org>
            Gerrit-CC: Chromium commit bot <commi...@chromium.org>
            Gerrit-CC: Tom Sepez <tse...@chromium.org>
            Gerrit-Comment-Date: Thu, 25 Jun 2020 21:31:44 +0000

            Chromium commit bot (Gerrit)

            unread,
            Jun 25, 2020, 5:35:29 PM6/25/20
            to Miklos V, Lei Zhang, Tom Sepez, pdfium-...@googlegroups.com

            Chromium commit bot submitted this change.

            View Change

            Approvals: Lei Zhang: Looks good to me; Commit
            Add FPDF_GetSignatureCount() API

            This is the first step towards exposing enough information about digital
            signatures so that client code (not pdfium itself) can evaluate if they
            are valid or not.

            Change-Id: I9b913521bd700bfadd8ca02f5c6fe49f7b63e31e
            Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/70830
            Reviewed-by: Lei Zhang <the...@chromium.org>
            Commit-Queue: Lei Zhang <the...@chromium.org>
            ---
            M BUILD.gn
            M fpdfsdk/BUILD.gn
            A fpdfsdk/fpdf_signature.cpp
            A fpdfsdk/fpdf_signature_embeddertest.cpp
            M fpdfsdk/fpdf_view_c_api_test.c
            A public/fpdf_signature.h
            A testing/resources/two_signatures.in
            A testing/resources/two_signatures.pdf
            8 files changed, 444 insertions(+), 0 deletions(-)

            diff --git a/BUILD.gn b/BUILD.gn
            index 5bcb9cb..8bfe0ca55 100644
            --- a/BUILD.gn
            +++ b/BUILD.gn
            @@ -122,6 +122,7 @@
            "public/fpdf_progressive.h",
            "public/fpdf_save.h",
            "public/fpdf_searchex.h",
            + "public/fpdf_signature.h",
            "public/fpdf_structtree.h",
            "public/fpdf_sysfontinfo.h",
            "public/fpdf_text.h",
            diff --git a/fpdfsdk/BUILD.gn b/fpdfsdk/BUILD.gn
            index 081152e..93cfe5c 100644
            --- a/fpdfsdk/BUILD.gn
            +++ b/fpdfsdk/BUILD.gn
            @@ -62,6 +62,7 @@
            "fpdf_progressive.cpp",
            "fpdf_save.cpp",
            "fpdf_searchex.cpp",
            + "fpdf_signature.cpp",
            "fpdf_structtree.cpp",
            "fpdf_sysfontinfo.cpp",
            "fpdf_text.cpp",
            @@ -145,6 +146,7 @@
            "fpdf_ppo_embeddertest.cpp",
            "fpdf_save_embeddertest.cpp",
            "fpdf_searchex_embeddertest.cpp",
            + "fpdf_signature_embeddertest.cpp",
            "fpdf_structtree_embeddertest.cpp",
            "fpdf_sysfontinfo_embeddertest.cpp",
            "fpdf_text_embeddertest.cpp",
            diff --git a/fpdfsdk/fpdf_signature.cpp b/fpdfsdk/fpdf_signature.cpp
            new file mode 100644
            index 0000000..0d898ef
            --- /dev/null
            +++ b/fpdfsdk/fpdf_signature.cpp
            @@ -0,0 +1,38 @@
            +// Copyright 2020 PDFium Authors. All rights reserved.
            +// Use of this source code is governed by a BSD-style license that can be
            +// found in the LICENSE file.
            +
            +#include "public/fpdf_signature.h"
            +
            +#include "core/fpdfapi/parser/cpdf_array.h"
            +#include "core/fpdfapi/parser/cpdf_dictionary.h"
            +#include "core/fpdfapi/parser/cpdf_document.h"
            +#include "fpdfsdk/cpdfsdk_helpers.h"
            +
            +FPDF_EXPORT int FPDF_CALLCONV FPDF_GetSignatureCount(FPDF_DOCUMENT document) {
            + auto* doc = CPDFDocumentFromFPDFDocument(document);
            + if (!doc)
            + return -1;
            +
            + CPDF_Dictionary* root = doc->GetRoot();
            + if (!root)
            + return 0;
            +
            + const CPDF_Dictionary* acro_form = root->GetDictFor("AcroForm");
            + if (!acro_form)
            + return 0;
            +
            + const CPDF_Array* fields = acro_form->GetArrayFor("Fields");
            + if (!fields)
            + return 0;
            +
            + int signature_count = 0;
            + CPDF_ArrayLocker locker(fields);
            + for (const auto& field : locker) {
            + const CPDF_Dictionary* field_dict = field->GetDict();
            + if (field_dict && field_dict->GetNameFor("FT") == "Sig")
            + ++signature_count;
            + }
            +
            + return signature_count;
            +}
            diff --git a/fpdfsdk/fpdf_signature_embeddertest.cpp b/fpdfsdk/fpdf_signature_embeddertest.cpp
            new file mode 100644
            index 0000000..fb8bb3a
            --- /dev/null
            +++ b/fpdfsdk/fpdf_signature_embeddertest.cpp
            @@ -0,0 +1,21 @@
            +// Copyright 2020 PDFium Authors. All rights reserved.
            +// Use of this source code is governed by a BSD-style license that can be
            +// found in the LICENSE file.
            +
            +#include "public/fpdf_signature.h"
            +#include "testing/embedder_test.h"
            +
            +class FPDFSignatureEmbedderTest : public EmbedderTest {};
            +
            +TEST_F(FPDFSignatureEmbedderTest, GetSignatureCount) {
            + EXPECT_TRUE(OpenDocument("two_signatures.pdf"));
            + EXPECT_EQ(2, FPDF_GetSignatureCount(document()));
            +}
            +
            +TEST_F(FPDFSignatureEmbedderTest, GetSignatureCountZero) {
            + EXPECT_TRUE(OpenDocument("hello_world.pdf"));
            + EXPECT_EQ(0, FPDF_GetSignatureCount(document()));
            +
            + // Provide no document.
            + EXPECT_EQ(-1, FPDF_GetSignatureCount(nullptr));
            +}
            diff --git a/fpdfsdk/fpdf_view_c_api_test.c b/fpdfsdk/fpdf_view_c_api_test.c
            index f76d3d2..d04d1f8 100644
            --- a/fpdfsdk/fpdf_view_c_api_test.c
            +++ b/fpdfsdk/fpdf_view_c_api_test.c
            @@ -24,6 +24,7 @@
            #include "public/fpdf_progressive.h"
            #include "public/fpdf_save.h"
            #include "public/fpdf_searchex.h"
            +#include "public/fpdf_signature.h"
            #include "public/fpdf_structtree.h"
            #include "public/fpdf_sysfontinfo.h"
            #include "public/fpdf_text.h"
            @@ -314,6 +315,9 @@
            CHK(FPDFText_GetCharIndexFromTextIndex);
            CHK(FPDFText_GetTextIndexFromCharIndex);

            + // fpdf_signature.h
            + CHK(FPDF_GetSignatureCount);
            +
            // fpdf_structtree.h
            CHK(FPDF_StructElement_CountChildren);
            CHK(FPDF_StructElement_GetAltText);
            diff --git a/public/fpdf_signature.h b/public/fpdf_signature.h
            new file mode 100644
            index 0000000..7290bcb
            --- /dev/null
            +++ b/public/fpdf_signature.h
            @@ -0,0 +1,28 @@
            +// Copyright 2020 PDFium Authors. All rights reserved.
            +// Use of this source code is governed by a BSD-style license that can be
            +// found in the LICENSE file.
            +
            +#ifndef PUBLIC_FPDF_SIGNATURE_H_
            +#define PUBLIC_FPDF_SIGNATURE_H_
            +
            +// NOLINTNEXTLINE(build/include)
            +#include "fpdfview.h"
            +
            +#ifdef __cplusplus
            +extern "C" {
            +#endif // __cplusplus
            +
            +// Experimental API.
            +// Function: FPDF_GetSignatureCount
            +// Get total number of signatures in the document.
            +// Parameters:
            +// document - Handle to document. Returned by FPDF_LoadDocument().
            +// Return value:
            +// Total number of signatures in the document on success, -1 on error.
            +FPDF_EXPORT int FPDF_CALLCONV FPDF_GetSignatureCount(FPDF_DOCUMENT document);
            +
            +#ifdef __cplusplus
            +} // extern "C"
            +#endif // __cplusplus
            +
            +#endif // PUBLIC_FPDF_SIGNATURE_H_
            diff --git a/testing/resources/two_signatures.in b/testing/resources/two_signatures.in
            new file mode 100644
            index 0000000..f18495f
            --- /dev/null
            +++ b/testing/resources/two_signatures.in
            @@ -0,0 +1,155 @@
            +{{header}}
            +{{object 1 0}} <<
            + /Type /Catalog
            + /Pages 2 0 R
            +>>
            +endobj
            +{{object 2 0}} <<
            + /Type /Pages
            + /MediaBox [0 0 200 300]
            + /Count 1
            + /Kids [3 0 R]
            +>>
            +endobj
            +{{object 3 0}} <<
            + /Type /Page
            + /Parent 2 0 R
            + /Contents 4 0 R
            +>>
            +endobj
            +{{object 4 0}} <<
            + {{streamlen}}
            +>>
            +stream
            +q
            +0 0 0 rg
            +0 290 10 10 re B*
            +10 150 50 30 re B*
            +0 0 1 rg
            +190 290 10 10 re B*
            +70 232 50 30 re B*
            +0 1 0 rg
            +190 0 10 10 re B*
            +130 150 50 30 re B*
            +1 0 0 rg
            +0 0 10 10 re B*
            +70 67 50 30 re B*
            +Q
            +endstream
            +endobj
            +{{xref}}
            +{{trailer}}
            +{{startxref}}
            +%%EOF
            +
            +%% First incremental update adds an initial signature and update objects to
            +%% refer to it.
            +{{object 1 0}} <<
            + /Type /Catalog
            + /Pages 2 0 R
            + /AcroForm <<
            + /Fields [7 0 R]
            + /SigFlags 3
            + >>
            +>>
            +endobj
            +{{object 3 0}} <<
            + /Type /Page
            + /Parent 2 0 R
            + /Contents 4 0 R
            + /Annots [7 0 R]
            +>>
            +endobj
            +%% ByteRange is a pairs of integers (starting byte offset, length in bytes)
            +{{object 5 0}} <<
            + /Type /Sig
            + /Filter /Adobe.PPKMS
            + /SubFilter /ETSI.CAdES.detached
            + /ByteRange [0 10 30 10]
            + /Contents <308006092A864886F70D010702A0803080020101>
            + /M (D:20200624093114+02'00')
            +>>
            +endobj
            +{{object 6 0}} <<
            + /Type /XObject
            + /Subtype /Form
            + /BBox [0 0 0 0]
            + /Length 0
            +>>
            +stream
            +endstream
            +endobj
            +{{object 7 0}} <<
            + /Type /Annot
            + /Subtype /Widget
            + /FT /Sig
            + /F 132
            + /Rect [0 0 0 0]
            + /P 3 0 R
            + /T (Signature1)
            + /V 5 0 R
            + /DV 5 0 R
            + /AP <<
            + /N 6 0 R
            + >>
            +>>
            +endobj
            +{{xref}}
            +{{trailer}}
            +{{startxref}}
            +%%EOF
            +
            +%% Second incremental update adds a next signature and update objects once again to refer to it.
            +{{object 1 0}} <<
            + /Type /Catalog
            + /Pages 2 0 R
            + /AcroForm <<
            + /Fields [7 0 R 10 0 R]
            + /SigFlags 3
            + >>
            +>>
            +endobj
            +{{object 3 0}} <<
            + /Type /Page
            + /Parent 2 0 R
            + /Contents 4 0 R
            + /Annots [7 0 R 10 0 R]
            +>>
            +endobj
            +{{object 8 0}} <<
            + /Type /Sig
            + /Filter /Adobe.PPKMS
            + /SubFilter /ETSI.CAdES.detached
            + /ByteRange [0 40 50 10]
            + /Contents <308006092A864886F70D010702A080308002010131>
            + /M (D:20200624093118+02'00')
            +>>
            +endobj
            +{{object 9 0}} <<
            + /Type /XObject
            + /Subtype /Form
            + /BBox [0 0 0 0]
            + /Length 0
            +>>
            +stream
            +endstream
            +endobj
            +{{object 10 0}} <<
            + /Type /Annot
            + /Subtype /Widget
            + /FT /Sig
            + /F 132
            + /Rect [0 0 0 0]
            + /P 3 0 R
            + /T (Signature2)
            + /V 8 0 R
            + /DV 8 0 R
            + /AP <<
            + /N 9 0 R
            + >>
            +>>
            +endobj
            +{{xref}}
            +{{trailer}}
            +{{startxref}}
            +%%EOF
            diff --git a/testing/resources/two_signatures.pdf b/testing/resources/two_signatures.pdf
            new file mode 100644
            index 0000000..9a033d6
            --- /dev/null
            +++ b/testing/resources/two_signatures.pdf
            @@ -0,0 +1,195 @@
            +%PDF-1.7
            +% ò¤ô
            +1 0 obj <<
            + /Type /Catalog
            + /Pages 2 0 R
            +>>
            +endobj
            +2 0 obj <<
            + /Type /Pages
            + /MediaBox [0 0 200 300]
            + /Count 1
            + /Kids [3 0 R]
            +>>
            +endobj
            +3 0 obj <<
            + /Type /Page
            + /Parent 2 0 R
            + /Contents 4 0 R
            +>>
            +endobj
            +4 0 obj <<
            + /Length 188
            +>>
            +stream
            +q
            +0 0 0 rg
            +0 290 10 10 re B*
            +10 150 50 30 re B*
            +0 0 1 rg
            +190 290 10 10 re B*
            +70 232 50 30 re B*
            +0 1 0 rg
            +190 0 10 10 re B*
            +130 150 50 30 re B*
            +1 0 0 rg
            +0 0 10 10 re B*
            +70 67 50 30 re B*
            +Q
            +endstream
            +endobj
            +xref
            +0 5
            +0000000000 65535 f
            +0000000015 00000 n
            +0000000068 00000 n
            +0000000157 00000 n
            +0000000226 00000 n
            +trailer <<
            + /Root 1 0 R
            + /Size 5
            +>>
            +startxref
            +466
            +%%EOF
            +
            +%% First incremental update adds an initial signature and update objects to
            +%% refer to it.
            +1 0 obj <<
            + /Type /Catalog
            + /Pages 2 0 R
            + /AcroForm <<
            + /Fields [7 0 R]
            + /SigFlags 3
            + >>
            +>>
            +endobj
            +3 0 obj <<
            + /Type /Page
            + /Parent 2 0 R
            + /Contents 4 0 R
            + /Annots [7 0 R]
            +>>
            +endobj
            +%% ByteRange is a pairs of integers (starting byte offset, length in bytes)
            +5 0 obj <<
            + /Type /Sig
            + /Filter /Adobe.PPKMS
            + /SubFilter /ETSI.CAdES.detached
            + /ByteRange [0 10 30 10]
            + /Contents <308006092A864886F70D010702A0803080020101>
            + /M (D:20200624093114+02'00')
            +>>
            +endobj
            +6 0 obj <<
            + /Type /XObject
            + /Subtype /Form
            + /BBox [0 0 0 0]
            + /Length 0
            +>>
            +stream
            +endstream
            +endobj
            +7 0 obj <<
            + /Type /Annot
            + /Subtype /Widget
            + /FT /Sig
            + /F 132
            + /Rect [0 0 0 0]
            + /P 3 0 R
            + /T (Signature1)
            + /V 5 0 R
            + /DV 5 0 R
            + /AP <<
            + /N 6 0 R
            + >>
            +>>
            +endobj
            +xref
            +0 8
            +0000000000 65535 f
            +0000000726 00000 n
            +0000000068 00000 n
            +0000000835 00000 n
            +0000000226 00000 n
            +0000000998 00000 n
            +0000001201 00000 n
            +0000001303 00000 n
            +trailer <<
            + /Root 1 0 R
            + /Size 8
            +>>
            +startxref
            +1475
            +%%EOF
            +
            +%% Second incremental update adds a next signature and update objects once again to refer to it.
            +1 0 obj <<
            + /Type /Catalog
            + /Pages 2 0 R
            + /AcroForm <<
            + /Fields [7 0 R 10 0 R]
            + /SigFlags 3
            + >>
            +>>
            +endobj
            +3 0 obj <<
            + /Type /Page
            + /Parent 2 0 R
            + /Contents 4 0 R
            + /Annots [7 0 R 10 0 R]
            +>>
            +endobj
            +8 0 obj <<
            + /Type /Sig
            + /Filter /Adobe.PPKMS
            + /SubFilter /ETSI.CAdES.detached
            + /ByteRange [0 40 50 10]
            + /Contents <308006092A864886F70D010702A080308002010131>
            + /M (D:20200624093118+02'00')
            +>>
            +endobj
            +9 0 obj <<
            + /Type /XObject
            + /Subtype /Form
            + /BBox [0 0 0 0]
            + /Length 0
            +>>
            +stream
            +endstream
            +endobj
            +10 0 obj <<
            + /Type /Annot
            + /Subtype /Widget
            + /FT /Sig
            + /F 132
            + /Rect [0 0 0 0]
            + /P 3 0 R
            + /T (Signature2)
            + /V 8 0 R
            + /DV 8 0 R
            + /AP <<
            + /N 9 0 R
            + >>
            +>>
            +endobj
            +xref
            +0 11
            +0000000000 65535 f
            +0000001801 00000 n
            +0000000068 00000 n
            +0000001917 00000 n
            +0000000226 00000 n
            +0000000998 00000 n
            +0000001201 00000 n
            +0000001303 00000 n
            +0000002011 00000 n
            +0000002216 00000 n
            +0000002318 00000 n
            +trailer <<
            + /Root 1 0 R
            + /Size 11
            +>>
            +startxref
            +2491
            +%%EOF

            To view, visit change 70830. To unsubscribe, or for help writing mail filters, visit settings.

            Gerrit-Project: pdfium
            Gerrit-Branch: master
            Gerrit-Change-Id: I9b913521bd700bfadd8ca02f5c6fe49f7b63e31e
            Gerrit-Change-Number: 70830
            Gerrit-PatchSet: 7
            Gerrit-Owner: Miklos V <vmi...@collabora.co.uk>
            Gerrit-Reviewer: Chromium commit bot <commi...@chromium.org>
            Gerrit-Reviewer: Lei Zhang <the...@chromium.org>
            Gerrit-CC: Tom Sepez <tse...@chromium.org>
            Gerrit-MessageType: merged
            Reply all
            Reply to author
            Forward
            0 new messages