aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Lenz <thomas.lenz@a-sit.at>2026-01-13 13:11:04 +0000
committerThomas Lenz <thomas.lenz@a-sit.at>2026-01-13 13:11:04 +0000
commit26c64ac5e251d359c8ca958150e76b0d9f0da78f (patch)
tree06b5631a2fef6403178ac23a39e1234ce45c0309
parent6fb0555f4af1c0cd18713562e2e8609da82c3b72 (diff)
parent485e89f588a61b30f2aa2cb1d4e3406fce8d2bb8 (diff)
downloadpdf-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.java100
-rw-r--r--pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox2/PADESPDFBOXSigner.java7
-rw-r--r--pdf-as-pdfbox-2/src/test/java/at/gv/egiz/pdfas/lib/testpdfbox/PDFBoxPlaceholderExtractorTest.java2
-rw-r--r--pdf-as-pdfbox-2/src/test/java/at/gv/egiz/pdfas/lib/testpdfbox/SignatureFieldsAndPlaceHolderExtractorTest.java20
-rw-r--r--pdf-as-pdfbox-2/src/test/resources/new_qr_2_signed.pdfbin225097 -> 267402 bytes
-rw-r--r--pdf-as-pdfbox-2/src/test/resources/new_qr_2_signed_signed.pdfbin267093 -> 352501 bytes
-rw-r--r--pdf-as-pdfbox-2/src/test/resources/new_qr_2_signed_signed_signed.pdfbin310607 -> 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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ