aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Fitzek <andreas.fitzek@iaik.tugraz.at>2016-12-12 07:50:25 +0100
committerAndreas Fitzek <andreas.fitzek@iaik.tugraz.at>2016-12-12 07:50:25 +0100
commit65eb7054679d63a4f519bd31eb37805666e6fef8 (patch)
tree132ec9504a268e44e801e6bd1c26fcc49bd57e7d
parent57ffbe830705003caa2af2e12f7e38c38d3a2ff8 (diff)
downloadpdf-as-4-65eb7054679d63a4f519bd31eb37805666e6fef8.tar.gz
pdf-as-4-65eb7054679d63a4f519bd31eb37805666e6fef8.tar.bz2
pdf-as-4-65eb7054679d63a4f519bd31eb37805666e6fef8.zip
added PDF/A-3b support, and PDF/A version detection
-rw-r--r--pdf-as-common/src/main/java/at/gv/egiz/pdfas/common/settings/IProfileConstants.java1
-rw-r--r--pdf-as-common/src/main/java/at/gv/egiz/pdfas/common/settings/SignatureProfileSettings.java26
-rw-r--r--pdf-as-pdfbox-2/build.gradle1
-rw-r--r--pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox2/PADESPDFBOXSigner.java40
-rw-r--r--pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFAsTemplateCreator.java37
-rw-r--r--pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFAsVisualSignatureBuilder.java48
-rw-r--r--pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFAsVisualSignatureProperties.java2
-rw-r--r--pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFBoxFont.java15
-rw-r--r--pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/TableDrawUtils.java16
9 files changed, 160 insertions, 26 deletions
diff --git a/pdf-as-common/src/main/java/at/gv/egiz/pdfas/common/settings/IProfileConstants.java b/pdf-as-common/src/main/java/at/gv/egiz/pdfas/common/settings/IProfileConstants.java
index 2c2b941b..a2cee944 100644
--- a/pdf-as-common/src/main/java/at/gv/egiz/pdfas/common/settings/IProfileConstants.java
+++ b/pdf-as-common/src/main/java/at/gv/egiz/pdfas/common/settings/IProfileConstants.java
@@ -92,6 +92,7 @@ public interface IProfileConstants {
public final static String SIGNFIELD_VALUE = "adobeSignFieldValue";
public final static String TIMEZONE_BASE = "timezone";
public final static String SIG_PDFA1B_VALID = "SIG_PDFA1B_VALID";
+ public final static String SIG_PDFA3B_VALID = "SIG_PDFA3B_VALID";
public final static String SIG_PDFUA_FORCE = "SIG_PDFUA_FORCE";
}
diff --git a/pdf-as-common/src/main/java/at/gv/egiz/pdfas/common/settings/SignatureProfileSettings.java b/pdf-as-common/src/main/java/at/gv/egiz/pdfas/common/settings/SignatureProfileSettings.java
index cbc1d601..b6a1b6ca 100644
--- a/pdf-as-common/src/main/java/at/gv/egiz/pdfas/common/settings/SignatureProfileSettings.java
+++ b/pdf-as-common/src/main/java/at/gv/egiz/pdfas/common/settings/SignatureProfileSettings.java
@@ -39,6 +39,8 @@ public class SignatureProfileSettings implements IProfileConstants {
private String profileID;
+ private String pdfAVersion = null;
+
private ISettings configuration;
public SignatureProfileSettings(String profileID, ISettings configuration) {
@@ -203,8 +205,17 @@ public class SignatureProfileSettings implements IProfileConstants {
public String getProfileTimeZone() {
return this.getValue(TIMEZONE_BASE);
}
-
+
+ public void setPDFAVersion(String version) {
+ this.pdfAVersion = version;
+ }
+
public boolean isPDFA() {
+
+ if(this.pdfAVersion != null) {
+ return "1".equals(this.pdfAVersion);
+ }
+
SignatureProfileEntry entry = profileInformations.get(SIG_PDFA1B_VALID);
if (entry != null) {
String value = entry.getCaption();
@@ -221,4 +232,17 @@ public class SignatureProfileSettings implements IProfileConstants {
}
return false;
}
+
+ public boolean isPDFA3() {
+ if(this.pdfAVersion != null) {
+ return "3".equals(this.pdfAVersion);
+ }
+
+ SignatureProfileEntry entry = profileInformations.get(SIG_PDFA3B_VALID);
+ if (entry != null) {
+ String value = entry.getCaption();
+ return "true".equals(value);
+ }
+ return false;
+ }
}
diff --git a/pdf-as-pdfbox-2/build.gradle b/pdf-as-pdfbox-2/build.gradle
index 970ca038..c5d7d41e 100644
--- a/pdf-as-pdfbox-2/build.gradle
+++ b/pdf-as-pdfbox-2/build.gradle
@@ -16,6 +16,7 @@ jar {
repositories {
+ mavenLocal()
mavenCentral()
}
diff --git a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox2/PADESPDFBOXSigner.java b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox2/PADESPDFBOXSigner.java
index 8965ce0e..901e47db 100644
--- a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox2/PADESPDFBOXSigner.java
+++ b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox2/PADESPDFBOXSigner.java
@@ -48,6 +48,7 @@ import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDResources;
+import org.apache.pdfbox.pdmodel.common.PDMetadata;
import org.apache.pdfbox.pdmodel.common.PDNumberTreeNode;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.documentinterchange.logicalstructure.PDStructureElement;
@@ -68,6 +69,9 @@ import org.apache.pdfbox.preflight.exception.ValidationException;
import org.apache.pdfbox.preflight.parser.PreflightParser;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
+import org.apache.xmpbox.XMPMetadata;
+import org.apache.xmpbox.schema.PDFAIdentificationSchema;
+import org.apache.xmpbox.xml.DomXmpParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -132,6 +136,8 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants {
PDFASPDFBOXSignatureInterface signer = (PDFASPDFBOXSignatureInterface) genericSigner;
+ String pdfaVersion = null;
+
PDDocument doc = null;
SignatureOptions options = new SignatureOptions();
COSDocument visualSignatureDocumentGuard = null;
@@ -221,6 +227,11 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants {
}
options.setPreferredSignatureSize(signatureSize);
+ if(signatureProfileSettings.isPDFA() || signatureProfileSettings.isPDFA3()) {
+ pdfaVersion = getPDFAVersion(doc);
+ signatureProfileSettings.setPDFAVersion(pdfaVersion);
+ }
+
// Is visible Signature
if (requestedSignature.isVisual()) {
logger.info("Creating visual siganture block");
@@ -352,7 +363,7 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants {
}
- if (signatureProfileSettings.isPDFA()) {
+ if (signatureProfileSettings.isPDFA() || signatureProfileSettings.isPDFA3()) {
PDDocumentCatalog root = doc.getDocumentCatalog();
COSBase base = root.getCOSObject().getItem(COSName.OUTPUT_INTENTS);
if (base == null) {
@@ -807,4 +818,31 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants {
throw ErrorExtractor.searchPdfAsError(e, status);
}
}
+
+ private String getPDFAVersion(PDDocument doc) {
+ try {
+ PDDocumentCatalog cat = doc.getDocumentCatalog();
+ PDMetadata metadata = cat.getMetadata();
+
+ if(metadata != null) {
+ DomXmpParser xmpParser = new DomXmpParser();
+ XMPMetadata xmpMetadata = xmpParser.parse(metadata.exportXMPMetadata());
+ if(xmpMetadata != null) {
+ PDFAIdentificationSchema pdfaIdentificationSchema = xmpMetadata.getPDFIdentificationSchema();
+ if (pdfaIdentificationSchema != null) {
+ Integer pdfaversion = pdfaIdentificationSchema.getPart();
+ String conformance = pdfaIdentificationSchema.getConformance();
+ logger.info("Detected PDF/A Version: {} - {}", pdfaversion, conformance);
+
+ if(pdfaversion != null) {
+ return String.valueOf(pdfaversion);
+ }
+ }
+ }
+ }
+ } catch (Throwable e) {
+ logger.warn("Failed to determine PDF/A Version!", e);
+ }
+ return null;
+ }
}
diff --git a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFAsTemplateCreator.java b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFAsTemplateCreator.java
index b8c15119..b07e6ed5 100644
--- a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFAsTemplateCreator.java
+++ b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFAsTemplateCreator.java
@@ -23,11 +23,10 @@
******************************************************************************/
package at.gv.egiz.pdfas.lib.impl.stamping.pdfbox2;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
+import java.io.*;
+import at.gv.egiz.pdfas.common.settings.SignatureProfileSettings;
+import at.gv.egiz.pdfas.lib.impl.stamping.TableFactory;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
@@ -143,7 +142,9 @@ public class PDFAsTemplateCreator extends PDFTemplateCreator {
null, innerFormName, properties);
this.pdfBuilder.createVisualSignature(template);
this.pdfBuilder.createWidgetDictionary(pdSignatureField, holderFormResources);
-
+
+
+
ByteArrayInputStream in = null;
//COSDocument doc = pdfStructure.getVisualSignature();
@@ -152,7 +153,31 @@ public class PDFAsTemplateCreator extends PDFTemplateCreator {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
template.save(baos);
baos.close();
- in = new ByteArrayInputStream(baos.toByteArray());
+
+ SignatureProfileSettings signatureProfileSettings =
+ this.pdfBuilder.signatureProfileSettings;
+
+ boolean requirePDFA3 = signatureProfileSettings.isPDFA3();
+
+ if(requirePDFA3) {
+
+ //FileOutputStream fos = new FileOutputStream("/tmp/signature.pdf");
+ //fos.write(baos.toByteArray());
+ //fos.close();
+
+ PDDocument cidSetRemoved = PDDocument.load(baos.toByteArray());
+ try {
+ this.pdfBuilder.removeCidSet(cidSetRemoved);
+ baos.reset();
+ baos = new ByteArrayOutputStream();
+ cidSetRemoved.save(baos);
+ baos.close();
+ } finally {
+ cidSetRemoved.close();
+ }
+ }
+
+ in = new ByteArrayInputStream(baos.toByteArray());
logger.debug("stream returning started, size= " + in.available());
diff --git a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFAsVisualSignatureBuilder.java b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFAsVisualSignatureBuilder.java
index a33a46e7..d283c3e3 100644
--- a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFAsVisualSignatureBuilder.java
+++ b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFAsVisualSignatureBuilder.java
@@ -30,22 +30,15 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.MessageDigest;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
+import at.gv.egiz.pdfas.common.settings.SignatureProfileSettings;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.io.IOUtils;
import org.apache.pdfbox.cos.COSArray;
import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSName;
-import org.apache.pdfbox.pdfparser.PDFParser;
-import org.apache.pdfbox.pdfparser.PDFStreamParser;
-import org.apache.pdfbox.pdmodel.PDDocument;
-import org.apache.pdfbox.pdmodel.PDPage;
-import org.apache.pdfbox.pdmodel.PDPageContentStream;
-import org.apache.pdfbox.pdmodel.PDResources;
+import org.apache.pdfbox.pdmodel.*;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.common.PDStream;
import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
@@ -59,6 +52,7 @@ import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDVisibleS
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.apache.pdfbox.pdmodel.font.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -76,15 +70,18 @@ public class PDFAsVisualSignatureBuilder extends PDVisibleSigBuilder implements
private PDFAsVisualSignatureProperties properties;
private PDFAsVisualSignatureDesigner designer;
private ISettings settings;
+ public SignatureProfileSettings signatureProfileSettings;
private PDResources innerFormResources;
private Map<String, ImageObject> images = new HashMap<String, ImageObject>();
public PDFAsVisualSignatureBuilder(
PDFAsVisualSignatureProperties properties, ISettings settings,
- PDFAsVisualSignatureDesigner designer) {
+ PDFAsVisualSignatureDesigner designer,
+ SignatureProfileSettings signatureProfileSettings) {
this.properties = properties;
this.settings = settings;
this.designer = designer;
+ this.signatureProfileSettings = signatureProfileSettings;
}
@Override
@@ -657,4 +654,33 @@ public class PDFAsVisualSignatureBuilder extends PDVisibleSigBuilder implements
this.getStructure().getTemplate().close();
}
+ public void removeCidSet(PDDocument document) throws IOException {
+
+ PDDocumentCatalog catalog = document.getDocumentCatalog();
+
+ COSName cidSet = COSName.getPDFName("CIDSet");
+
+ Iterator<PDPage> pdPageIterator = catalog.getPages().iterator();
+ while(pdPageIterator.hasNext()) {
+
+ PDPage page = pdPageIterator.next();
+
+ Iterator<COSName> cosNameIterator = page.getResources().getFontNames().iterator();
+ while (cosNameIterator.hasNext()) {
+ COSName fontName = cosNameIterator.next();
+ PDFont pdFont = page.getResources().getFont(fontName);
+
+ if (pdFont instanceof PDType0Font) {
+ PDType0Font typedFont = (PDType0Font) pdFont;
+
+ if (typedFont.getDescendantFont() != null) {
+ if (typedFont.getDescendantFont().getFontDescriptor() != null) {
+ typedFont.getDescendantFont().getFontDescriptor().getCOSObject().removeItem(cidSet);
+ }
+ }
+ }
+ }
+ }
+ }
+
}
diff --git a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFAsVisualSignatureProperties.java b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFAsVisualSignatureProperties.java
index db96767a..adfd6694 100644
--- a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFAsVisualSignatureProperties.java
+++ b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFAsVisualSignatureProperties.java
@@ -112,7 +112,7 @@ public class PDFAsVisualSignatureProperties extends PDVisibleSigProperties {
@Override
public void buildSignature() throws IOException {
- PDFAsVisualSignatureBuilder builder = new PDFAsVisualSignatureBuilder(this, this.settings, designer);
+ PDFAsVisualSignatureBuilder builder = new PDFAsVisualSignatureBuilder(this, this.settings, designer, this.signatureProfileSettings);
PDFAsTemplateCreator creator = new PDFAsTemplateCreator(builder);
try {
setVisibleSignature(creator.buildPDF(designer, this.origDoc));
diff --git a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFBoxFont.java b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFBoxFont.java
index 8795907d..9c848ff9 100644
--- a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFBoxFont.java
+++ b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/PDFBoxFont.java
@@ -24,8 +24,11 @@
package at.gv.egiz.pdfas.lib.impl.stamping.pdfbox2;
import java.io.File;
+import java.io.FileInputStream;
import java.io.IOException;
+import at.gv.egiz.pdfas.common.settings.SignatureProfileSettings;
+import at.gv.egiz.pdfas.lib.impl.stamping.TableFactory;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType0Font;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
@@ -158,6 +161,7 @@ public class PDFBoxFont {
private PDFont generateTTF(String fonttype, PDFBOXObject pdfObject)
throws IOException {
+
ttfFontDesc = fonttype;
String fontName = fonttype.replaceFirst("TTF:", "");
String fontPath = this.settings.getWorkingDirectory() + File.separator
@@ -165,6 +169,7 @@ public class PDFBoxFont {
logger.debug("Font from: \"" + fontPath + "\".");
+
PDFAsFontCache fontCache = pdfObject.getSigBlockFontCache();
if(fontCache.contains(fontPath)){
@@ -185,8 +190,14 @@ public class PDFBoxFont {
// }
logger.debug("Instantiating new font.");
-
- PDType0Font font = PDType0Font.load(pdfObject.getDocument(), new File(fontPath));
+
+/*
+ SignatureProfileSettings signatureProfileSettings = TableFactory
+ .createProfile(pdfObject.getStatus().getRequestedSignature().getSignatureProfileID(), pdfObject.getStatus().getSettings());
+
+ boolean requirePDFA3 = signatureProfileSettings.isPDFA3();
+*/
+ PDType0Font font = PDType0Font.load(pdfObject.getDocument(), new FileInputStream(fontPath));
fontCache.addFont(fontPath,font);
return font;
diff --git a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/TableDrawUtils.java b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/TableDrawUtils.java
index 5162b287..df8d3e3b 100644
--- a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/TableDrawUtils.java
+++ b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox2/TableDrawUtils.java
@@ -230,8 +230,10 @@ public class TableDrawUtils {
drawDebugLineString(contentStream, tx, ty, maxWidth, textHeight, descent, settings);
contentStream.beginText();
-
-
+
+ contentStream.setFont(textFont, fontSize);
+ contentStream.newLineAtOffset(tx, (ty - fontSize + (descent * (-1))));
+ /*
if (formResources.getFont(COSName.getPDFName(textFont.getName())) != null) {
String fontID = getFontID(textFont, formResources);
logger.debug("Using Font: " + fontID);
@@ -246,11 +248,17 @@ public class TableDrawUtils {
contentStream.moveTextPositionByAmount(tx, (ty - fontSize + (descent * (-1))));
contentStream.appendRawCommands(fontSize + " TL\n");
-
+ */
+
+ if(textFont.willBeSubset()) {
+ logger.debug("Font will be subset!");
+ }
+
for (int k = 0; k < tlines.length; k++) {
contentStream.showText(tlines[k]);
if (k < tlines.length - 1) {
- contentStream.appendRawCommands("T*\n");
+ contentStream.newLineAtOffset(0, -1 * fontSize );
+ //contentStream.appendRawCommands("T*\n");
}
}