aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Fitzek <afitzek@iaik.tugraz.at>2014-03-13 16:47:23 +0100
committerAndreas Fitzek <andreas.fitzek@iaik.tugraz.at>2014-04-01 16:51:50 +0200
commit0596609c350efb8af333feb650317c8640921a94 (patch)
tree0c7388ddf509b3950833cde74bbf241b51b56bb5
parent8d9cc698494694a57743c7443bf5e77d4e6c882b (diff)
downloadpdf-as-4-0596609c350efb8af333feb650317c8640921a94.tar.gz
pdf-as-4-0596609c350efb8af333feb650317c8640921a94.tar.bz2
pdf-as-4-0596609c350efb8af333feb650317c8640921a94.zip
WIP: Appearance Dictionary Signature OK
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox/PADESPDFBOXSigner.java11
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsTemplateCreator.java140
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureBuilder.java345
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureDesigner.java392
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureProperties.java17
5 files changed, 872 insertions, 33 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 93c19fe5..651c2e49 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
@@ -111,7 +111,16 @@ public class PADESPDFBOXSigner implements IPdfSigner {
PDFAsVisualSignatureProperties properties = new PDFAsVisualSignatureProperties(
pdfObject.getStatus().getSettings(), pdfObject);
properties.buildSignature();
- options.setVisualSignature(properties.getVisibleSignature());
+
+ 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);
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsTemplateCreator.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsTemplateCreator.java
new file mode 100644
index 00000000..e952ea73
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsTemplateCreator.java
@@ -0,0 +1,140 @@
+package at.gv.egiz.pdfas.lib.impl.stamping.pdfbox;
+
+import java.awt.geom.AffineTransform;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.pdfbox.exceptions.COSVisitorException;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDPage;
+import org.apache.pdfbox.pdmodel.PDResources;
+import org.apache.pdfbox.pdmodel.common.PDRectangle;
+import org.apache.pdfbox.pdmodel.common.PDStream;
+import org.apache.pdfbox.pdmodel.graphics.xobject.PDXObjectForm;
+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.PDFTemplateStructure;
+import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDVisibleSignDesigner;
+import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
+import org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PDFAsTemplateCreator extends PDFTemplateCreator {
+
+ PDFAsVisualSignatureBuilder pdfBuilder;
+ private static final Logger logger = LoggerFactory.getLogger(PDFAsTemplateCreator.class);
+
+ public PDFAsTemplateCreator(PDFAsVisualSignatureBuilder bookBuilder) {
+ super(bookBuilder);
+ this.pdfBuilder = bookBuilder;
+ }
+
+
+ public InputStream buildPDF(PDFAsVisualSignatureDesigner properties)
+ throws IOException {
+ logger.info("pdf building has been started");
+ PDFTemplateStructure pdfStructure = pdfBuilder.getStructure();
+
+ // 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.getImageStream());
+
+ // 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);
+ PDXObjectForm 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.getJpedImage());
+
+ // now inject procSetArray
+ /*this.pdfBuilder.injectProcSetArray(innerForm, page, innerFormResource, imageFormResources, holderFormResources,
+ pdfStructure.getProcSet());*/
+ this.pdfBuilder.injectProcSetArray(innerForm, page, innerFormResource, null, 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.injectAppearanceStreams(holderFormStream, null, null, null,
+ null, innerFormName, properties);
+ this.pdfBuilder.createVisualSignature(template);
+ this.pdfBuilder.createWidgetDictionary(pdSignatureField, holderFormResources);
+
+ ByteArrayInputStream in = null;
+ try
+ {
+ in = pdfStructure.getTemplateAppearanceStream();
+ }
+ catch (COSVisitorException e)
+ {
+ logger.error("COSVisitorException: can't get apereance stream ", e);
+ }
+ logger.info("stream returning started, size= " + in.available());
+
+ // we must close the document
+ template.close();
+
+ // return result of the stream
+ return in;
+ }
+}
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
index 496bc0d8..cd4abdf9 100644
--- 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
@@ -1,16 +1,33 @@
package at.gv.egiz.pdfas.lib.impl.stamping.pdfbox;
+import java.awt.geom.AffineTransform;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.util.ArrayList;
+import java.util.List;
+import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
+import org.apache.pdfbox.pdmodel.PDResources;
+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.PDType1Font;
+import org.apache.pdfbox.pdmodel.graphics.xobject.PDJpeg;
+import org.apache.pdfbox.pdmodel.graphics.xobject.PDXObjectForm;
+import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceDictionary;
+import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceStream;
+import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature;
+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.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
+import org.apache.pdfbox.pdmodel.interactive.form.PDField;
+import org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -120,6 +137,15 @@ public class PDFAsVisualSignatureBuilder extends PDVisibleSigBuilder {
}
@Override
+ public void createProcSetArray() {
+ COSArray procSetArr = new COSArray();
+ procSetArr.add(COSName.getPDFName("PDF"));
+ procSetArr.add(COSName.getPDFName("Text"));
+ getStructure().setProcSet(procSetArr);
+ logger.info("ProcSet array has been created");
+ }
+
+ @Override
public void createTemplate(PDPage page) throws IOException {
PDDocument template = new PDDocument();
@@ -144,30 +170,299 @@ public class PDFAsVisualSignatureBuilder extends PDVisibleSigBuilder {
e.printStackTrace();
}
}
+
+ @Override
+ public void injectProcSetArray(PDXObjectForm innerForm, PDPage page,
+ PDResources innerFormResources, PDResources imageFormResources,
+ PDResources holderFormResources, COSArray procSet) {
+ innerForm.getResources().getCOSDictionary()
+ .setItem(COSName.PROC_SET, procSet); //
+ page.getCOSDictionary().setItem(COSName.PROC_SET, procSet);
+ innerFormResources.getCOSDictionary()
+ .setItem(COSName.PROC_SET, procSet);
+ /*imageFormResources.getCOSDictionary()
+ .setItem(COSName.PROC_SET, procSet);*/
+ holderFormResources.getCOSDictionary().setItem(COSName.PROC_SET,
+ procSet);
+ logger.info("inserted ProcSet to PDF");
+ }
+
+ public void injectAppearanceStreams(PDStream holderFormStream,
+ PDStream innterFormStream, PDStream imageFormStream,
+ String imageObjectName, String imageName, String innerFormName,
+ PDFAsVisualSignatureDesigner 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";
+ String innerFormComment = getStructure().getInnterFormStream()
+ .getInputStreamAsString();
+
+ logger.info("Inner Form Stream: " + innerFormComment);
+
+ // appendRawCommands(getStructure().getInnterFormStream().createOutputStream(),
+ // getStructure().getInnterFormStream().getInputStreamAsString());
+
+ appendRawCommands(getStructure().getHolderFormStream()
+ .createOutputStream(), holderFormComment);
+ appendRawCommands(getStructure().getInnterFormStream()
+ .createOutputStream(), innerFormComment);
+ // appendRawCommands(getStructure().getImageFormStream().createOutputStream(),
+ // imgFormComment);
+ logger.info("Injected apereance stream to pdf");
+
+ }
+
+ public void createPage(PDFAsVisualSignatureDesigner properties)
+ {
+ PDPage page = new PDPage();
+ page.setMediaBox(new PDRectangle(properties.getPageWidth(), properties.getPageHeight()));
+ getStructure().setPage(page);
+ logger.info("PDF page has been created");
+ }
+
+ public void createAcroForm(PDDocument template)
+ {
+ PDAcroForm theAcroForm = new PDAcroForm(template);
+ template.getDocumentCatalog().setAcroForm(theAcroForm);
+ getStructure().setAcroForm(theAcroForm);
+ logger.info("Acro form page has been created");
+
+ }
+
+ public void createSignatureField(PDAcroForm acroForm) throws IOException
+ {
+ PDSignatureField sf = new PDSignatureField(acroForm);
+ getStructure().setSignatureField(sf);
+ logger.info("Signature field has been created");
+ }
+
+ public void createSignature(PDSignatureField pdSignatureField, PDPage page, String signatureName)
+ throws IOException
+ {
+ PDSignature pdSignature = new PDSignature();
+ pdSignatureField.setSignature(pdSignature);
+ pdSignatureField.getWidget().setPage(page);
+ page.getAnnotations().add(pdSignatureField.getWidget());
+ pdSignature.setName(signatureName);
+ pdSignature.setByteRange(new int[] { 0, 0, 0, 0 });
+ pdSignature.setContents(new byte[4096]);
+ getStructure().setPdSignature(pdSignature);
+ logger.info("PDSignatur has been created");
+ }
+
+ public void createAcroFormDictionary(PDAcroForm acroForm, PDSignatureField signatureField) throws IOException
+ {
+ @SuppressWarnings("unchecked")
+ List<PDField> acroFormFields = acroForm.getFields();
+ COSDictionary acroFormDict = acroForm.getDictionary();
+ acroFormDict.setDirect(true);
+ acroFormDict.setInt(COSName.SIG_FLAGS, 3);
+ acroFormFields.add(signatureField);
+ acroFormDict.setString(COSName.DA, "/sylfaen 0 Tf 0 g");
+ getStructure().setAcroFormFields(acroFormFields);
+ getStructure().setAcroFormDictionary(acroFormDict);
+ logger.info("AcroForm dictionary has been created");
+ }
+
+ public void createSignatureRectangle(PDSignatureField signatureField, PDFAsVisualSignatureDesigner properties)
+ throws IOException
+ {
+
+ PDRectangle rect = new PDRectangle();
+ rect.setUpperRightX(properties.getxAxis() + properties.getWidth());
+ rect.setUpperRightY(properties.getPageHeight() - properties.getyAxis());
+ rect.setLowerLeftY(properties.getPageHeight() - properties.getyAxis() - properties.getHeight());
+ rect.setLowerLeftX(properties.getxAxis());
+ signatureField.getWidget().setRectangle(rect);
+ getStructure().setSignatureRectangle(rect);
+ logger.info("rectangle of signature has been created");
+ }
+
+ public void createAffineTransform(byte[] params)
+ {
+ AffineTransform transform = new AffineTransform(params[0], params[1], params[2], params[3], params[4],
+ params[5]);
+ getStructure().setAffineTransform(transform);
+ logger.info("Matrix has been added");
+ }
+
+ public void createSignatureImage(PDDocument template, InputStream inputStream) throws IOException
+ {
+ PDJpeg img = new PDJpeg(template, inputStream);
+ getStructure().setJpedImage(img);
+ logger.info("Visible Signature Image has been created");
+ // pdfStructure.setTemplate(template);
+ inputStream.close();
+
+ }
+
+ public void createFormaterRectangle(byte[] params)
+ {
+
+ PDRectangle formrect = new PDRectangle();
+ formrect.setUpperRightX(params[0]);
+ formrect.setUpperRightY(params[1]);
+ formrect.setLowerLeftX(params[2]);
+ formrect.setLowerLeftY(params[3]);
+
+ getStructure().setFormaterRectangle(formrect);
+ logger.info("Formater rectangle has been created");
+
+ }
+
+ public void createHolderFormStream(PDDocument template)
+ {
+ PDStream holderForm = new PDStream(template);
+ getStructure().setHolderFormStream(holderForm);
+ logger.info("Holder form Stream has been created");
+ }
+
+ public void createHolderFormResources()
+ {
+ PDResources holderFormResources = new PDResources();
+ getStructure().setHolderFormResources(holderFormResources);
+ logger.info("Holder form resources have been created");
+
+ }
+
+ public void createHolderForm(PDResources holderFormResources, PDStream holderFormStream, PDRectangle formrect)
+ {
+
+ PDXObjectForm holderForm = new PDXObjectForm(holderFormStream);
+ holderForm.setResources(holderFormResources);
+ holderForm.setBBox(formrect);
+ holderForm.setFormType(1);
+ getStructure().setHolderForm(holderForm);
+ logger.info("Holder form has been created");
+
+ }
+
+ public void createAppearanceDictionary(PDXObjectForm holderForml, PDSignatureField signatureField)
+ throws IOException
+ {
+
+ PDAppearanceDictionary appearance = new PDAppearanceDictionary();
+ appearance.getCOSObject().setDirect(true);
+
+ PDAppearanceStream appearanceStream = new PDAppearanceStream(holderForml.getCOSStream());
+
+ appearance.setNormalAppearance(appearanceStream);
+ signatureField.getWidget().setAppearance(appearance);
+
+ getStructure().setAppearanceDictionary(appearance);
+ logger.info("PDF appereance Dictionary has been created");
+
+ }
+
+ public void createInnerFormResource()
+ {
+ PDResources innerFormResources = new PDResources();
+ getStructure().setInnerFormResources(innerFormResources);
+ logger.info("Resources of another form (inner form - it would be inside holder form) have been created");
+ }
+
+ public void createInnerForm(PDResources innerFormResources, PDStream innerFormStream, PDRectangle formrect)
+ {
+ PDXObjectForm innerForm = new PDXObjectForm(innerFormStream);
+ innerForm.setResources(innerFormResources);
+ innerForm.setBBox(formrect);
+ innerForm.setFormType(1);
+ getStructure().setInnerForm(innerForm);
+ logger.info("Another form (inner form - it would be inside holder form) have been created");
+
+ }
+
+ public void insertInnerFormToHolerResources(PDXObjectForm innerForm, PDResources holderFormResources)
+ {
+ String name = holderFormResources.addXObject(innerForm, "FRM");
+ getStructure().setInnerFormName(name);
+ logger.info("Alerady inserted inner form inside holder form");
+ }
+
+ public void createImageFormStream(PDDocument template)
+ {
+ PDStream imageFormStream = new PDStream(template);
+ getStructure().setImageFormStream(imageFormStream);
+ logger.info("Created image form Stream");
+
+ }
+
+ public void createImageFormResources()
+ {
+ PDResources imageFormResources = new PDResources();
+ getStructure().setImageFormResources(imageFormResources);
+ logger.info("Created image form Resources");
+ }
+
+ public void createImageForm(PDResources imageFormResources, PDResources innerFormResource,
+ PDStream imageFormStream, PDRectangle formrect, AffineTransform affineTransform, PDJpeg img)
+ throws IOException
+ {
+
+ /*
+ * if you need text on the visible signature
+ *
+ * PDFont font = PDTrueTypeFont.loadTTF(this.pdfStructure.getTemplate(), new File("D:\\arial.ttf"));
+ * font.setFontEncoding(new WinAnsiEncoding());
+ *
+ * Map<String, PDFont> fonts = new HashMap<String, PDFont>(); fonts.put("arial", font);
+ */
+ PDXObjectForm imageForm = new PDXObjectForm(imageFormStream);
+ imageForm.setBBox(formrect);
+ imageForm.setMatrix(affineTransform);
+ imageForm.setResources(imageFormResources);
+ imageForm.setFormType(1);
+ /*
+ * imageForm.getResources().addFont(font);
+ * imageForm.getResources().setFonts(fonts);
+ */
+
+ imageFormResources.getCOSObject().setDirect(true);
+ String imageFormName = innerFormResource.addXObject(imageForm, "n");
+ String imageName = imageFormResources.addXObject(img, "img");
+ this.getStructure().setImageForm(imageForm);
+ this.getStructure().setImageFormName(imageFormName);
+ this.getStructure().setImageName(imageName);
+ logger.info("Created image form");
+ }
+
+ public void appendRawCommands(OutputStream os, String commands) throws IOException
+ {
+ os.write(commands.getBytes("UTF-8"));
+ os.close();
+ }
+
+ public void createVisualSignature(PDDocument template)
+ {
+ this.getStructure().setVisualSignature(template.getDocument());
+ logger.info("Visible signature has been created");
+
+ }
+
+ public void createWidgetDictionary(PDSignatureField signatureField, PDResources holderFormResources)
+ throws IOException
+ {
+
+ COSDictionary widgetDict = signatureField.getWidget().getDictionary();
+ widgetDict.setNeedToBeUpdate(true);
+ widgetDict.setItem(COSName.DR, holderFormResources.getCOSObject());
+
+ getStructure().setWidgetDictionary(widgetDict);
+ logger.info("WidgetDictionary has been crated");
+ }
+
+ public void closeTemplate(PDDocument template) throws IOException
+ {
+ template.close();
+ this.getStructure().getTemplate().close();
+ }
- @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/PDFAsVisualSignatureDesigner.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureDesigner.java
new file mode 100644
index 00000000..5ad36c62
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureDesigner.java
@@ -0,0 +1,392 @@
+package at.gv.egiz.pdfas.lib.impl.stamping.pdfbox;
+
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.imageio.ImageIO;
+
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDPage;
+import org.apache.pdfbox.pdmodel.common.PDRectangle;
+import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDVisibleSignDesigner;
+
+public class PDFAsVisualSignatureDesigner {
+
+ private Float sigImgWidth;
+ private Float sigImgHeight;
+ private float xAxis;
+ private float yAxis;
+ private float pageHeight;
+ private float pageWidth;
+ private InputStream imgageStream;
+ private String signatureFieldName = "sig"; // default
+ private byte[] formaterRectangleParams = { 0, 0, 100, 50 }; // default
+ private byte[] AffineTransformParams = { 1, 0, 0, 1, 0, 0 }; // default
+ private float imageSizeInPercents;
+ private PDDocument document = null;
+
+ /**
+ *
+ * @param doc
+ * - Already created PDDocument of your PDF document
+ * @param imageStream
+ * @param page
+ * @throws IOException
+ * - If we can't read, flush, or can't close stream
+ */
+ public PDFAsVisualSignatureDesigner(PDDocument doc,
+ int page) throws IOException {
+ calculatePageSize(doc, page);
+ }
+
+ /**
+ * Each page of document can be different sizes.
+ *
+ * @param document
+ * @param page
+ */
+ private void calculatePageSize(PDDocument document, int page) {
+
+ if (page < 1) {
+ throw new IllegalArgumentException("First page of pdf is 1, not "
+ + page);
+ }
+
+ List<?> pages = document.getDocumentCatalog().getAllPages();
+ PDPage firstPage = (PDPage) pages.get(page - 1);
+ PDRectangle mediaBox = firstPage.findMediaBox();
+ this.pageHeight(mediaBox.getHeight());
+ this.pageWidth = mediaBox.getWidth();
+
+ float x = this.pageWidth;
+ float y = 0;
+ this.pageWidth = this.pageWidth + y;
+ float tPercent = (100 * y / (x + y));
+ this.imageSizeInPercents = 100 - tPercent;
+
+ }
+
+ /**
+ *
+ * @param path
+ * of image location
+ * @return image Stream
+ * @throws IOException
+ */
+ public PDFAsVisualSignatureDesigner signatureImage(String path) throws IOException {
+ InputStream fin = new FileInputStream(path);
+ return signatureImageStream(fin);
+ }
+
+ /**
+ * zoom signature image with some percent.
+ *
+ * @param percent
+ * - x % increase image with x percent.
+ * @return Visible Signature Configuration Object
+ */
+ public PDFAsVisualSignatureDesigner zoom(float percent) {
+ sigImgHeight = sigImgHeight + (sigImgHeight * percent) / 100;
+ sigImgWidth = sigImgWidth + (sigImgWidth * percent) / 100;
+ return this;
+ }
+
+ /**
+ *
+ * @param xAxis
+ * - x coordinate
+ * @param yAxis
+ * - y coordinate
+ * @return Visible Signature Configuration Object
+ */
+ public PDFAsVisualSignatureDesigner coordinates(float x, float y) {
+ xAxis(x);
+ yAxis(y);
+ return this;
+ }
+
+ /**
+ *
+ * @return xAxis - gets x coordinates
+ */
+ public float getxAxis() {
+ return xAxis;
+ }
+
+ /**
+ *
+ * @param xAxis
+ * - x coordinate
+ * @return Visible Signature Configuration Object
+ */
+ public PDFAsVisualSignatureDesigner xAxis(float xAxis) {
+ this.xAxis = xAxis;
+ return this;
+ }
+
+ /**
+ *
+ * @return yAxis
+ */
+ public float getyAxis() {
+ return yAxis;
+ }
+
+ /**
+ *
+ * @param yAxis
+ * @return Visible Signature Configuration Object
+ */
+ public PDFAsVisualSignatureDesigner yAxis(float yAxis) {
+ this.yAxis = yAxis;
+ return this;
+ }
+
+ /**
+ *
+ * @return signature image width
+ */
+ public float getWidth() {
+ return 400;
+ }
+
+ /**
+ *
+ * @param sets
+ * signature image width
+ * @return Visible Signature Configuration Object
+ */
+ public PDFAsVisualSignatureDesigner width(float signatureImgWidth) {
+ this.sigImgWidth = signatureImgWidth;
+ return this;
+ }
+
+ /**
+ *
+ * @return signature image height
+ */
+ public float getHeight() {
+ return 300;
+ }
+
+ /**
+ *
+ * @param set
+ * signature image Height
+ * @return Visible Signature Configuration Object
+ */
+ public PDFAsVisualSignatureDesigner height(float signatureImgHeight) {
+ this.sigImgHeight = signatureImgHeight;
+ return this;
+ }
+
+ /**
+ *
+ * @return template height
+ */
+ protected float getTemplateHeight() {
+ return getPageHeight();
+ }
+
+ /**
+ *
+ * @param templateHeight
+ * @return Visible Signature Configuration Object
+ */
+ private PDFAsVisualSignatureDesigner pageHeight(float templateHeight) {
+ this.pageHeight = templateHeight;
+ return this;
+ }
+
+ /**
+ *
+ * @return signature field name
+ */
+ public String getSignatureFieldName() {
+ return signatureFieldName;
+ }
+
+ /**
+ *
+ * @param signatureFieldName
+ * @return Visible Signature Configuration Object
+ */
+ public PDFAsVisualSignatureDesigner signatureFieldName(String signatureFieldName) {
+ this.signatureFieldName = signatureFieldName;
+ return this;
+ }
+
+ /**
+ *
+ * @return image Stream
+ */
+ public InputStream getImageStream() {
+ return imgageStream;
+ }
+
+ /**
+ *
+ * @param imgageStream
+ * - stream of your visible signature image
+ * @return Visible Signature Configuration Object
+ * @throws IOException
+ * - If we can't read, flush, or close stream of image
+ */
+ private PDFAsVisualSignatureDesigner signatureImageStream(InputStream imageStream)
+ throws IOException {
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ byte[] buffer = new byte[1024];
+ int len;
+ while ((len = imageStream.read(buffer)) > -1) {
+ baos.write(buffer, 0, len);
+ }
+ baos.flush();
+ baos.close();
+
+ byte[] byteArray = baos.toByteArray();
+ byte[] byteArraySecond = byteArray.clone();
+
+ InputStream inputForBufferedImage = new ByteArrayInputStream(byteArray);
+ InputStream revertInputStream = new ByteArrayInputStream(
+ byteArraySecond);
+
+ if (sigImgHeight == null || sigImgWidth == null) {
+ calcualteImageSize(inputForBufferedImage);
+ }
+
+ this.imgageStream = revertInputStream;
+
+ return this;
+ }
+
+ /**
+ * calculates image width and height. sported formats: all
+ *
+ * @param fis
+ * - input stream of image
+ * @throws IOException
+ * - if can't read input stream
+ */
+ private void calcualteImageSize(InputStream fis) throws IOException {
+
+ BufferedImage bimg = ImageIO.read(fis);
+ int width = bimg.getWidth();
+ int height = bimg.getHeight();
+
+ sigImgHeight = (float) height;
+ sigImgWidth = (float) width;
+
+ }
+
+ /**
+ *
+ * @return Affine Transform parameters of for PDF Matrix
+ */
+ public byte[] getAffineTransformParams() {
+ return AffineTransformParams;
+ }
+
+ /**
+ *
+ * @param affineTransformParams
+ * @return Visible Signature Configuration Object
+ */
+ public PDFAsVisualSignatureDesigner affineTransformParams(
+ byte[] affineTransformParams) {
+ AffineTransformParams = affineTransformParams;
+ return this;
+ }
+
+ /**
+ *
+ * @return formatter PDRectanle parameters
+ */
+ public byte[] getFormaterRectangleParams() {
+ return formaterRectangleParams;
+ }
+
+ /**
+ * sets formatter PDRectangle;
+ *
+ * @param formaterRectangleParams
+ * @return Visible Signature Configuration Object
+ */
+ public PDFAsVisualSignatureDesigner formaterRectangleParams(
+ byte[] formaterRectangleParams) {
+ this.formaterRectangleParams = formaterRectangleParams;
+ return this;
+ }
+
+ /**
+ *
+ * @return page width
+ */
+ public float getPageWidth() {
+ return pageWidth;
+ }
+
+ /**
+ *
+ * @param sets
+ * pageWidth
+ * @return Visible Signature Configuration Object
+ */
+ public PDFAsVisualSignatureDesigner pageWidth(float pageWidth) {
+ this.pageWidth = pageWidth;
+ return this;
+ }
+
+ /**
+ *
+ * @return page height
+ */
+ public float getPageHeight() {
+ return pageHeight;
+ }
+
+ /**
+ * get image size in percents
+ *
+ * @return
+ */
+ public float getImageSizeInPercents() {
+ return imageSizeInPercents;
+ }
+
+ /**
+ *
+ * @param imageSizeInPercents
+ */
+ public void imageSizeInPercents(float imageSizeInPercents) {
+ this.imageSizeInPercents = imageSizeInPercents;
+ }
+
+ /**
+ * returns visible signature text
+ *
+ * @return
+ */
+ public String getSignatureText() {
+ throw new UnsupportedOperationException(
+ "That method is not yet implemented");
+ }
+
+ /**
+ *
+ * @param signatureText
+ * - adds the text on visible signature
+ * @return
+ */
+ public PDFAsVisualSignatureDesigner signatureText(String signatureText) {
+ throw new UnsupportedOperationException(
+ "That method is not yet implemented");
+ }
+
+}
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
index a3d02db2..055f035d 100644
--- 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
@@ -24,6 +24,8 @@ public class PDFAsVisualSignatureProperties extends PDVisibleSigProperties {
private ISettings settings;
private Table main;
+
+ private PDFAsVisualSignatureDesigner designer;
public PDFAsVisualSignatureProperties(ISettings settings, PDFObject object) {
this.settings = settings;
@@ -32,7 +34,7 @@ public class PDFAsVisualSignatureProperties extends PDVisibleSigProperties {
.createProfile("SIGNATURBLOCK_DE", settings);
X509Certificate cert = new X509Certificate(new FileInputStream(
- "/home/afitzek/qualified.cer"));
+ "/home/andy/certificates/test.crt"));
CertificateHolderRequest request = new CertificateHolderRequest(
cert);
@@ -47,10 +49,10 @@ public class PDFAsVisualSignatureProperties extends PDVisibleSigProperties {
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);
+ designer = new PDFAsVisualSignatureDesigner(origDoc, 1);
+
+ //this.setPdVisibleSignature(designer);
} catch (Throwable e) {
e.printStackTrace();
}
@@ -58,13 +60,14 @@ public class PDFAsVisualSignatureProperties extends PDVisibleSigProperties {
@Override
public void buildSignature() throws IOException {
- PDFTemplateBuilder builder = new PDFAsVisualSignatureBuilder(this);
- PDFTemplateCreator creator = new PDFTemplateCreator(builder);
- setVisibleSignature(creator.buildPDF(getPdVisibleSignature()));
+ PDFAsVisualSignatureBuilder builder = new PDFAsVisualSignatureBuilder(this);
+ PDFAsTemplateCreator creator = new PDFAsTemplateCreator(builder);
+ setVisibleSignature(creator.buildPDF(designer));
}
public Table getMainTable() {
return main;
}
+
}