diff options
author | Thomas <> | 2023-06-26 21:11:51 +0200 |
---|---|---|
committer | Thomas <> | 2023-06-26 21:11:51 +0200 |
commit | 8c0dbe2fe66df35108c0d5ef137465779d55ad11 (patch) | |
tree | 0e1c545cf4cf1e2be2637ae06ec37a75f7ea19dc | |
parent | 8e0ccca7cfd1680e33737e0db8d6e1091661568c (diff) | |
download | pdf-as-4-8c0dbe2fe66df35108c0d5ef137465779d55ad11.tar.gz pdf-as-4-8c0dbe2fe66df35108c0d5ef137465779d55ad11.tar.bz2 pdf-as-4-8c0dbe2fe66df35108c0d5ef137465779d55ad11.zip |
refact(core): pdfBox signer refactoring
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) |