aboutsummaryrefslogtreecommitdiff
path: root/pdf-as-pdfbox-2/src/main/java
diff options
context:
space:
mode:
authorThomas <>2023-06-26 21:11:51 +0200
committerThomas <>2023-06-26 21:11:51 +0200
commit8c0dbe2fe66df35108c0d5ef137465779d55ad11 (patch)
tree0e1c545cf4cf1e2be2637ae06ec37a75f7ea19dc /pdf-as-pdfbox-2/src/main/java
parent8e0ccca7cfd1680e33737e0db8d6e1091661568c (diff)
downloadpdf-as-4-8c0dbe2fe66df35108c0d5ef137465779d55ad11.tar.gz
pdf-as-4-8c0dbe2fe66df35108c0d5ef137465779d55ad11.tar.bz2
pdf-as-4-8c0dbe2fe66df35108c0d5ef137465779d55ad11.zip
refact(core): pdfBox signer refactoring
Diffstat (limited to 'pdf-as-pdfbox-2/src/main/java')
-rw-r--r--pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/positioning/Positioning.java3
-rw-r--r--pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox2/PADESPDFBOXSigner.java493
2 files changed, 227 insertions, 269 deletions
diff --git a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/positioning/Positioning.java b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/positioning/Positioning.java
index 31de6446..491a6f31 100644
--- a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/positioning/Positioning.java
+++ b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/positioning/Positioning.java
@@ -66,7 +66,6 @@ public class Positioning {
*
* @param pos The absolute positioning parameter. If null it is
* sought in the profile definition.
- * @param signature_type The profile definition of the table to be written.
* @param pdfDataSource The pdf.
* @param pdf_table The pdf table to be written.
* @param settings
@@ -75,7 +74,7 @@ public class Positioning {
* @throws PdfAsException F.e.
*/
public static PositioningInstruction determineTablePositioning(
- TablePos pos, String signature_type, PDDocument pdfDataSource,
+ TablePos pos, PDDocument pdfDataSource,
IPDFVisualObject pdf_table, ISettings settings, SignatureProfileSettings signatureProfileSettings) throws PdfAsException {
return adjustSignatureTableandCalculatePosition(pdfDataSource,
pdf_table, pos, settings, signatureProfileSettings);
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 e555cb39..575fbc47 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
@@ -115,7 +115,6 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants {
public void signPDF(PDFObject genericPdfObject, RequestedSignature requestedSignature,
PDFASSignatureInterface genericSigner) throws PdfAsException {
- PDFAsVisualSignatureProperties properties = null;
boolean isAdobeSigForm = false;
@@ -132,8 +131,6 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants {
final PDFBOXObject pdfObject = (PDFBOXObject) genericPdfObject;
final PDFASPDFBOXSignatureInterface signer = (PDFASPDFBOXSignatureInterface) genericSigner;
- String pdfaVersion = null;
-
PDDocument doc = null;
SignatureOptions options = new SignatureOptions();
try {
@@ -152,19 +149,23 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants {
}
+ // set basic signature parameters
signature.setFilter(COSName.getPDFName(signer.getPDFFilter()));
signature.setSubFilter(COSName.getPDFName(signer.getPDFSubFilter()));
+ signature.setSignDate(Calendar.getInstance());
+ log.debug("Signing @ " + signature.getSignDate().getTime().toString());
-
- String placeholder_id = pdfObject.getStatus().getSignParamter().getPlaceHolderId();
-
+ // extract next QR-code placeholder, if exists
SignaturePlaceholderData nextPlaceholderData = PlaceholderFilter.checkPlaceholderSignatureLocation(
- pdfObject.getStatus(), pdfObject.getStatus().getSettings(), placeholder_id);
+ pdfObject.getStatus(), pdfObject.getStatus().getSettings(),
+ pdfObject.getStatus().getSignParamter().getPlaceHolderId());
if (nextPlaceholderData != null) {
log.info("Placeholder data found.");
signature.setLocation(nextPlaceholderData.getPlaceholderName());
-
+
+
+ // TODO: only over-write if requested
if (nextPlaceholderData.getProfile() != null) {
log.debug("Placeholder Profile set to: {}", nextPlaceholderData.getProfile());
requestedSignature.setSignatureProfileID(nextPlaceholderData.getProfile());
@@ -173,92 +174,49 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants {
}
- final SignatureProfileSettings signatureProfileSettings = TableFactory.createProfile(
- requestedSignature.getSignatureProfileID(), pdfObject.getStatus().getSettings());
-
- // Check if input document is PDF-A conform
- if (signatureProfileSettings.isPDFA()) {
- final DataSource origDoc = pdfObject.getOriginalDocument();
- final InputStream stream = origDoc.getInputStream();
- // Run PreflightParser for checking conformity//
- // runPDFAPreflight(origDoc);
- }
+ final SignatureProfileSettings signatureProfileSettings =
+ TableFactory.createProfile(requestedSignature.getSignatureProfileID(), pdfObject.getStatus().getSettings());
+
+ // set signature name
final ValueResolver resolver = new ValueResolver(requestedSignature, pdfObject.getStatus());
-
- final String signerName = resolver.resolve("SIG_SUBJECT", signatureProfileSettings.getValue(
- "SIG_SUBJECT"),
- signatureProfileSettings);
-
+ final String signerName = resolver.resolve("SIG_SUBJECT",
+ signatureProfileSettings.getValue("SIG_SUBJECT"), signatureProfileSettings);
signature.setName(signerName);
- signature.setSignDate(Calendar.getInstance());
- String signerReason = signatureProfileSettings.getSigningReason();
-
- if (signerReason == null) {
- signerReason = "PAdES Signature";
- }
+ // set signature reason
+ String signerReason = signatureProfileSettings.getSigningReason() != null
+ ? signatureProfileSettings.getSigningReason() : "PAdES Signature";
signature.setReason(signerReason);
log.debug("Signing reason: " + signerReason);
-
-
- log.debug("Signing @ " + signer.getSigningDate().getTime().toString());
- // the signing date, needed for valid signature
- // signature.setSignDate(signer.getSigningDate());
-
signer.setPDSignature(signature);
- int signatureSize = 0x1000;
- try {
- final String reservedSignatureSizeString = signatureProfileSettings.getValue(SIG_RESERVED_SIZE);
- if (reservedSignatureSizeString != null) {
- signatureSize = Integer.parseInt(reservedSignatureSizeString);
- }
- log.debug("Reserving {} bytes for signature", signatureSize);
- } catch (final NumberFormatException e) {
- log.warn("Invalid configuration value: {} should be a number using 0x1000", SIG_RESERVED_SIZE);
- }
- options.setPreferredSignatureSize(signatureSize);
-
+
if (signatureProfileSettings.isPDFA() || signatureProfileSettings.isPDFA3()) {
- pdfaVersion = getPDFAVersion(doc);
- signatureProfileSettings.setPDFAVersion(pdfaVersion);
+ signatureProfileSettings.setPDFAVersion(getPDFAVersion(doc));
+
}
- // Is visible Signature
+ // prepare basic signature options
+ options.setPreferredSignatureSize(calculateBlankAreaForSignature(signatureProfileSettings));
+
+
+ PDFAsVisualSignatureProperties properties = null;
if (requestedSignature.isVisual()) {
log.info("Creating visual siganture block");
final SignatureProfileConfiguration signatureProfileConfiguration =
pdfObject.getStatus().getSignatureProfileConfiguration(requestedSignature.getSignatureProfileID());
- TablePos tablePos = prepareTablePosition(nextPlaceholderData, signatureProfileConfiguration,
+ final TablePos tablePos = prepareTablePosition(nextPlaceholderData, signatureProfileConfiguration,
pdfObject.getStatus().getSignParamter().getSignaturePosition());
-
-
-
- // Legacy Modes not supported with pdfbox2 anymore
-// boolean legacy32Position = signatureProfileConfiguration.getLegacy32Positioning();
-// boolean legacy40Position = signatureProfileConfiguration.getLegacy40Positioning();
-
- // create Table describtion
-
final Table main = TableFactory.createSigTable(signatureProfileSettings, MAIN, pdfObject.getStatus(),
requestedSignature);
final IPDFStamper stamper = StamperFactory.createDefaultStamper(pdfObject.getStatus().getSettings());
-
final IPDFVisualObject visualObject = stamper.createVisualPDFObject(pdfObject, main);
- /*
- * PDDocument originalDocument = PDDocument .load(new
- * ByteArrayInputStream(pdfObject.getStatus()
- * .getPdfObject().getOriginalDocument()));
- */
-
final PositioningInstruction positioningInstruction = Positioning.determineTablePositioning(tablePos,
- "",
doc, visualObject, pdfObject.getStatus().getSettings(), signatureProfileSettings);
-
log.debug("Positioning: {}", positioningInstruction.toString());
if (!isAdobeSigForm) {
@@ -289,44 +247,11 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants {
position.setWidth(visualObject.getWidth());
requestedSignature.setSignaturePosition(position);
}
-
+
properties = new PDFAsVisualSignatureProperties(pdfObject.getStatus().getSettings(), pdfObject,
(PdfBoxVisualObject) visualObject, positioningInstruction, signatureProfileSettings);
-
properties.buildSignature();
- /*
- * ByteArrayOutputStream sigbos = new ByteArrayOutputStream();
- * sigbos.write(StreamUtils.inputStreamToByteArray (properties
- * .getVisibleSignature())); sigbos.close();
- */
-
- /*
- * if (signaturePlaceholderData != null) {
- *
- * InputStream fis =
- * PADESPDFBOXSigner.class.getResourceAsStream("/placeholder/empty.jpg");
- * PDImageXObject img = JPEGFactory.createFromStream(doc, fis);
- *
- * img.getCOSObject().setNeedToBeUpdated(true); // PDDocumentCatalog root =
- * doc.getDocumentCatalog(); // PDPageNode rootPages = root.getPages(); //
- * List<PDPage> kids = new ArrayList<PDPage>(); // rootPages.getAllKids(kids);
- * int pageNumber = positioningInstruction.getPage(); PDPage page =
- * doc.getPages().get(pageNumber - 1);
- *
- * log.info("Placeholder name: " +
- * signaturePlaceholderData.getPlaceholderName()); COSDictionary
- * xobjectsDictionary = (COSDictionary) page.getResources().getCOSObject()
- * .getDictionaryObject(COSName.XOBJECT);
- *
- *
- * xobjectsDictionary.setItem(signaturePlaceholderData.getPlaceholderName(),
- * img); xobjectsDictionary.setNeedToBeUpdated(true);
- * page.getResources().getCOSObject().setNeedToBeUpdated(true);
- * log.info("Placeholder name: " +
- * signaturePlaceholderData.getPlaceholderName()); }
- */
-
if (signatureProfileSettings.isPDFA() || signatureProfileSettings.isPDFA3()) {
final PDDocumentCatalog root = doc.getDocumentCatalog();
@@ -350,37 +275,26 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants {
} catch (final Throwable e) {
e.printStackTrace();
throw new PdfAsException("Failed to add Output Intent", e);
+
} finally {
IOUtils.closeQuietly(colorProfile);
+
}
}
+
options.setPage(positioningInstruction.getPage() - 1);
options.setVisualSignature(properties.getVisibleSignature());
+
}
doc.addSignature(signature, signer, options);
-
- String sigFieldName = getSignatureFieldNameConfig(pdfObject);
- if (sigFieldName == null) {
- sigFieldName = "PDF-AS Signatur";
- }
- final int count = PdfBoxUtils.countSignatures(doc, sigFieldName);
-
- sigFieldName = sigFieldName + count;
-
- final PDAcroForm acroFormm = doc.getDocumentCatalog().getAcroForm();
-
- // PDStructureTreeRoot pdstRoot =
- // doc.getDocumentCatalog().getStructureTreeRoot();
- // COSDictionary dic =
- // doc.getDocumentCatalog().getCOSDictionary();
- // PDStructureElement el = new PDStructureElement("Widget",
- // pdstRoot);
-
+ String sigFieldName = buildNextSignatureFieldName(doc, pdfObject);
+
// this is not used for Adobe signature fields
if (!isAdobeSigForm) {
PDSignatureField signatureField = null;
+ final PDAcroForm acroFormm = doc.getDocumentCatalog().getAcroForm();
if (acroFormm != null) {
@SuppressWarnings("unchecked")
final List<PDField> fields = acroFormm.getFields();
@@ -416,6 +330,7 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants {
}
} else {
log.warn("Failed to name Signature Field! [Cannot find acroForm!]");
+
}
}
@@ -423,192 +338,235 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants {
final PDAcroForm acroForm = doc.getDocumentCatalog().getAcroForm();
if (acroForm != null) {
signatureField = (PDSignatureField) acroForm.getField(sigFieldName);
+
}
- // PDF-UA
- log.info("Adding pdf/ua content.");
- try {
- final PDDocumentCatalog root = doc.getDocumentCatalog();
- final PDStructureTreeRoot structureTreeRoot = root.getStructureTreeRoot();
- if (structureTreeRoot != null) {
- log.info("Tree Root: {}", structureTreeRoot.toString());
- final List<Object> kids = structureTreeRoot.getKids();
-
- if (kids == null) {
- log.info("No kid-elements in structure tree Root, maybe not PDF/UA document");
- }
- PDStructureElement docElement = null;
- for (final Object k : kids) {
- if (k instanceof PDStructureElement) {
- docElement = (PDStructureElement) k;
- break;
+ injectPdfUaContent(doc, signatureField, sigFieldName, signatureProfileSettings);
+
+ performTechnicalSignature(doc, pdfObject, signatureProfileSettings);
- }
+
+ log.debug("Signature done!");
+
+ } catch (final IOException e) {
+ log.warn(MessageResolver.resolveMessage("error.pdf.sig.01"), e);
+ throw new PdfAsException("error.pdf.sig.01", e);
+
+ } catch (PDFASError e2) {
+ log.warn(e2.getInfo());
+ throw new PdfAsException("error.pdf.sig.01", e2);
+
+ } finally {
+ if (options != null) {
+ if (options.getVisualSignature() != null) {
+ try {
+ options.getVisualSignature().close();
+ options.close();
+ } catch (IOException e) {
+ log.debug("Failed to close VisualSignature!", e);
}
+ }
+ }
+
+ if (doc != null) {
+ try {
+ doc.close();
+ // SignaturePlaceholderExtractor.getPlaceholders().clear();
+ } catch (final IOException e) {
+ log.debug("Failed to close COS Doc!", e);
+ // Ignore
+ }
+ }
+ }
+ }
- final PDStructureElement sigBlock = new PDStructureElement("Form", docElement);
+ private void performTechnicalSignature(PDDocument doc, PDFBOXObject pdfObject,
+ SignatureProfileSettings signatureProfileSettings) throws PdfAsException {
+ try {
+ final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ synchronized (doc) {
+ doc.saveIncremental(bos);
+ final byte[] outputDocument = bos.toByteArray();
+ pdfObject.setSignedDocument(outputDocument);
+ }
+ /* Check if resulting pdf is PDF-A conform */
+ if (signatureProfileSettings.isPDFA()) {
+ runPDFAPreflight(new ByteArrayDataSource(pdfObject.getSignedDocument()));
+ }
- // create object dictionary and add as child element
- final COSDictionary objectDic = new COSDictionary();
- objectDic.setName("Type", "OBJR");
+ } catch (final IOException e1) {
+ log.error("Can not save incremental update", e1);
- objectDic.setItem("Pg", signatureField.getWidget().getPage());
- objectDic.setItem("Obj", signatureField.getWidget());
+ }
+
+ System.gc();
+
+ }
- final List<Object> l = new ArrayList<>();
- l.add(objectDic);
- sigBlock.setKids(l);
- sigBlock.setPage(signatureField.getWidget().getPage());
+ private void injectPdfUaContent(PDDocument doc, PDSignatureField signatureField, String sigFieldName,
+ SignatureProfileSettings signatureProfileSettings) throws PdfAsException {
+ try {
+ log.info("Adding pdf/ua content .... ");
+ final PDDocumentCatalog root = doc.getDocumentCatalog();
+ final PDStructureTreeRoot structureTreeRoot = root.getStructureTreeRoot();
+ if (structureTreeRoot != null) {
+ log.info("Tree Root: {}", structureTreeRoot.toString());
+ final List<Object> kids = structureTreeRoot.getKids();
+
+ if (kids == null) {
+ log.info("No kid-elements in structure tree Root, maybe not PDF/UA document");
+ }
- sigBlock.setTitle("Signature Table");
- sigBlock.setParent(docElement);
- docElement.appendKid(sigBlock);
+ PDStructureElement docElement = null;
+ for (final Object k : kids) {
+ if (k instanceof PDStructureElement) {
+ docElement = (PDStructureElement) k;
+ break;
- // Create and add Attribute dictionary to mitigate PAC
- // warning
- final COSDictionary sigBlockDic = sigBlock.getCOSObject();
- final COSDictionary sub = new COSDictionary();
+ }
+ }
- sub.setName("O", "Layout");
- sub.setName("Placement", "Block");
- sigBlockDic.setItem(COSName.A, sub);
- sigBlockDic.setNeedToBeUpdated(true);
+ final PDStructureElement sigBlock = new PDStructureElement("Form", docElement);
- // Modify number tree
- PDNumberTreeNode ntn = structureTreeRoot.getParentTree();
- if (ntn == null) {
- ntn = new PDNumberTreeNode(objectDic, null);
- log.info("No number-tree-node found!");
- }
+ // create object dictionary and add as child element
+ final COSDictionary objectDic = new COSDictionary();
+ objectDic.setName("Type", "OBJR");
- final COSArray ntnKids = (COSArray) ntn.getCOSObject().getDictionaryObject(COSName.KIDS);
- final COSArray ntnNumbers = (COSArray) ntn.getCOSObject().getDictionaryObject(COSName.NUMS);
+ objectDic.setItem("Pg", signatureField.getWidget().getPage());
+ objectDic.setItem("Obj", signatureField.getWidget());
- final int parentTreeNextKey = getParentTreeNextKey(structureTreeRoot);
+ final List<Object> l = new ArrayList<>();
+ l.add(objectDic);
+ sigBlock.setKids(l);
+ sigBlock.setPage(signatureField.getWidget().getPage());
- if (ntnNumbers == null && ntnKids != null) {// no number array, so continue with the kids array
- // create dictionary with limits and nums array
- final COSDictionary pTreeEntry = new COSDictionary();
- final COSArray limitsArray = new COSArray();
- // limits for exact one entry
- limitsArray.add(COSInteger.get(parentTreeNextKey));
- limitsArray.add(COSInteger.get(parentTreeNextKey));
+ sigBlock.setTitle("Signature Table");
+ sigBlock.setParent(docElement);
+ docElement.appendKid(sigBlock);
- final COSArray numsArray = new COSArray();
- numsArray.add(COSInteger.get(parentTreeNextKey));
- numsArray.add(sigBlock);
+ // Create and add Attribute dictionary to mitigate PAC
+ // warning
+ final COSDictionary sigBlockDic = sigBlock.getCOSObject();
+ final COSDictionary sub = new COSDictionary();
- pTreeEntry.setItem(COSName.NUMS, numsArray);
- pTreeEntry.setItem(COSName.LIMITS, limitsArray);
+ sub.setName("O", "Layout");
+ sub.setName("Placement", "Block");
+ sigBlockDic.setItem(COSName.A, sub);
+ sigBlockDic.setNeedToBeUpdated(true);
- final PDNumberTreeNode newKidsElement = new PDNumberTreeNode(pTreeEntry, PDNumberTreeNode.class);
+ // Modify number tree
+ PDNumberTreeNode ntn = structureTreeRoot.getParentTree();
+ if (ntn == null) {
+ ntn = new PDNumberTreeNode(objectDic, null);
+ log.info("No number-tree-node found!");
+ }
- ntnKids.add(newKidsElement);
- ntnKids.setNeedToBeUpdated(true);
+ final COSArray ntnKids = (COSArray) ntn.getCOSObject().getDictionaryObject(COSName.KIDS);
+ final COSArray ntnNumbers = (COSArray) ntn.getCOSObject().getDictionaryObject(COSName.NUMS);
- } else if (ntnNumbers != null && ntnKids == null) {
+ final int parentTreeNextKey = getParentTreeNextKey(structureTreeRoot);
- final int arrindex = ntnNumbers.size();
+ if (ntnNumbers == null && ntnKids != null) {// no number array, so continue with the kids array
+ // create dictionary with limits and nums array
+ final COSDictionary pTreeEntry = new COSDictionary();
+ final COSArray limitsArray = new COSArray();
+ // limits for exact one entry
+ limitsArray.add(COSInteger.get(parentTreeNextKey));
+ limitsArray.add(COSInteger.get(parentTreeNextKey));
- ntnNumbers.add(arrindex, COSInteger.get(parentTreeNextKey));
- ntnNumbers.add(arrindex + 1, sigBlock.getCOSObject());
+ final COSArray numsArray = new COSArray();
+ numsArray.add(COSInteger.get(parentTreeNextKey));
+ numsArray.add(sigBlock);
- ntnNumbers.setNeedToBeUpdated(true);
+ pTreeEntry.setItem(COSName.NUMS, numsArray);
+ pTreeEntry.setItem(COSName.LIMITS, limitsArray);
- structureTreeRoot.setParentTree(ntn);
+ final PDNumberTreeNode newKidsElement = new PDNumberTreeNode(pTreeEntry, PDNumberTreeNode.class);
- } else if (ntnNumbers == null && ntnKids == null) {
- // document is not pdfua conform before signature creation
- throw new PdfAsException("error.pdf.sig.pdfua.1");
- } else {
- // this is not allowed
- throw new PdfAsException("error.pdf.sig.pdfua.1");
- }
+ ntnKids.add(newKidsElement);
+ ntnKids.setNeedToBeUpdated(true);
- // set StructureParent for signature field annotation
- signatureField.getWidget().setStructParent(parentTreeNextKey);
+ } else if (ntnNumbers != null && ntnKids == null) {
- // Increase the next Key value in the structure tree root
- structureTreeRoot.setParentTreeNextKey(parentTreeNextKey + 1);
+ final int arrindex = ntnNumbers.size();
- // add the Tabs /S Element for Tabbing through annots
- final PDPage p = signatureField.getWidget().getPage();
- p.getCOSObject().setName("Tabs", "S");
- p.getCOSObject().setNeedToBeUpdated(true);
+ ntnNumbers.add(arrindex, COSInteger.get(parentTreeNextKey));
+ ntnNumbers.add(arrindex + 1, sigBlock.getCOSObject());
- // check alternative signature field name
- if (signatureField != null) {
- if (signatureField.getAlternateFieldName().equals("")) {
- signatureField.setAlternateFieldName(sigFieldName);
- }
- }
+ ntnNumbers.setNeedToBeUpdated(true);
- ntn.getCOSObject().setNeedToBeUpdated(true);
- sigBlock.getCOSObject().setNeedToBeUpdated(true);
- structureTreeRoot.getCOSObject().setNeedToBeUpdated(true);
- objectDic.setNeedToBeUpdated(true);
- docElement.getCOSObject().setNeedToBeUpdated(true);
- }
- } catch (final Throwable e) {
- if (signatureProfileSettings.isPDFUA() == true) {
- log.error("Could not create PDF-UA conform document!");
- throw new PdfAsException("error.pdf.sig.pdfua.1", e);
+ structureTreeRoot.setParentTree(ntn);
+
+ } else if (ntnNumbers == null && ntnKids == null) {
+ // document is not pdfua conform before signature creation
+ throw new PdfAsException("error.pdf.sig.pdfua.1");
} else {
- log.info("Could not create PDF-UA conform signature");
+ // this is not allowed
+ throw new PdfAsException("error.pdf.sig.pdfua.1");
}
- }
- try {
- final ByteArrayOutputStream bos = new ByteArrayOutputStream();
- synchronized (doc) {
- doc.saveIncremental(bos);
- final byte[] outputDocument = bos.toByteArray();
- pdfObject.setSignedDocument(outputDocument);
- }
- /* Check if resulting pdf is PDF-A conform */
- if (signatureProfileSettings.isPDFA()) {
- runPDFAPreflight(new ByteArrayDataSource(pdfObject.getSignedDocument()));
- }
+ // set StructureParent for signature field annotation
+ signatureField.getWidget().setStructParent(parentTreeNextKey);
- } catch (final IOException e1) {
- log.error("Can not save incremental update", e1);
+ // Increase the next Key value in the structure tree root
+ structureTreeRoot.setParentTreeNextKey(parentTreeNextKey + 1);
- }
-
- System.gc();
- log.debug("Signature done!");
-
- } catch (final IOException e) {
- log.warn(MessageResolver.resolveMessage("error.pdf.sig.01"), e);
- throw new PdfAsException("error.pdf.sig.01", e);
-
- } catch (PDFASError e2) {
- log.warn(e2.getInfo());
- throw new PdfAsException("error.pdf.sig.01", e2);
-
- } finally {
- if (options != null) {
- if (options.getVisualSignature() != null) {
- try {
- options.getVisualSignature().close();
- options.close();
- } catch (IOException e) {
- log.debug("Failed to close VisualSignature!", e);
+ // add the Tabs /S Element for Tabbing through annots
+ final PDPage p = signatureField.getWidget().getPage();
+ p.getCOSObject().setName("Tabs", "S");
+ p.getCOSObject().setNeedToBeUpdated(true);
+
+ // check alternative signature field name
+ if (signatureField != null) {
+ if (signatureField.getAlternateFieldName().equals("")) {
+ signatureField.setAlternateFieldName(sigFieldName);
}
}
+
+ ntn.getCOSObject().setNeedToBeUpdated(true);
+ sigBlock.getCOSObject().setNeedToBeUpdated(true);
+ structureTreeRoot.getCOSObject().setNeedToBeUpdated(true);
+ objectDic.setNeedToBeUpdated(true);
+ docElement.getCOSObject().setNeedToBeUpdated(true);
}
+ } catch (final Throwable e) {
+ if (signatureProfileSettings.isPDFUA()) {
+ log.error("Could not create PDF-UA conform document!");
+ throw new PdfAsException("error.pdf.sig.pdfua.1", e);
+
+ } else {
+ log.info("Could not create PDF-UA conform signature");
+ }
+ }
+
+ }
+
+ private String buildNextSignatureFieldName(PDDocument doc, PDFBOXObject pdfObject) {
+ String sigFieldName = getSignatureFieldNameConfig(pdfObject);
+ if (sigFieldName == null) {
+ sigFieldName = "PDF-AS Signatur";
- if (doc != null) {
- try {
- doc.close();
- // SignaturePlaceholderExtractor.getPlaceholders().clear();
- } catch (final IOException e) {
- log.debug("Failed to close COS Doc!", e);
- // Ignore
- }
+ }
+ return sigFieldName + PdfBoxUtils.countSignatures(doc, sigFieldName);
+
+ }
+
+ private int calculateBlankAreaForSignature(SignatureProfileSettings signatureProfileSettings) {
+ int signatureSize = 0x1000;
+ try {
+ final String reservedSignatureSizeString = signatureProfileSettings.getValue(SIG_RESERVED_SIZE);
+ if (reservedSignatureSizeString != null) {
+ signatureSize = Integer.parseInt(reservedSignatureSizeString);
}
+ log.debug("Reserving {} bytes for signature", signatureSize);
+
+ } catch (final NumberFormatException e) {
+ log.warn("Invalid configuration value: {} should be a number using 0x1000", SIG_RESERVED_SIZE);
+
}
+
+ return signatureSize;
}
private TablePos prepareTablePosition(SignaturePlaceholderData nextPlaceholderData,
@@ -796,10 +754,10 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants {
final String signaturePosString = signatureProfileConfiguration.getDefaultPositioning();
PositioningInstruction positioningInstruction;
if (signaturePosString != null) {
- positioningInstruction = Positioning.determineTablePositioning(new TablePos(signaturePosString), "",
+ positioningInstruction = Positioning.determineTablePositioning(new TablePos(signaturePosString),
origDoc, visualObject, pdfObject.getStatus().getSettings(), signatureProfileSettings);
} else {
- positioningInstruction = Positioning.determineTablePositioning(new TablePos(), "", origDoc,
+ positioningInstruction = Positioning.determineTablePositioning(new TablePos(), origDoc,
visualObject, pdfObject.getStatus().getSettings(), signatureProfileSettings);
}
@@ -907,6 +865,7 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants {
}
}
return signature;
+
}
static Map<Integer, COSObjectable> getNumberTreeAsMap(PDNumberTreeNode tree)