aboutsummaryrefslogtreecommitdiff
path: root/pdf-as-lib
diff options
context:
space:
mode:
authorAndreas Fitzek <andreas.fitzek@iaik.tugraz.at>2014-03-13 08:52:46 +0100
committerAndreas Fitzek <andreas.fitzek@iaik.tugraz.at>2014-04-01 16:51:50 +0200
commit8d9cc698494694a57743c7443bf5e77d4e6c882b (patch)
tree6b7cf655ffdc0a8e92252adbf25ce5ae4fd41f1f /pdf-as-lib
parent78c7b6b82267b766b573046d722a55638749a6cd (diff)
downloadpdf-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')
-rw-r--r--pdf-as-lib/build.gradle2
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/PdfAsImpl.java2
-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/CertificateResolver.java3
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/IResolver.java3
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/TableFactory.java11
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/ValueResolver.java7
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureBuilder.java173
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureProperties.java70
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PdfBoxStamper.java143
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PdfBoxVisualObject.java46
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/status/ICertificateProvider.java7
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/status/RequestedSignature.java2
-rw-r--r--pdf-as-lib/src/test/java/at/gv/egiz/pdfas/lib/test/mains/CertificateHolderRequest.java18
-rw-r--r--pdf-as-lib/src/test/java/at/gv/egiz/pdfas/lib/test/mains/TestPDFBoxTable.java207
-rw-r--r--pdf-as-lib/src/test/java/at/gv/egiz/pdfas/lib/test/mains/package-info.java8
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