From 504b663c8f14805cf9d00efc54e3a1b7bd104e25 Mon Sep 17 00:00:00 2001 From: Christoph Reiter <reiter.christoph@gmail.com> Date: Thu, 7 Jan 2021 13:02:02 +0100 Subject: [PATCH] Add a funtion for guessing the signature count of a PDF file We require the signature count in the future to force users to do a manual positioning when there are already signatures in the file since we can't add a new page for them. This uses a simple regex, matching parts of the signatures we use (PAdES). In case the result is wrong, worst case the user has to do extra work by positioning or the auto positioning will put it at the top of the first page, which might not be ideal, but the document is still signed either way. --- src/dbp-pdf-preview.js | 3 +++ src/utils.js | 33 +++++++++++++++++++++++++++++++++ test/unit.js | 22 ++++++++++++++++++++++ 3 files changed, 58 insertions(+) diff --git a/src/dbp-pdf-preview.js b/src/dbp-pdf-preview.js index edc2409..301ad03 100644 --- a/src/dbp-pdf-preview.js +++ b/src/dbp-pdf-preview.js @@ -10,6 +10,7 @@ import * as commonStyles from '@dbp-toolkit/common/styles'; import pdfjs from 'pdfjs-dist/es5/build/pdf.js'; import buildinfo from 'consts:buildinfo'; import {name as pkgName} from './../package.json'; +import {getPDFSignatureCount} from './utils.js'; const i18n = createI18nInstance(); @@ -238,6 +239,8 @@ export class PdfPreview extends ScopedElementsMixin(DBPLitElement) { }; reader.readAsBinaryString(file); + + console.log(`Signature count: ${await getPDFSignatureCount(file)}`); } getSignatureRect() { diff --git a/src/utils.js b/src/utils.js index 615b2ae..ea75b14 100644 --- a/src/utils.js +++ b/src/utils.js @@ -80,3 +80,36 @@ export const fabricjs2pdfasPosition = (data) => { p: data.currentPage }; }; + +/** + * Given a PDF file returns the amount of signatures found in it. + * + * Note that this uses an heuristic, so the result can be wrong + * (improvements welcome). + * + * @param {File} file The PDF file object + * @returns {number} The amount of signatures found + */ +export const getPDFSignatureCount = async (file) => { + const sigRegex = new RegExp( + "/Type\\s*/Sig\\s*/Filter\\s*/Adobe.PPKLite\\s*/SubFilter\\s*(/ETSI\\.CAdES\\.detached|/adbe\\.pkcs7\\.detached)", + "g"); + + const promise = new Promise((resolve, reject) => { + let reader = new FileReader(); + reader.onload = async () => { + let result = reader.result; + let matches = 0; + while (sigRegex.exec(result) !== null) { + matches++; + } + resolve(matches); + }; + reader.onerror = async () => { + reject(reader.error); + }; + reader.readAsBinaryString(file); + }); + + return promise; +}; \ No newline at end of file diff --git a/test/unit.js b/test/unit.js index 611333e..6038335 100644 --- a/test/unit.js +++ b/test/unit.js @@ -2,6 +2,7 @@ import {assert} from 'chai'; import '../src/dbp-official-signature-pdf-upload'; import '../src/dbp-signature.js'; +import {getPDFSignatureCount} from '../src/utils.js'; suite('dbp-official-signature-pdf-upload basics', () => { let node; @@ -39,3 +40,24 @@ suite('dbp-signature-app basics', () => { }); }); +suite('pdf signature detection', () => { + + function getPDFFile(data) { + return new File([new Blob([data])], 'test.pdf', {type: 'application/pdf'}); + } + + test('getPDFSignatureCount', async () => { + let sig1 = "/Type\n/Sig\n/Filter\n/Adobe.PPKLite\n/SubFilter\n/ETSI.CAdES.detached"; + let sig2 = "/Type\n/Sig\n/Filter\n/Adobe.PPKLite\n/SubFilter\n/adbe.pkcs7.detached"; + + assert(await getPDFSignatureCount(getPDFFile(sig1)) === 1); + assert(await getPDFSignatureCount(getPDFFile(sig2)) === 1); + assert(await getPDFSignatureCount(getPDFFile(sig1 + sig2)) === 2); + assert(await getPDFSignatureCount(getPDFFile("foo" + sig1 + "bar" + sig2 + "quux")) === 2); + assert(await getPDFSignatureCount(getPDFFile("\nfoo" + sig1 + "bar\n")) === 1); + assert(await getPDFSignatureCount(getPDFFile("\nfoo" + sig2 + "bar\n")) === 1); + + assert(await getPDFSignatureCount(getPDFFile("foobar")) === 0); + assert(await getPDFSignatureCount(getPDFFile("")) === 0); + }); +}); -- GitLab