diff options
| author | Thomas Lenz <thomas.lenz@a-sit.at> | 2026-01-13 13:11:04 +0000 |
|---|---|---|
| committer | Thomas Lenz <thomas.lenz@a-sit.at> | 2026-01-13 13:11:04 +0000 |
| commit | 26c64ac5e251d359c8ca958150e76b0d9f0da78f (patch) | |
| tree | 06b5631a2fef6403178ac23a39e1234ce45c0309 | |
| parent | 6fb0555f4af1c0cd18713562e2e8609da82c3b72 (diff) | |
| parent | 485e89f588a61b30f2aa2cb1d4e3406fce8d2bb8 (diff) | |
| download | pdf-as-4-26c64ac5e251d359c8ca958150e76b0d9f0da78f.tar.gz pdf-as-4-26c64ac5e251d359c8ca958150e76b0d9f0da78f.tar.bz2 pdf-as-4-26c64ac5e251d359c8ca958150e76b0d9f0da78f.zip | |
Merge branch 'feature/placeholder_fix' into 'development'
chore(placeholder): store placeholderId in a different location within the signature dictionary
See merge request egiz/pdf-as-4!12
| -rw-r--r-- | pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/placeholder/SignaturePlaceholderExtractor.java | 100 | ||||
| -rw-r--r-- | pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox2/PADESPDFBOXSigner.java | 7 | ||||
| -rw-r--r-- | pdf-as-pdfbox-2/src/test/java/at/gv/egiz/pdfas/lib/testpdfbox/PDFBoxPlaceholderExtractorTest.java | 2 | ||||
| -rw-r--r-- | pdf-as-pdfbox-2/src/test/java/at/gv/egiz/pdfas/lib/testpdfbox/SignatureFieldsAndPlaceHolderExtractorTest.java | 20 | ||||
| -rw-r--r-- | pdf-as-pdfbox-2/src/test/resources/new_qr_2_signed.pdf | bin | 225097 -> 267402 bytes | |||
| -rw-r--r-- | pdf-as-pdfbox-2/src/test/resources/new_qr_2_signed_signed.pdf | bin | 267093 -> 352501 bytes | |||
| -rw-r--r-- | pdf-as-pdfbox-2/src/test/resources/new_qr_2_signed_signed_signed.pdf | bin | 310607 -> 437946 bytes |
7 files changed, 103 insertions, 26 deletions
diff --git a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/placeholder/SignaturePlaceholderExtractor.java b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/placeholder/SignaturePlaceholderExtractor.java index 7cff90d6..8716603b 100644 --- a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/placeholder/SignaturePlaceholderExtractor.java +++ b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/placeholder/SignaturePlaceholderExtractor.java @@ -55,6 +55,7 @@ import java.util.Collections; import java.util.Hashtable; import java.util.List; import java.util.Map.Entry; +import java.util.Objects; import java.util.Properties; import java.util.Set; import java.util.Vector; @@ -64,11 +65,15 @@ import org.apache.pdfbox.contentstream.PDFStreamEngine; import org.apache.pdfbox.contentstream.operator.Operator; import org.apache.pdfbox.contentstream.operator.OperatorProcessor; import org.apache.pdfbox.cos.COSBase; +import org.apache.pdfbox.cos.COSDictionary; import org.apache.pdfbox.cos.COSName; +import org.apache.pdfbox.cos.COSObject; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.graphics.PDXObject; import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject; +import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDPropBuild; +import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDPropBuildDataDict; import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature; import org.apache.pdfbox.util.Matrix; @@ -101,6 +106,8 @@ import lombok.extern.slf4j.Slf4j; @Slf4j public class SignaturePlaceholderExtractor extends PDFStreamEngine implements PlaceholderExtractorConstants { + public static final String PREFIX = "PDF-AS_"; + private final List<SignaturePlaceholderData> placeholders = new ArrayList<>(); private int currentPage = 0; @@ -235,11 +242,11 @@ public class SignaturePlaceholderExtractor extends PDFStreamEngine implements Pl final String posString = "p:" + currentPage + ";x:" + Math.floor(x) + ";y:" + Math.ceil(y) + ";w:" + Math.ceil(w); - - log.debug("Found Placeholder at: {}", posString); + try { data.setTablePos(new TablePos(posString)); - data.setPlaceholderName(objectName.getName()); + data.setPlaceholderName(buildUniqueObjectName(objectName)); + log.debug("Found Placeholder at: {}", data.toString()); placeholders.add(data); } catch (final PdfAsException e) { @@ -256,6 +263,62 @@ public class SignaturePlaceholderExtractor extends PDFStreamEngine implements Pl } } + /** + * Read placeholderId from signature. + * + * @param signature Signature + * @return placeholderId or <code>null</code> if there is no placeholderId. + */ + private static String readPlaceHolderId(PDSignature signature) { + PDPropBuild sigProps = getOrNew(signature); + PDPropBuildDataDict appProps = getOrNew(sigProps); + return appProps.getName() != null && appProps.getName().startsWith(PREFIX) + ? appProps.getName().substring(PREFIX.length()) + : appProps.getName(); + + } + + /** + * Set a placeholderId into signature directory. + * + * @param signature Signature + * @param placeholderId placeholderId + */ + public static void setPlaceholderId(PDSignature signature, String placeholderId) { + PDPropBuild sigProps = getOrNew(signature); + PDPropBuildDataDict appProps = getOrNew(sigProps); + appProps.setName(PREFIX + placeholderId); + sigProps.setPDPropBuildApp(appProps); + signature.setPropBuild(sigProps); + + } + + /** + * Builds unique placeholderId from PDF element. + * + * @param name PDF element name + * @return unique identifier + */ + private String buildUniqueObjectName(COSName name) + { + COSDictionary dict = getResources().getCOSObject().getCOSDictionary(COSName.XOBJECT); + if (dict == null) + { + return name.getName(); + + } + + COSBase base = dict.getItem(name); + if (base instanceof COSObject) + { + return name.getName() + "_" + String.valueOf(((COSObject) base).getObjectNumber()); + + } + + return name.getName(); + + } + private SignaturePlaceholderData matchPlaceholderPage( List<SignaturePlaceholderData> placeholders, String placeholderId, int matchMode) { log.debug("Searching requested placeholder:{} with matchMode:{} in single page ... ", placeholderId, matchMode); @@ -382,19 +445,32 @@ public class SignaturePlaceholderExtractor extends PDFStreamEngine implements Pl } } + + + private static final PDPropBuildDataDict getOrNew(PDPropBuild sigProps) { + PDPropBuildDataDict props = sigProps.getApp(); + return props != null ? props : new PDPropBuildDataDict(); + } + + private static final PDPropBuild getOrNew(PDSignature signature) { + PDPropBuild sigProps = signature.getPropBuild(); + return sigProps != null ? sigProps : new PDPropBuild(); + + } + private List<String> existingExistingSignatureNames(PDDocument doc) { - final List<String> existingLocations = new ArrayList<>(); try { - final List<PDSignature> pdSignatureList = doc.getSignatureDictionaries(); - if (pdSignatureList.size() != 0) { - for (final PDSignature sig : pdSignatureList) { - existingLocations.add(sig.getLocation()); - } - } + final List<PDSignature> pdSignatureList = doc.getSignatureDictionaries(); + return pdSignatureList.stream() + .map(el -> readPlaceHolderId(el)) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + } catch (final IOException e) { - e.printStackTrace(); + log.warn("Can not parse signature dictionaries", e); + return Collections.emptyList(); + } - return existingLocations; } private List<SignaturePlaceholderData> removeAlreadyUsePlaceholders( diff --git a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox2/PADESPDFBOXSigner.java b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox2/PADESPDFBOXSigner.java index abbe7c8e..d8a25a9a 100644 --- a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox2/PADESPDFBOXSigner.java +++ b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox2/PADESPDFBOXSigner.java @@ -85,6 +85,7 @@ import at.gv.egiz.pdfas.lib.impl.ErrorExtractor; import at.gv.egiz.pdfas.lib.impl.SignaturePositionImpl; import at.gv.egiz.pdfas.lib.impl.configuration.SignatureProfileConfiguration; import at.gv.egiz.pdfas.lib.impl.pdfbox2.PDFBOXObject; +import at.gv.egiz.pdfas.lib.impl.pdfbox2.placeholder.SignaturePlaceholderExtractor; import at.gv.egiz.pdfas.lib.impl.pdfbox2.positioning.Positioning; import at.gv.egiz.pdfas.lib.impl.pdfbox2.utils.PdfBoxUtils; import at.gv.egiz.pdfas.lib.impl.placeholder.PlaceholderFilter; @@ -163,9 +164,9 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { pdfObject.getStatus().getSignParamter().getPlaceHolderId()); if (nextPlaceholderData != null) { - log.info("Placeholder data found."); - signature.setLocation(nextPlaceholderData.getPlaceholderName()); - + log.info("Placeholder data found. Injection placeholderId ..."); + SignaturePlaceholderExtractor.setPlaceholderId(signature, nextPlaceholderData.getPlaceholderName()); + if (nextPlaceholderData.getProfile() != null) { if (pdfObject.getStatus().getSettings().isValue(IConfigurationConstants.PLACEHOLDER_PROFILE_OVERWRITE, true)) { log.debug("Placeholder Profile set to: {}", nextPlaceholderData.getProfile()); diff --git a/pdf-as-pdfbox-2/src/test/java/at/gv/egiz/pdfas/lib/testpdfbox/PDFBoxPlaceholderExtractorTest.java b/pdf-as-pdfbox-2/src/test/java/at/gv/egiz/pdfas/lib/testpdfbox/PDFBoxPlaceholderExtractorTest.java index 80e3eb4d..d0c215ae 100644 --- a/pdf-as-pdfbox-2/src/test/java/at/gv/egiz/pdfas/lib/testpdfbox/PDFBoxPlaceholderExtractorTest.java +++ b/pdf-as-pdfbox-2/src/test/java/at/gv/egiz/pdfas/lib/testpdfbox/PDFBoxPlaceholderExtractorTest.java @@ -21,7 +21,7 @@ public class PDFBoxPlaceholderExtractorTest { @SneakyThrows public void nextPlaceholder() { SignaturePlaceholderData result = getNextSignaturePlaceHolder("/data/platzhalter_en_de_test.pdf"); - assertEquals("Im48", result.getPlaceholderName()); + assertEquals("Im48_48", result.getPlaceholderName()); } diff --git a/pdf-as-pdfbox-2/src/test/java/at/gv/egiz/pdfas/lib/testpdfbox/SignatureFieldsAndPlaceHolderExtractorTest.java b/pdf-as-pdfbox-2/src/test/java/at/gv/egiz/pdfas/lib/testpdfbox/SignatureFieldsAndPlaceHolderExtractorTest.java index 0ed05eb5..2e5e475c 100644 --- a/pdf-as-pdfbox-2/src/test/java/at/gv/egiz/pdfas/lib/testpdfbox/SignatureFieldsAndPlaceHolderExtractorTest.java +++ b/pdf-as-pdfbox-2/src/test/java/at/gv/egiz/pdfas/lib/testpdfbox/SignatureFieldsAndPlaceHolderExtractorTest.java @@ -29,12 +29,12 @@ public class SignatureFieldsAndPlaceHolderExtractorTest { @Test public void notSigned(){ SignaturePlaceholderData result = getNextSignaturePlaceHolder(getPath("new_qr_2-2.pdf")); - Assert.assertEquals("Image5",result.getPlaceholderName()); + Assert.assertEquals("Image5_5",result.getPlaceholderName()); } @Test public void signedOnce(){ SignaturePlaceholderData result = getNextSignaturePlaceHolder(getPath("new_qr_2_signed.pdf")); - Assert.assertEquals("Image8",result.getPlaceholderName()); + Assert.assertEquals("Image8_8",result.getPlaceholderName()); } @Test public void signedTwice(){ @@ -56,7 +56,7 @@ public class SignatureFieldsAndPlaceHolderExtractorTest { @Test public void firstQrCodeOnUnsignedDoc() { SignaturePlaceholderData result = getNextSignaturePlaceHolder(getPath("new_qr_2-2.pdf")); - Assert.assertEquals("Image5",result.getPlaceholderName()); + Assert.assertEquals("Image5_5",result.getPlaceholderName()); } @@ -66,28 +66,28 @@ public class SignatureFieldsAndPlaceHolderExtractorTest { Assert.assertEquals(null,result); result = getNextSignaturePlaceHolder(getPath("new_qr_2_signed.pdf")); - Assert.assertEquals("Image8",result.getPlaceholderName()); + Assert.assertEquals("Image8_8",result.getPlaceholderName()); result = getNextSignaturePlaceHolder(getPath("new_qr_2-2.pdf")); - Assert.assertEquals("Image5",result.getPlaceholderName()); + Assert.assertEquals("Image5_5",result.getPlaceholderName()); result = getNextSignaturePlaceHolder(getPath("new_qr_2-2.pdf")); - Assert.assertEquals("Image5",result.getPlaceholderName()); + Assert.assertEquals("Image5_5",result.getPlaceholderName()); result = getNextSignaturePlaceHolder(getPath("new_qr_2-2.pdf")); - Assert.assertEquals("Image5",result.getPlaceholderName()); + Assert.assertEquals("Image5_5",result.getPlaceholderName()); result = getNextSignaturePlaceHolder(getPath("new_qr_2_signed.pdf")); - Assert.assertEquals("Image8",result.getPlaceholderName()); + Assert.assertEquals("Image8_8",result.getPlaceholderName()); result = getNextSignaturePlaceHolder(getPath("new_qr_2_signed_signed_signed.pdf")); Assert.assertEquals(null,result); result = getNextSignaturePlaceHolder(getPath("new_qr_2-2.pdf")); - Assert.assertEquals("Image5",result.getPlaceholderName()); + Assert.assertEquals("Image5_5",result.getPlaceholderName()); result = getNextSignaturePlaceHolder(getPath("new_qr_2_signed.pdf")); - Assert.assertEquals("Image8",result.getPlaceholderName()); + Assert.assertEquals("Image8_8",result.getPlaceholderName()); } @Test public void notSignedAndNoFields(){ diff --git a/pdf-as-pdfbox-2/src/test/resources/new_qr_2_signed.pdf b/pdf-as-pdfbox-2/src/test/resources/new_qr_2_signed.pdf Binary files differindex be6fdddb..c3a53b23 100644 --- a/pdf-as-pdfbox-2/src/test/resources/new_qr_2_signed.pdf +++ b/pdf-as-pdfbox-2/src/test/resources/new_qr_2_signed.pdf diff --git a/pdf-as-pdfbox-2/src/test/resources/new_qr_2_signed_signed.pdf b/pdf-as-pdfbox-2/src/test/resources/new_qr_2_signed_signed.pdf Binary files differindex ee0f140f..1b831a73 100644 --- a/pdf-as-pdfbox-2/src/test/resources/new_qr_2_signed_signed.pdf +++ b/pdf-as-pdfbox-2/src/test/resources/new_qr_2_signed_signed.pdf diff --git a/pdf-as-pdfbox-2/src/test/resources/new_qr_2_signed_signed_signed.pdf b/pdf-as-pdfbox-2/src/test/resources/new_qr_2_signed_signed_signed.pdf Binary files differindex 34769dd0..6468ada7 100644 --- a/pdf-as-pdfbox-2/src/test/resources/new_qr_2_signed_signed_signed.pdf +++ b/pdf-as-pdfbox-2/src/test/resources/new_qr_2_signed_signed_signed.pdf |
