diff options
Diffstat (limited to 'pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PADESPDFBOXSigner.java')
-rw-r--r-- | pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PADESPDFBOXSigner.java | 353 |
1 files changed, 263 insertions, 90 deletions
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PADESPDFBOXSigner.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PADESPDFBOXSigner.java index 651c2e49..767887b3 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PADESPDFBOXSigner.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PADESPDFBOXSigner.java @@ -29,12 +29,21 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; import java.util.Calendar; +import java.util.List; +import org.apache.pdfbox.cos.COSDictionary; import org.apache.pdfbox.cos.COSName; import org.apache.pdfbox.exceptions.COSVisitorException; import org.apache.pdfbox.exceptions.SignatureException; import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.pdmodel.PDDocumentCatalog; +import org.apache.pdfbox.pdmodel.PDPage; +import org.apache.pdfbox.pdmodel.PDPageNode; +import org.apache.pdfbox.pdmodel.graphics.color.PDOutputIntent; +import org.apache.pdfbox.pdmodel.graphics.xobject.PDJpeg; import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature; import org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureOptions; import org.slf4j.Logger; @@ -45,111 +54,275 @@ import at.gv.egiz.pdfas.common.messages.MessageResolver; import at.gv.egiz.pdfas.common.settings.SignatureProfileSettings; import at.gv.egiz.pdfas.common.utils.StreamUtils; import at.gv.egiz.pdfas.common.utils.TempFileHelper; +import at.gv.egiz.pdfas.lib.api.IConfigurationConstants; +import at.gv.egiz.pdfas.lib.impl.SignaturePositionImpl; +import at.gv.egiz.pdfas.lib.impl.configuration.SignatureProfileConfiguration; +import at.gv.egiz.pdfas.lib.impl.placeholder.PlaceholderFilter; +import at.gv.egiz.pdfas.lib.impl.placeholder.SignaturePlaceholderData; +import at.gv.egiz.pdfas.lib.impl.positioning.Positioning; import at.gv.egiz.pdfas.lib.impl.signing.IPdfSigner; import at.gv.egiz.pdfas.lib.impl.signing.sig_interface.PDFASSignatureInterface; +import at.gv.egiz.pdfas.lib.impl.stamping.IPDFStamper; +import at.gv.egiz.pdfas.lib.impl.stamping.IPDFVisualObject; +import at.gv.egiz.pdfas.lib.impl.stamping.StamperFactory; import at.gv.egiz.pdfas.lib.impl.stamping.TableFactory; import at.gv.egiz.pdfas.lib.impl.stamping.ValueResolver; import at.gv.egiz.pdfas.lib.impl.stamping.pdfbox.PDFAsVisualSignatureProperties; +import at.gv.egiz.pdfas.lib.impl.stamping.pdfbox.PdfBoxVisualObject; import at.gv.egiz.pdfas.lib.impl.status.PDFObject; import at.gv.egiz.pdfas.lib.impl.status.RequestedSignature; +import at.knowcenter.wag.egov.egiz.pdf.PositioningInstruction; +import at.knowcenter.wag.egov.egiz.pdf.TablePos; +import at.knowcenter.wag.egov.egiz.table.Table; -public class PADESPDFBOXSigner implements IPdfSigner { +public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { - private static final Logger logger = LoggerFactory.getLogger(PADESPDFBOXSigner.class); + private static final Logger logger = LoggerFactory + .getLogger(PADESPDFBOXSigner.class); - public void signPDF(PDFObject pdfObject, RequestedSignature requestedSignature, - PDFASSignatureInterface signer) - throws PdfAsException { - String fisTmpFile = null; - - TempFileHelper helper = pdfObject.getStatus().getTempFileHelper(); - - try { - fisTmpFile = helper.getStaticFilename(); + public void signPDF(PDFObject pdfObject, + RequestedSignature requestedSignature, + PDFASSignatureInterface signer) throws PdfAsException { + String fisTmpFile = null; - // write to temporary file - FileOutputStream fos = new FileOutputStream(new File(fisTmpFile)); - fos.write(pdfObject.getStampedDocument()); + TempFileHelper helper = pdfObject.getStatus().getTempFileHelper(); + try { + fisTmpFile = helper.getStaticFilename(); - FileInputStream fis = new FileInputStream(new File(fisTmpFile)); + // write to temporary file + FileOutputStream fos = new FileOutputStream(new File(fisTmpFile)); + fos.write(pdfObject.getOriginalDocument()); - PDDocument doc = PDDocument.load( - new ByteArrayInputStream(pdfObject.getStampedDocument())); + FileInputStream fis = new FileInputStream(new File(fisTmpFile)); - PDSignature signature = new PDSignature(); - signature.setFilter(COSName.getPDFName(signer.getPDFFilter())); // default filter - signature.setSubFilter(COSName.getPDFName(signer.getPDFSubFilter())); + PDDocument doc = PDDocument.load(new ByteArrayInputStream(pdfObject + .getOriginalDocument())); - SignatureProfileSettings signatureProfileSettings = TableFactory - .createProfile(requestedSignature.getSignatureProfileID(), + PDSignature signature = new PDSignature(); + signature.setFilter(COSName.getPDFName(signer.getPDFFilter())); // default + // filter + signature + .setSubFilter(COSName.getPDFName(signer.getPDFSubFilter())); + + SignatureProfileSettings signatureProfileSettings = TableFactory + .createProfile(requestedSignature.getSignatureProfileID(), pdfObject.getStatus().getSettings()); - - ValueResolver resolver = new ValueResolver(); - String signerName = resolver.resolve("SIG_SUBJECT", signatureProfileSettings.getValue("SIG_SUBJECT"), - signatureProfileSettings, requestedSignature); - - signature.setName(signerName); - signature.setSignDate(Calendar.getInstance()); - String signerReason = signatureProfileSettings.getSigningReason(); - - if(signerReason == null) { - signerReason = "PAdES Signature"; - } - - signature.setReason(signerReason); - logger.debug("Signing reason: " + signerReason); - - logger.debug("Signing @ " + signer.getSigningDate().getTime().toString()); - // the signing date, needed for valid signature - //signature.setSignDate(signer.getSigningDate()); - - signer.setPDSignature(signature); - SignatureOptions options = new SignatureOptions(); - - // FOR DEVELOPING: Call custom visual signature creation - PDFAsVisualSignatureProperties properties = new PDFAsVisualSignatureProperties( - pdfObject.getStatus().getSettings(), pdfObject); - properties.buildSignature(); - - ByteArrayOutputStream sigbos = new ByteArrayOutputStream(); - sigbos.write(StreamUtils.inputStreamToByteArray(properties.getVisibleSignature())); - sigbos.close(); - - FileOutputStream fos2 = new FileOutputStream("/tmp/apsig.pdf"); - fos2.write(sigbos.toByteArray()); - fos2.close(); - - options.setVisualSignature(new ByteArrayInputStream(sigbos.toByteArray())); - - doc.addSignature(signature, signer, options); - - // pdfbox patched (FIS -> IS) - doc.saveIncremental(fis, fos); - fis.close(); - fos.close(); - - fis = new FileInputStream(new File(fisTmpFile)); - - // write to resulting output stream - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - bos.write(StreamUtils.inputStreamToByteArray(fis)); - fis.close(); - bos.close(); - - pdfObject.setSignedDocument(bos.toByteArray()); - - helper.deleteFile(fisTmpFile); - - } catch (IOException e) { - logger.error(MessageResolver.resolveMessage("error.pdf.sig.01"), e); - throw new PdfAsException("error.pdf.sig.01", e); - } catch(SignatureException e) { - logger.error(MessageResolver.resolveMessage("error.pdf.sig.01"), e); - throw new PdfAsException("error.pdf.sig.01", e); - } catch (COSVisitorException e) { - logger.error(MessageResolver.resolveMessage("error.pdf.sig.01"), e); - throw new PdfAsException("error.pdf.sig.01", e); - } - } + + ValueResolver resolver = new ValueResolver(); + String signerName = resolver.resolve("SIG_SUBJECT", + signatureProfileSettings.getValue("SIG_SUBJECT"), + signatureProfileSettings, requestedSignature); + + signature.setName(signerName); + signature.setSignDate(Calendar.getInstance()); + String signerReason = signatureProfileSettings.getSigningReason(); + + if (signerReason == null) { + signerReason = "PAdES Signature"; + } + + signature.setReason(signerReason); + logger.debug("Signing reason: " + signerReason); + + logger.debug("Signing @ " + + signer.getSigningDate().getTime().toString()); + // the signing date, needed for valid signature + // signature.setSignDate(signer.getSigningDate()); + + signer.setPDSignature(signature); + SignatureOptions options = new SignatureOptions(); + + // Is visible Signature + if (requestedSignature.isVisual()) { + logger.info("Creating visual siganture block"); + + SignatureProfileConfiguration signatureProfileConfiguration = pdfObject + .getStatus().getSignatureProfileConfiguration( + requestedSignature.getSignatureProfileID()); + + SignaturePlaceholderData signaturePlaceholderData = PlaceholderFilter + .checkPlaceholderSignature(pdfObject.getStatus(), + pdfObject.getStatus().getSettings()); + + TablePos tablePos = null; + + if (signaturePlaceholderData != null) { + // Placeholder found! + + if (signaturePlaceholderData.getProfile() != null) { + requestedSignature + .setSignatureProfileID(signaturePlaceholderData + .getProfile()); + } + + tablePos = signaturePlaceholderData.getTablePos(); + } + + if (tablePos == null) { + // ================================================================ + // PositioningStage (visual) -> find position or use fixed + // position + + String posString = pdfObject.getStatus().getSignParamter() + .getSignaturePosition(); + + if (posString == null) { + posString = signatureProfileConfiguration + .getDefaultPositioning(); + } + + logger.debug("using Positioning: " + posString); + + if (posString == null) { + tablePos = new TablePos(); + } else { + tablePos = new TablePos(posString); + } + } + boolean legacy32Position = signatureProfileConfiguration + .getLegacy32Positioning(); + + // create Table describtion + Table main = TableFactory.createSigTable( + signatureProfileSettings, MAIN, pdfObject.getStatus() + .getSettings(), requestedSignature); + + IPDFStamper stamper = StamperFactory + .createDefaultStamper(pdfObject.getStatus() + .getSettings()); + + IPDFVisualObject visualObject = stamper.createVisualPDFObject( + pdfObject, main); + + PDDocument originalDocument = PDDocument + .load(new ByteArrayInputStream(pdfObject.getStatus() + .getPdfObject().getOriginalDocument())); + + PositioningInstruction positioningInstruction = Positioning + .determineTablePositioning(tablePos, "", + originalDocument, visualObject, + legacy32Position); + + SignaturePositionImpl position = new SignaturePositionImpl(); + position.setX(positioningInstruction.getX()); + position.setY(positioningInstruction.getY()); + position.setPage(positioningInstruction.getPage()); + position.setHeight(visualObject.getHeight()); + position.setWidth(visualObject.getWidth()); + + requestedSignature.setSignaturePosition(position); + + PDFAsVisualSignatureProperties properties = new PDFAsVisualSignatureProperties( + pdfObject.getStatus().getSettings(), pdfObject, + (PdfBoxVisualObject) visualObject, + positioningInstruction); + + properties.buildSignature(); + + ByteArrayOutputStream sigbos = new ByteArrayOutputStream(); + sigbos.write(StreamUtils.inputStreamToByteArray(properties + .getVisibleSignature())); + sigbos.close(); + + FileOutputStream fos2 = new FileOutputStream("/tmp/apsig.pdf"); + fos2.write(sigbos.toByteArray()); + fos2.close(); + + if (signaturePlaceholderData != null) { + // Placeholder found! + // replace placeholder + InputStream is = PADESPDFBOXSigner.class + .getResourceAsStream("/placeholder/empty.jpg"); + PDJpeg img = new PDJpeg(doc, is); + img.getCOSObject().setNeedToBeUpdate(true); + + PDDocumentCatalog root = doc.getDocumentCatalog(); + PDPageNode rootPages = root.getPages(); + List<PDPage> kids = new ArrayList<PDPage>(); + rootPages.getAllKids(kids); + int pageNumber = positioningInstruction.getPage(); + rootPages.getAllKids(kids); + PDPage page = kids.get(pageNumber); + + logger.info("Placeholder name: " + signaturePlaceholderData.getPlaceholderName()); + COSDictionary xobjectsDictionary = (COSDictionary) page.findResources().getCOSDictionary() + .getDictionaryObject(COSName.XOBJECT); + xobjectsDictionary.setItem(signaturePlaceholderData.getPlaceholderName(), img); + xobjectsDictionary.setNeedToBeUpdate(true); + page.findResources().getCOSObject().setNeedToBeUpdate(true); + logger.info("Placeholder name: " + signaturePlaceholderData.getPlaceholderName()); + } + + if (positioningInstruction.isMakeNewPage()) { + int last = doc.getNumberOfPages() - 1; + PDDocumentCatalog root = doc.getDocumentCatalog(); + PDPageNode rootPages = root.getPages(); + List<PDPage> kids = new ArrayList<PDPage>(); + rootPages.getAllKids(kids); + PDPage lastPage = kids.get(last); + rootPages.getCOSObject().setNeedToBeUpdate(true); + PDPage p = new PDPage(lastPage.findMediaBox()); + + doc.addPage(p); + } + + if (signatureProfileSettings.isPDFA()) { + PDDocumentCatalog root = doc.getDocumentCatalog(); + InputStream colorProfile = PDDocumentCatalog.class + .getResourceAsStream("/icm/sRGB Color Space Profile.icm"); + try { + PDOutputIntent oi = new PDOutputIntent(doc, + colorProfile); + oi.setInfo("sRGB IEC61966-2.1"); + oi.setOutputCondition("sRGB IEC61966-2.1"); + oi.setOutputConditionIdentifier("sRGB IEC61966-2.1"); + oi.setRegistryName("http://www.color.org"); + + root.addOutputIntent(oi); + root.getCOSObject().setNeedToBeUpdate(true); + logger.info("added Output Intent"); + } catch (Throwable e) { + e.printStackTrace(); + throw new PdfAsException("Failed to add Output Intent", + e); + } + } + + options.setPreferedSignatureSize(0x1000); + options.setPage(positioningInstruction.getPage()); + options.setVisualSignature(new ByteArrayInputStream(sigbos + .toByteArray())); + } + + doc.addSignature(signature, signer, options); + + // pdfbox patched (FIS -> IS) + doc.saveIncremental(fis, fos); + fis.close(); + fos.close(); + + fis = new FileInputStream(new File(fisTmpFile)); + + // write to resulting output stream + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + bos.write(StreamUtils.inputStreamToByteArray(fis)); + fis.close(); + bos.close(); + + pdfObject.setSignedDocument(bos.toByteArray()); + + helper.deleteFile(fisTmpFile); + + } catch (IOException e) { + logger.error(MessageResolver.resolveMessage("error.pdf.sig.01"), e); + throw new PdfAsException("error.pdf.sig.01", e); + } catch (SignatureException e) { + logger.error(MessageResolver.resolveMessage("error.pdf.sig.01"), e); + throw new PdfAsException("error.pdf.sig.01", e); + } catch (COSVisitorException e) { + logger.error(MessageResolver.resolveMessage("error.pdf.sig.01"), e); + throw new PdfAsException("error.pdf.sig.01", e); + } + } } |