diff options
author | Andreas Fitzek <andreas.fitzek@iaik.tugraz.at> | 2014-03-13 08:52:46 +0100 |
---|---|---|
committer | Andreas Fitzek <andreas.fitzek@iaik.tugraz.at> | 2014-04-01 16:51:50 +0200 |
commit | 8d9cc698494694a57743c7443bf5e77d4e6c882b (patch) | |
tree | 6b7cf655ffdc0a8e92252adbf25ce5ae4fd41f1f /pdf-as-lib | |
parent | 78c7b6b82267b766b573046d722a55638749a6cd (diff) | |
download | pdf-as-4-8d9cc698494694a57743c7443bf5e77d4e6c882b.tar.gz pdf-as-4-8d9cc698494694a57743c7443bf5e77d4e6c882b.tar.bz2 pdf-as-4-8d9cc698494694a57743c7443bf5e77d4e6c882b.zip |
WIP: pdfbox table to Sign AP
Diffstat (limited to 'pdf-as-lib')
16 files changed, 699 insertions, 14 deletions
diff --git a/pdf-as-lib/build.gradle b/pdf-as-lib/build.gradle index 9e440fb8..81c53dce 100644 --- a/pdf-as-lib/build.gradle +++ b/pdf-as-lib/build.gradle @@ -41,7 +41,7 @@ dependencies { compile project (':pdf-as-common') compile group: 'org.apache.httpcomponents', name: 'httpmime', version: '4.3.1' compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.3.1' - compile group: 'org.apache.pdfbox', name: 'pdfbox', version: '1.8.2' + compile group: 'org.apache.pdfbox', name: 'pdfbox', version: '1.8.4' compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.1' compile group: 'org.apache.commons', name: 'commons-io', version: '1.3.2' compile group: 'commons-collections', name: 'commons-collections', version: '3.2' diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/PdfAsImpl.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/PdfAsImpl.java index a2ad3575..3fdfb576 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/PdfAsImpl.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/PdfAsImpl.java @@ -530,7 +530,7 @@ public class PdfAsImpl implements PdfAs, IConfigurationConstants { return; } - if (requestedSignature.isVisual()) { + if (requestedSignature.isVisual() && false) { logger.info("Creating visual siganture block"); // ================================================================ // SignBlockCreationStage (visual) -> create visual signature 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 d93ff5e1..93c19fe5 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 @@ -36,6 +36,7 @@ import org.apache.pdfbox.exceptions.COSVisitorException; import org.apache.pdfbox.exceptions.SignatureException; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature; +import org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureOptions; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -48,6 +49,7 @@ 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.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.status.PDFObject; import at.gv.egiz.pdfas.lib.impl.status.RequestedSignature; @@ -103,8 +105,15 @@ public class PADESPDFBOXSigner implements IPdfSigner { //signature.setSignDate(signer.getSigningDate()); signer.setPDSignature(signature); + SignatureOptions options = new SignatureOptions(); - doc.addSignature(signature, signer); + // FOR DEVELOPING: Call custom visual signature creation + PDFAsVisualSignatureProperties properties = new PDFAsVisualSignatureProperties( + pdfObject.getStatus().getSettings(), pdfObject); + properties.buildSignature(); + options.setVisualSignature(properties.getVisibleSignature()); + + doc.addSignature(signature, signer, options); // pdfbox patched (FIS -> IS) doc.saveIncremental(fis, fos); diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/CertificateResolver.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/CertificateResolver.java index 0aacb1b0..42f81f42 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/CertificateResolver.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/CertificateResolver.java @@ -37,6 +37,7 @@ import org.slf4j.LoggerFactory; import at.gv.egiz.pdfas.common.settings.SignatureProfileSettings; import at.gv.egiz.pdfas.common.utils.DNUtils; import at.gv.egiz.pdfas.common.utils.OgnlUtils; +import at.gv.egiz.pdfas.lib.impl.status.ICertificateProvider; import at.gv.egiz.pdfas.lib.impl.status.RequestedSignature; public class CertificateResolver implements IResolver { @@ -69,7 +70,7 @@ public class CertificateResolver implements IResolver { } public String resolve(String key, String value, SignatureProfileSettings settings, - RequestedSignature signature) { + ICertificateProvider signature) { return OgnlUtils.resolvsOgnlExpression(value, this.ctx); } diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/IResolver.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/IResolver.java index 4ba365fa..8c38039f 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/IResolver.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/IResolver.java @@ -24,6 +24,7 @@ package at.gv.egiz.pdfas.lib.impl.stamping; import at.gv.egiz.pdfas.common.settings.SignatureProfileSettings; +import at.gv.egiz.pdfas.lib.impl.status.ICertificateProvider; import at.gv.egiz.pdfas.lib.impl.status.RequestedSignature; /** @@ -35,5 +36,5 @@ import at.gv.egiz.pdfas.lib.impl.status.RequestedSignature; */ public interface IResolver { public String resolve(String key, String value, SignatureProfileSettings settings, - RequestedSignature signature); + ICertificateProvider signature); } diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/TableFactory.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/TableFactory.java index cbda8e95..038e9a88 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/TableFactory.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/TableFactory.java @@ -26,6 +26,7 @@ package at.gv.egiz.pdfas.lib.impl.stamping; import at.gv.egiz.pdfas.common.settings.IProfileConstants; import at.gv.egiz.pdfas.common.settings.ISettings; import at.gv.egiz.pdfas.common.settings.SignatureProfileSettings; +import at.gv.egiz.pdfas.lib.impl.status.ICertificateProvider; import at.gv.egiz.pdfas.lib.impl.status.RequestedSignature; import at.knowcenter.wag.egov.egiz.pdf.sig.SignatureEntry; import at.knowcenter.wag.egov.egiz.table.Entry; @@ -96,7 +97,7 @@ public class TableFactory implements IProfileConstants { * @see at.knowcenter.wag.egov.egiz.table.Entry */ public static Table createSigTable(SignatureProfileSettings profile, String tableID, ISettings configuration, - RequestedSignature requestedSignature) + ICertificateProvider certProvider) { String table_key_prefix = SIG_OBJ + profile.getProfileID() + "." + TABLE; String table_key = table_key_prefix + tableID; @@ -160,7 +161,7 @@ public class TableFactory implements IProfileConstants { if (TYPE_TABLE.equals(key)) { // add a table entry - Table table = createSigTable(profile, type, configuration, requestedSignature); + Table table = createSigTable(profile, type, configuration, certProvider); if (table != null) { Entry entry = new Entry(Entry.TYPE_TABLE, table, key); @@ -188,7 +189,7 @@ public class TableFactory implements IProfileConstants { ValueResolver resolver = new ValueResolver(); String value = profile.getValue(key); Entry entry = new Entry(Entry.TYPE_VALUE, - resolver.resolve(key, value, profile, requestedSignature), key); + resolver.resolve(key, value, profile, certProvider), key); if (entry != null) { entry.setColSpan(2); @@ -210,7 +211,7 @@ public class TableFactory implements IProfileConstants { c_entry.setStyle(defaultCaptionStyle_); ValueResolver resolver = new ValueResolver(); Entry v_entry = new Entry(Entry.TYPE_VALUE, - resolver.resolve(key, value, profile, requestedSignature), key); + resolver.resolve(key, value, profile, certProvider), key); v_entry.setStyle(defaultValueStyle_); if (c_entry != null && v_entry != null) { @@ -226,7 +227,7 @@ public class TableFactory implements IProfileConstants { ValueResolver resolver = new ValueResolver(); Entry v_entry = new Entry(Entry.TYPE_VALUE, - resolver.resolve(key, value, profile, requestedSignature), key); + resolver.resolve(key, value, profile, certProvider), key); v_entry.setStyle(defaultValueStyle_); if (c_entry != null && v_entry != null) { diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/ValueResolver.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/ValueResolver.java index dc24f40f..ebd5c962 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/ValueResolver.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/ValueResolver.java @@ -33,6 +33,7 @@ import org.slf4j.LoggerFactory; import at.gv.egiz.pdfas.common.settings.IProfileConstants; import at.gv.egiz.pdfas.common.settings.SignatureProfileSettings; +import at.gv.egiz.pdfas.lib.impl.status.ICertificateProvider; import at.gv.egiz.pdfas.lib.impl.status.RequestedSignature; /** @@ -52,7 +53,7 @@ public class ValueResolver implements IProfileConstants, IResolver { public static final String EXP_END = "}"; public String resolve(String key, String value, - SignatureProfileSettings settings, RequestedSignature signature) { + SignatureProfileSettings settings, ICertificateProvider certProvider) { logger.debug("Resolving value for key: " + key); logger.debug("Resolving value with value: " + value); @@ -72,7 +73,7 @@ public class ValueResolver implements IProfileConstants, IResolver { Pattern pattern = Pattern.compile(PatternRegex); Matcher matcher = pattern.matcher(value); CertificateResolver certificateResolver = new CertificateResolver( - signature.getCertificate()); + certProvider.getCertificate()); String result = ""; int curidx = 0; if (matcher.find()) { @@ -82,7 +83,7 @@ public class ValueResolver implements IProfileConstants, IResolver { result += value.substring(curidx, idx); curidx = idxe; result += certificateResolver.resolve(key, - matcher.group(1), settings, signature); + matcher.group(1), settings, certProvider); } while (matcher.find()); } else { result = value; diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureBuilder.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureBuilder.java new file mode 100644 index 00000000..496bc0d8 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureBuilder.java @@ -0,0 +1,173 @@ +package at.gv.egiz.pdfas.lib.impl.stamping.pdfbox; + +import java.io.IOException; +import java.util.ArrayList; + +import org.apache.pdfbox.cos.COSName; +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.pdmodel.PDPage; +import org.apache.pdfbox.pdmodel.common.PDStream; +import org.apache.pdfbox.pdmodel.edit.PDPageContentStream; +import org.apache.pdfbox.pdmodel.font.PDType1Font; +import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDVisibleSigBuilder; +import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDVisibleSignDesigner; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egiz.pdfas.lib.test.mains.TestPDFBoxTable; +import at.knowcenter.wag.egov.egiz.table.Entry; +import at.knowcenter.wag.egov.egiz.table.Table; + +public class PDFAsVisualSignatureBuilder extends PDVisibleSigBuilder { + + private static final Logger logger = LoggerFactory + .getLogger(TestPDFBoxTable.class); + + private static void drawTable(PDPage page, + PDPageContentStream contentStream, float x, float y, + Table abstractTable) throws IOException { + + final int rows = abstractTable.getRows().size(); + final int cols = abstractTable.getMaxCols(); + float[] colsSizes = abstractTable.getColsRelativeWith(); + int max_cols = abstractTable.getMaxCols(); + if (colsSizes == null) { + colsSizes = new float[max_cols]; + // set the column ratio for all columns to 1 + for (int cols_idx = 0; cols_idx < colsSizes.length; cols_idx++) { + colsSizes[cols_idx] = 1; + } + } + + logger.info("TOTAL Col: " + abstractTable.getWidth()); + + float total = 0; + + for (int cols_idx = 0; cols_idx < colsSizes.length; cols_idx++) { + total += colsSizes[cols_idx]; + } + + for (int cols_idx = 0; cols_idx < colsSizes.length; cols_idx++) { + colsSizes[cols_idx] = (colsSizes[cols_idx] / total) + * abstractTable.getWidth(); + } + + for (int cols_idx = 0; cols_idx < colsSizes.length; cols_idx++) { + logger.info("Col: " + cols_idx + " : " + colsSizes[cols_idx]); + } + + final float cellMargin = 5f; + final float rowHeight = 12f + 2 * cellMargin; + final float tableWidth = abstractTable.getWidth(); + final float tableHeight = rowHeight * rows; + final float colWidth = tableWidth / (float) cols; + + // draw the rows + float nexty = y; + for (int i = 0; i <= rows; i++) { + contentStream.drawLine(x, nexty, x + tableWidth, nexty); + nexty -= rowHeight; + } + + // draw the columns + float nextx = x; + for (int i = 0; i <= cols; i++) { + contentStream.drawLine(nextx, y, nextx, y - tableHeight); + if (i < colsSizes.length) { + nextx += (colsSizes != null) ? colsSizes[i] : colWidth; + } + } + + float textx = x + cellMargin; + float texty = y - 15; + for (int i = 0; i < abstractTable.getRows().size(); i++) { + ArrayList row = (ArrayList) abstractTable.getRows().get(i); + for (int j = 0; j < row.size(); j++) { + Entry cell = (Entry) row.get(j); + String text = cell.toString(); + text = "Hallo"; + COSName name = COSName.getPDFName("ANDI_TAG!"); + contentStream.beginMarkedContentSequence(COSName.ALT, name); + contentStream.beginText(); + logger.info("Writing: " + textx + " : " + texty + " = " + text); + contentStream.moveTextPositionByAmount(textx, texty); + + if (text.contains("\n")) { + String[] lines = text.split("\n"); + contentStream.appendRawCommands(10 + " TL\n"); + for (int k = 0; k < lines.length; k++) { + contentStream.drawString(lines[k]); + if (k < lines.length - 1) { + contentStream.appendRawCommands("T*\n"); + } + } + } else { + contentStream.drawString(text); + } + contentStream.endText(); + contentStream.endMarkedContentSequence(); + textx += (colsSizes != null) ? colsSizes[j] : colWidth; + } + texty -= rowHeight; + textx = x + cellMargin; + } + } + + private PDFAsVisualSignatureProperties properties; + + public PDFAsVisualSignatureBuilder(PDFAsVisualSignatureProperties properties) { + this.properties = properties; + } + + @Override + public void createTemplate(PDPage page) throws IOException { + PDDocument template = new PDDocument(); + + template.addPage(page); + getStructure().setTemplate(template); + } + + @Override + public void createInnerFormStream(PDDocument template) { + try { + PDPageContentStream stream = new PDPageContentStream(template, + getStructure().getPage()); + stream.setFont(PDType1Font.HELVETICA_BOLD, 12); + drawTable(getStructure().getPage(), stream, 0, 0, + properties.getMainTable()); + stream.close(); + PDStream innterFormStream = getStructure().getPage().getContents(); + getStructure().setInnterFormStream(innterFormStream); + logger.info("Strean of another form (inner form - it would be inside holder form) has been created"); + + } catch (Throwable e) { + e.printStackTrace(); + } + } + + @Override + public void injectAppearanceStreams(PDStream holderFormStream, PDStream innterFormStream, PDStream imageFormStream, + String imageObjectName, String imageName, String innerFormName, PDVisibleSignDesigner properties) + throws IOException + { + + // 100 means that document width is 100% via the rectangle. if rectangle + // is 500px, images 100% is 500px. + // String imgFormComment = "q "+imageWidthSize+ " 0 0 50 0 0 cm /" + + // imageName + " Do Q\n" + builder.toString(); + String imgFormComment = "q " + 100 + " 0 0 50 0 0 cm /" + imageName + " Do Q\n"; + String holderFormComment = "q 1 0 0 1 0 0 cm /" + innerFormName + " Do Q \n"; + String innerFormComment = "q 1 0 0 1 0 0 cm /" + imageObjectName + " Do Q\n"; + + logger.info("Holder Stream: " + getStructure().getInnterFormStream().getInputStreamAsString()); + + //appendRawCommands(getStructure().getInnterFormStream().createOutputStream(), + // getStructure().getInnterFormStream().getInputStreamAsString()); + + appendRawCommands(getStructure().getHolderFormStream().createOutputStream(), holderFormComment); + appendRawCommands(getStructure().getInnterFormStream().createOutputStream(), getStructure().getInnterFormStream().getInputStreamAsString()); + appendRawCommands(getStructure().getImageFormStream().createOutputStream(), imgFormComment); + logger.info("Injected apereance stream to pdf"); + + } +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureProperties.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureProperties.java new file mode 100644 index 00000000..a3d02db2 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureProperties.java @@ -0,0 +1,70 @@ +package at.gv.egiz.pdfas.lib.impl.stamping.pdfbox; + +import iaik.x509.X509Certificate; + +import java.io.ByteArrayInputStream; +import java.io.FileInputStream; +import java.io.IOException; + +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDFTemplateBuilder; +import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDFTemplateCreator; +import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDVisibleSigProperties; +import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDVisibleSignDesigner; + +import at.gv.egiz.pdfas.common.settings.ISettings; +import at.gv.egiz.pdfas.common.settings.SignatureProfileSettings; +import at.gv.egiz.pdfas.lib.impl.stamping.TableFactory; +import at.gv.egiz.pdfas.lib.impl.status.PDFObject; +import at.gv.egiz.pdfas.lib.test.mains.CertificateHolderRequest; +import at.knowcenter.wag.egov.egiz.table.Table; + +public class PDFAsVisualSignatureProperties extends PDVisibleSigProperties { + + private ISettings settings; + + private Table main; + + public PDFAsVisualSignatureProperties(ISettings settings, PDFObject object) { + this.settings = settings; + try { + SignatureProfileSettings profileSettings = TableFactory + .createProfile("SIGNATURBLOCK_DE", settings); + + X509Certificate cert = new X509Certificate(new FileInputStream( + "/home/afitzek/qualified.cer")); + + CertificateHolderRequest request = new CertificateHolderRequest( + cert); + + main = TableFactory.createSigTable(profileSettings, "main", + settings, request); + + main.setWidth(400); + } catch (Throwable e) { + e.printStackTrace(); + } + try { + PDDocument origDoc = PDDocument.load(new ByteArrayInputStream( + object.getStampedDocument())); + PDVisibleSignDesigner designer = new PDVisibleSignDesigner(origDoc, + new FileInputStream("/home/afitzek/.pdfas/images/signatur-logo_de.png"), 1); + + this.setPdVisibleSignature(designer); + } catch (Throwable e) { + e.printStackTrace(); + } + } + + @Override + public void buildSignature() throws IOException { + PDFTemplateBuilder builder = new PDFAsVisualSignatureBuilder(this); + PDFTemplateCreator creator = new PDFTemplateCreator(builder); + setVisibleSignature(creator.buildPDF(getPdVisibleSignature())); + } + + public Table getMainTable() { + return main; + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PdfBoxStamper.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PdfBoxStamper.java new file mode 100644 index 00000000..559c8c9b --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PdfBoxStamper.java @@ -0,0 +1,143 @@ +package at.gv.egiz.pdfas.lib.impl.stamping.pdfbox; + +import java.io.InputStream; + +import org.apache.pdfbox.pdmodel.PDPage; +import org.apache.pdfbox.pdmodel.common.PDRectangle; +import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDFTemplateBuilder; +import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDFTemplateStructure; +import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDVisibleSigBuilder; +import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDVisibleSignDesigner; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egiz.pdfas.common.exceptions.PdfAsException; +import at.gv.egiz.pdfas.common.settings.ISettings; +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.status.PDFObject; +import at.knowcenter.wag.egov.egiz.pdf.PositioningInstruction; +import at.knowcenter.wag.egov.egiz.table.Table; + +public class PdfBoxStamper implements IPDFStamper { + + private static final Logger logger = LoggerFactory.getLogger(PdfBoxStamper.class); + + private PDFTemplateBuilder pdfBuilder; + + public PdfBoxStamper() { + this.pdfBuilder = new PDVisibleSigBuilder(); + } + + /* + private InputStream renderTable(Table abstractTable) throws PdfAsException + { + logger.info("pdf building has been started"); + PDFTemplateStructure pdfStructure = pdfBuilder.getStructure(); + //pdfStructure.setIm + // we create array of [Text, ImageB, ImageC, ImageI] + this.pdfBuilder.createProcSetArray(); + + //create page + this.pdfBuilder.createPage(properties); + PDPage page = pdfStructure.getPage(); + + //create template + this.pdfBuilder.createTemplate(page); + PDDocument template = pdfStructure.getTemplate(); + + //create /AcroForm + this.pdfBuilder.createAcroForm(template); + PDAcroForm acroForm = pdfStructure.getAcroForm(); + + // AcroForm contains singature fields + this.pdfBuilder.createSignatureField(acroForm); + PDSignatureField pdSignatureField = pdfStructure.getSignatureField(); + + // create signature + this.pdfBuilder.createSignature(pdSignatureField, page, properties.getSignatureFieldName()); + + // that is /AcroForm/DR entry + this.pdfBuilder.createAcroFormDictionary(acroForm, pdSignatureField); + + // create AffineTransform + this.pdfBuilder.createAffineTransform(properties.getAffineTransformParams()); + AffineTransform transform = pdfStructure.getAffineTransform(); + + // rectangle, formatter, image. /AcroForm/DR/XObject contains that form + this.pdfBuilder.createSignatureRectangle(pdSignatureField, properties); + this.pdfBuilder.createFormaterRectangle(properties.getFormaterRectangleParams()); + PDRectangle formater = pdfStructure.getFormaterRectangle(); + this.pdfBuilder.createSignatureImage(template, properties.getImage()); + + // create form stream, form and resource. + this.pdfBuilder.createHolderFormStream(template); + PDStream holderFormStream = pdfStructure.getHolderFormStream(); + this.pdfBuilder.createHolderFormResources(); + PDResources holderFormResources = pdfStructure.getHolderFormResources(); + this.pdfBuilder.createHolderForm(holderFormResources, holderFormStream, formater); + + // that is /AP entry the appearance dictionary. + this.pdfBuilder.createAppearanceDictionary(pdfStructure.getHolderForm(), pdSignatureField); + + // inner formstream, form and resource (hlder form containts inner form) + this.pdfBuilder.createInnerFormStream(template); + this.pdfBuilder.createInnerFormResource(); + PDResources innerFormResource = pdfStructure.getInnerFormResources(); + this.pdfBuilder.createInnerForm(innerFormResource, pdfStructure.getInnterFormStream(), formater); + PDFormXObject innerForm = pdfStructure.getInnerForm(); + + // inner form must be in the holder form as we wrote + this.pdfBuilder.insertInnerFormToHolerResources(innerForm, holderFormResources); + + // Image form is in this structure: /AcroForm/DR/FRM0/Resources/XObject/n0 + this.pdfBuilder.createImageFormStream(template); + PDStream imageFormStream = pdfStructure.getImageFormStream(); + this.pdfBuilder.createImageFormResources(); + PDResources imageFormResources = pdfStructure.getImageFormResources(); + this.pdfBuilder.createImageForm(imageFormResources, innerFormResource, imageFormStream, formater, transform, + pdfStructure.getImage()); + + // now inject procSetArray + this.pdfBuilder.injectProcSetArray(innerForm, page, innerFormResource, imageFormResources, holderFormResources, + pdfStructure.getProcSet()); + + String imgFormName = pdfStructure.getImageFormName(); + String imgName = pdfStructure.getImageName(); + String innerFormName = pdfStructure.getInnerFormName(); + + // now create Streams of AP + this.pdfBuilder.injectAppearanceStreams(holderFormStream, imageFormStream, imageFormStream, imgFormName, + imgName, innerFormName, properties); + this.pdfBuilder.createVisualSignature(template); + this.pdfBuilder.createWidgetDictionary(pdSignatureField, holderFormResources); + + ByteArrayInputStream in = pdfStructure.getTemplateAppearanceStream(); + logger.info("stream returning started, size= " + in.available()); + + // we must close the document + template.close(); + + // return result of the stream + return in; + } + */ + + public IPDFVisualObject createVisualPDFObject(PDFObject pdf, Table table) { + + return null; + } + + public byte[] writeVisualObject(IPDFVisualObject visualObject, + PositioningInstruction positioningInstruction, byte[] pdfData, + String placeholderName) throws PdfAsException { + // TODO Auto-generated method stub + return null; + } + + public void setSettings(ISettings settings) { + // TODO Auto-generated method stub + + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PdfBoxVisualObject.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PdfBoxVisualObject.java new file mode 100644 index 00000000..25028073 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PdfBoxVisualObject.java @@ -0,0 +1,46 @@ +package at.gv.egiz.pdfas.lib.impl.stamping.pdfbox; + +import at.gv.egiz.pdfas.lib.impl.stamping.IPDFVisualObject; + +public class PdfBoxVisualObject implements IPDFVisualObject { + + public void setWidth(float width) { + + } + + public void fixWidth() { + // TODO Auto-generated method stub + + } + + public float getHeight() { + // TODO Auto-generated method stub + return 0; + } + + public float getWidth() { + // TODO Auto-generated method stub + return 0; + } + + public void setXPos(float x) { + // TODO Auto-generated method stub + + } + + public void setYPos(float x) { + // TODO Auto-generated method stub + + } + + public int getPage() { + // TODO Auto-generated method stub + return 0; + } + + public void setPage(int page) { + // TODO Auto-generated method stub + + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/status/ICertificateProvider.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/status/ICertificateProvider.java new file mode 100644 index 00000000..2ae94d2d --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/status/ICertificateProvider.java @@ -0,0 +1,7 @@ +package at.gv.egiz.pdfas.lib.impl.status; + +import iaik.x509.X509Certificate; + +public interface ICertificateProvider { + public X509Certificate getCertificate(); +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/status/RequestedSignature.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/status/RequestedSignature.java index 63f6a0d7..c9cab906 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/status/RequestedSignature.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/status/RequestedSignature.java @@ -30,7 +30,7 @@ import at.gv.egiz.pdfas.lib.api.SignaturePosition; import at.knowcenter.wag.egov.egiz.pdf.TablePos; -public class RequestedSignature { +public class RequestedSignature implements ICertificateProvider { private String signatureProfile; private TablePos tablePosition; private OperationStatus status; diff --git a/pdf-as-lib/src/test/java/at/gv/egiz/pdfas/lib/test/mains/CertificateHolderRequest.java b/pdf-as-lib/src/test/java/at/gv/egiz/pdfas/lib/test/mains/CertificateHolderRequest.java new file mode 100644 index 00000000..6d853f6e --- /dev/null +++ b/pdf-as-lib/src/test/java/at/gv/egiz/pdfas/lib/test/mains/CertificateHolderRequest.java @@ -0,0 +1,18 @@ +package at.gv.egiz.pdfas.lib.test.mains; +import iaik.x509.X509Certificate; +import at.gv.egiz.pdfas.lib.impl.status.ICertificateProvider; + + +public class CertificateHolderRequest implements ICertificateProvider { + + private X509Certificate cert; + + public CertificateHolderRequest(X509Certificate cert) { + this.cert = cert; + } + + public X509Certificate getCertificate() { + return cert; + } + +} diff --git a/pdf-as-lib/src/test/java/at/gv/egiz/pdfas/lib/test/mains/TestPDFBoxTable.java b/pdf-as-lib/src/test/java/at/gv/egiz/pdfas/lib/test/mains/TestPDFBoxTable.java new file mode 100644 index 00000000..cba9b927 --- /dev/null +++ b/pdf-as-lib/src/test/java/at/gv/egiz/pdfas/lib/test/mains/TestPDFBoxTable.java @@ -0,0 +1,207 @@ +package at.gv.egiz.pdfas.lib.test.mains; +import iaik.x509.X509Certificate; + +import java.awt.Graphics; +import java.awt.geom.AffineTransform; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; + +import org.apache.pdfbox.cos.COSName; +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.pdmodel.PDPage; +import org.apache.pdfbox.pdmodel.common.PDRectangle; +import org.apache.pdfbox.pdmodel.common.PDStream; +import org.apache.pdfbox.pdmodel.edit.PDPageContentStream; +import org.apache.pdfbox.pdmodel.font.PDFont; +import org.apache.pdfbox.pdmodel.font.PDType1Font; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egiz.pdfas.common.settings.ISettings; +import at.gv.egiz.pdfas.common.settings.SignatureProfileSettings; +import at.gv.egiz.pdfas.lib.api.PdfAs; +import at.gv.egiz.pdfas.lib.api.PdfAsFactory; +import at.gv.egiz.pdfas.lib.impl.stamping.TableFactory; +import at.knowcenter.wag.egov.egiz.table.Entry; +import at.knowcenter.wag.egov.egiz.table.Style; +import at.knowcenter.wag.egov.egiz.table.Table; + +public class TestPDFBoxTable { + + private static final Logger logger = LoggerFactory + .getLogger(TestPDFBoxTable.class); + + private static void drawTable(PDPage page, PDPageContentStream contentStream, + float x, float y, Table abstractTable) throws IOException { + + final int rows = abstractTable.getRows().size(); + final int cols = abstractTable.getMaxCols(); + float[] colsSizes = abstractTable.getColsRelativeWith(); + int max_cols = abstractTable.getMaxCols(); + if (colsSizes == null) + { + colsSizes = new float[max_cols]; + // set the column ratio for all columns to 1 + for (int cols_idx = 0; cols_idx < colsSizes.length; cols_idx++) + { + colsSizes[cols_idx] = 1; + } + } + + logger.info("TOTAL Col: " + abstractTable.getWidth()); + + float total = 0; + + for (int cols_idx = 0; cols_idx < colsSizes.length; cols_idx++) + { + total += colsSizes[cols_idx]; + } + + for (int cols_idx = 0; cols_idx < colsSizes.length; cols_idx++) + { + colsSizes[cols_idx] = (colsSizes[cols_idx]/total) * abstractTable.getWidth(); + } + + for (int cols_idx = 0; cols_idx < colsSizes.length; cols_idx++) + { + logger.info("Col: " + cols_idx + " : " + colsSizes[cols_idx]); + } + + final float cellMargin=5f; + final float rowHeight = 12f + 2 * cellMargin; + final float tableWidth = abstractTable.getWidth(); + final float tableHeight = rowHeight * rows; + final float colWidth = tableWidth/(float)cols; + + //draw the rows + float nexty = y ; + for (int i = 0; i <= rows; i++) { + contentStream.drawLine(x, nexty, x+tableWidth, nexty); + nexty-= rowHeight; + } + + //draw the columns + float nextx = x; + for (int i = 0; i <= cols; i++) { + contentStream.drawLine(nextx, y, nextx, y-tableHeight); + if(i < colsSizes.length) { + nextx += (colsSizes != null) ? colsSizes[i] : colWidth; + } + } + + float textx = x+cellMargin; + float texty = y-15; + for(int i = 0; i < abstractTable.getRows().size(); i++){ + ArrayList row = (ArrayList) abstractTable.getRows().get(i); + for(int j = 0 ; j < row.size(); j++) { + Entry cell = (Entry) row.get(j); + String text = cell.toString(); + text = "Hallo"; + COSName name = COSName.getPDFName("ANDI_TAG!"); + contentStream.beginMarkedContentSequence(COSName.ALT, name); + contentStream.beginText(); + logger.info("Writing: " + textx + " : " + texty + " = " + text); + contentStream.moveTextPositionByAmount(textx,texty); + + if (text.contains("\n")) { + String[] lines = text.split("\n"); + contentStream.appendRawCommands(10 + " TL\n"); + for (int k = 0; k < lines.length; k++) { + contentStream.drawString(lines[k]); + if (k < lines.length - 1) { + contentStream.appendRawCommands("T*\n"); + } + } + } else { + contentStream.drawString(text); + } + contentStream.endText(); + contentStream.endMarkedContentSequence(); + textx += (colsSizes != null) ? colsSizes[j] : colWidth; + } + texty-= rowHeight; + textx = x+cellMargin; + } + } + + + private static void renderTable(Table abstractTable) { + + ArrayList rows = abstractTable.getRows(); + Style table_style = abstractTable.getStyle(); + for (int row_idx = 0; row_idx < rows.size(); row_idx++) + { + @SuppressWarnings("rawtypes") + ArrayList row = (ArrayList) rows.get(row_idx); + logger.info("## Row:" + row_idx + " ## of table:" + abstractTable.getName()); + for (int entry_idx = 0; entry_idx < row.size(); entry_idx++) + { + Entry cell = (Entry) row.get(entry_idx); + // 03.11.2010 changed by exthex - swapped the two params, was probably a bug + Style inherit_style = Style.doInherit(table_style, cell.getStyle()); + cell.setStyle(inherit_style); + logger.info(cell.toString()); + /*PdfPCell pdf_cell = renderCell(cell); + if (cell.getColSpan() > 1) + { + pdf_cell.setColspan(cell.getColSpan()); + } + if (cell.isNoWrap()) + { + pdf_cell.setNoWrap(true); + }*/ + // System.err.println("valign:" + pdf_cell.getVerticalAlignment() + " + // halign:" + + // pdf_cell.getHorizontalAlignment()); + //pdf_table.addCell(pdf_cell); + } + //pdf_table.completeRow(); + } + logger.info("render table:" + abstractTable.getName()); + } + + public static void main(String[] args) { + try { + PdfAs pdfAs = PdfAsFactory.createPdfAs(new File("/home/afitzek/.pdfas/")); + ISettings settings = (ISettings) pdfAs.getConfiguration(); + SignatureProfileSettings profileSettings = + TableFactory.createProfile("SIGNATURBLOCK_DE", settings); + + X509Certificate cert = new X509Certificate(new FileInputStream("/home/afitzek/qualified.cer")); + + CertificateHolderRequest request = new CertificateHolderRequest(cert); + + Table main = TableFactory.createSigTable(profileSettings, "main", settings, request); + + main.setWidth(400); + + renderTable(main); + + PDStream stream1; + + PDDocument document = new PDDocument(); + PDPage page = new PDPage(); + page.setMediaBox(new PDRectangle()); + PDPageContentStream stream = new PDPageContentStream(document, page); + stream.setFont(PDType1Font.HELVETICA_BOLD , 12); + drawTable(page, stream, 100, 300, main); + stream.close(); + + document.addPage(page); + + document.save("/tmp/test.pdf"); + + /* + FileOutputStream fos = new FileOutputStream("/tmp/buffer.bin"); + fos.write(page.getContents().getByteArray()); + fos.close(); + */ + + } catch(Throwable e) { + e.printStackTrace(); + } + } +} diff --git a/pdf-as-lib/src/test/java/at/gv/egiz/pdfas/lib/test/mains/package-info.java b/pdf-as-lib/src/test/java/at/gv/egiz/pdfas/lib/test/mains/package-info.java new file mode 100644 index 00000000..60f666c8 --- /dev/null +++ b/pdf-as-lib/src/test/java/at/gv/egiz/pdfas/lib/test/mains/package-info.java @@ -0,0 +1,8 @@ +/** + * + */ +/** + * @author afitzek + * + */ +package at.gv.egiz.pdfas.lib.test.mains;
\ No newline at end of file |