aboutsummaryrefslogtreecommitdiff
path: root/pdf-as-pdfbox-2/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'pdf-as-pdfbox-2/src/main')
-rw-r--r--pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/placeholder/PDFBoxPlaceholderExtractor.java32
-rw-r--r--pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/placeholder/SignaturePlaceholderExtractor.java95
-rw-r--r--pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/utils/PdfBoxUtils.java22
-rw-r--r--pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/signing/pdfbox2/PADESPDFBOXSigner.java94
4 files changed, 194 insertions, 49 deletions
diff --git a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/placeholder/PDFBoxPlaceholderExtractor.java b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/placeholder/PDFBoxPlaceholderExtractor.java
index 256400a0..63b006bf 100644
--- a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/placeholder/PDFBoxPlaceholderExtractor.java
+++ b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/placeholder/PDFBoxPlaceholderExtractor.java
@@ -1,19 +1,47 @@
package at.gv.egiz.pdfas.lib.impl.pdfbox2.placeholder;
+import at.gv.egiz.pdfas.common.exceptions.PDFIOException;
import at.gv.egiz.pdfas.common.exceptions.PdfAsException;
import at.gv.egiz.pdfas.lib.impl.pdfbox2.PDFBOXObject;
import at.gv.egiz.pdfas.lib.impl.placeholder.PlaceholderExtractor;
import at.gv.egiz.pdfas.lib.impl.placeholder.SignaturePlaceholderData;
import at.gv.egiz.pdfas.lib.impl.status.PDFObject;
+import java.io.IOException;
+import java.util.List;
+
public class PDFBoxPlaceholderExtractor implements PlaceholderExtractor {
+
@Override
public SignaturePlaceholderData extract(PDFObject doc, String placeholderId, int matchMode) throws PdfAsException {
if (doc instanceof PDFBOXObject) {
PDFBOXObject object = (PDFBOXObject) doc;
- return SignaturePlaceholderExtractor.extract(object.getDocument(),
- placeholderId, matchMode);
+ try {
+ SignaturePlaceholderExtractor extractor = new SignaturePlaceholderExtractor(placeholderId,
+ matchMode, object.getDocument());
+ return extractor.extract(object.getDocument(),
+ placeholderId, matchMode);
+ } catch (IOException | ClassNotFoundException | InstantiationException | IllegalAccessException e2) {
+ throw new PDFIOException("error.pdf.io.04", e2);
+ }
+
+ }
+ throw new PdfAsException("INVALID STATE");
+ }
+
+ @Override
+ public List<SignaturePlaceholderData> extractList(PDFObject doc, String placeholderId, int matchMode) throws PdfAsException {
+ if (doc instanceof PDFBOXObject) {
+ PDFBOXObject object = (PDFBOXObject) doc;
+ try {
+ SignaturePlaceholderExtractor extractor = new SignaturePlaceholderExtractor(placeholderId,
+ matchMode, object.getDocument());
+ return extractor.extractList(object.getDocument(),
+ placeholderId, matchMode);
+ } catch (IOException | ClassNotFoundException | InstantiationException | IllegalAccessException e2) {
+ throw new PDFIOException("error.pdf.io.04", e2);
+ }
}
throw new PdfAsException("INVALID STATE");
}
diff --git a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/placeholder/SignaturePlaceholderExtractor.java b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/placeholder/SignaturePlaceholderExtractor.java
index 8a2c1cff..4031d07f 100644
--- a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/placeholder/SignaturePlaceholderExtractor.java
+++ b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/placeholder/SignaturePlaceholderExtractor.java
@@ -103,11 +103,11 @@ public class SignaturePlaceholderExtractor extends PDFStreamEngine implements Pl
private static Logger logger = LoggerFactory
.getLogger(SignaturePlaceholderExtractor.class);
- private static List<SignaturePlaceholderData> placeholders = new ArrayList<>();
+ private List<SignaturePlaceholderData> placeholders = new ArrayList<>();
private int currentPage = 0;
private PDDocument doc;
- private SignaturePlaceholderExtractor(String placeholderId,
+ protected SignaturePlaceholderExtractor(String placeholderId,
int placeholderMatchMode, PDDocument doc) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {
super();
@@ -126,9 +126,9 @@ public class SignaturePlaceholderExtractor extends PDFStreamEngine implements Pl
this.doc = doc;
}
- public static List<SignaturePlaceholderData> getPlaceholders() {
- return placeholders;
- }
+// public static List<SignaturePlaceholderData> getPlaceholders() {
+// return placeholders;
+// }
/**
@@ -136,38 +136,36 @@ public class SignaturePlaceholderExtractor extends PDFStreamEngine implements Pl
* additional info.<br/>
* Searches only for the first placeholder page after page from top.
*
- * @param inputStream
* @return all available info from the first found placeholder.
- * @throws PDFDocumentException
+ * @throws PdfAsException
* if the document could not be read.
* @throws PlaceholderExtractionException
* if STRICT matching mode was requested and no suitable
* placeholder could be found.
*/
- public static SignaturePlaceholderData extract(PDDocument doc,
+ public SignaturePlaceholderData extract(PDDocument doc,
String placeholderId, int matchMode) throws PdfAsException {
SignaturePlaceholderContext.setSignaturePlaceholderData(null);
-
- SignaturePlaceholderExtractor extractor;
- try {
- extractor = new SignaturePlaceholderExtractor(placeholderId,
- matchMode, doc);
- } catch (IOException | ClassNotFoundException | InstantiationException | IllegalAccessException e2) {
- throw new PDFIOException("error.pdf.io.04", e2);
- }
+// SignaturePlaceholderExtractor extractor;
+// try {
+// extractor = new SignaturePlaceholderExtractor(placeholderId,
+// matchMode, doc);
+// } catch (IOException | ClassNotFoundException | InstantiationException | IllegalAccessException e2) {
+// throw new PDFIOException("error.pdf.io.04", e2);
+// }
int pageNr = 0;
for(PDPage page : doc.getPages()){
pageNr++;
try {
- extractor.setCurrentPage(pageNr);
+ setCurrentPage(pageNr);
if(page.getContents() != null && page.getResources() != null && page.getContentStreams() != null) {
- extractor.processPage(page); //TODO: pdfbox2 - right?
+ processPage(page); //TODO: pdfbox2 - right?
}
SignaturePlaceholderData ret = matchPlaceholderPage(
- extractor.placeholders, placeholderId, matchMode);
+ placeholders, placeholderId, matchMode);
if (ret != null) {
SignaturePlaceholderContext
.setSignaturePlaceholderData(ret);
@@ -179,9 +177,9 @@ public class SignaturePlaceholderExtractor extends PDFStreamEngine implements Pl
throw new PDFIOException("error.pdf.io.04", e);
}
}
- if (extractor.placeholders.size() > 0) {
+ if (placeholders.size() > 0) {
SignaturePlaceholderData ret = matchPlaceholderDocument(
- extractor.placeholders, placeholderId, matchMode);
+ placeholders, placeholderId, matchMode);
SignaturePlaceholderContext.setSignaturePlaceholderData(ret);
return ret;
}
@@ -193,7 +191,56 @@ public class SignaturePlaceholderExtractor extends PDFStreamEngine implements Pl
return null;
}
- private static SignaturePlaceholderData matchPlaceholderDocument(
+ public List<SignaturePlaceholderData> extractList(PDDocument doc,
+ String placeholderId, int matchMode) throws PdfAsException {
+ SignaturePlaceholderContext.setSignaturePlaceholderData(null);
+// List<SignaturePlaceholderData> placeholders = new ArrayList<>();
+// SignaturePlaceholderExtractor extractor;
+// try {
+// extractor = new SignaturePlaceholderExtractor(placeholderId,
+// matchMode, doc);
+// } catch (IOException | ClassNotFoundException | InstantiationException | IllegalAccessException e2) {
+// throw new PDFIOException("error.pdf.io.04", e2);
+// }
+
+ int pageNr = 0;
+ for(PDPage page : doc.getPages()){
+ pageNr++;
+
+ try {
+ setCurrentPage(pageNr);
+ if(page.getContents() != null && page.getResources() != null && page.getContentStreams() != null) {
+ processPage(page); //TODO: pdfbox2 - right?
+
+ }
+ SignaturePlaceholderData ret = matchPlaceholderPage(
+ placeholders, placeholderId, matchMode);
+ if (ret != null) {
+ SignaturePlaceholderContext
+ .setSignaturePlaceholderData(ret);
+ return placeholders;
+ }
+ } catch (IOException e1) {
+ throw new PDFIOException("error.pdf.io.04", e1);
+ } catch(Throwable e) {
+ throw new PDFIOException("error.pdf.io.04", e);
+ }
+ }
+ if (placeholders.size() > 0) {
+ SignaturePlaceholderData ret = matchPlaceholderDocument(
+ placeholders, placeholderId, matchMode);
+ SignaturePlaceholderContext.setSignaturePlaceholderData(ret);
+ return placeholders;
+ }
+ // no placeholders found, apply strict mode if set
+ if (matchMode == PLACEHOLDER_MATCH_MODE_STRICT) {
+ throw new PlaceholderExtractionException("error.pdf.stamp.09");
+ }
+
+ return null;
+ }
+
+ private SignaturePlaceholderData matchPlaceholderDocument(
List<SignaturePlaceholderData> placeholders, String placeholderId,
int matchMode) throws PlaceholderExtractionException {
@@ -247,7 +294,7 @@ public class SignaturePlaceholderExtractor extends PDFStreamEngine implements Pl
return null;
}
- private static SignaturePlaceholderData matchPlaceholderPage(
+ private SignaturePlaceholderData matchPlaceholderPage(
List<SignaturePlaceholderData> placeholders, String placeholderId,
int matchMode) {
@@ -266,6 +313,8 @@ public class SignaturePlaceholderExtractor extends PDFStreamEngine implements Pl
return null;
}
+
+
private void setCurrentPage(int pageNr) {
this.currentPage = pageNr;
}
diff --git a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/utils/PdfBoxUtils.java b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/utils/PdfBoxUtils.java
index 1a6499ac..112d9a86 100644
--- a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/utils/PdfBoxUtils.java
+++ b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/utils/PdfBoxUtils.java
@@ -16,16 +16,26 @@ public class PdfBoxUtils {
public static void checkPDFPermissions(PDDocument doc)
throws PdfAsValidationException {
-
AccessPermission accessPermission = doc.getCurrentAccessPermission();
- if (doc.isEncrypted()) {
- throw new PdfAsValidationException("error.pdf.sig.12", null);
- }
+ if (doc.isEncrypted() || !accessPermission.isOwnerPermission()) {
+ //canFillInForm()
+ //This will tell if the user can fill in interactive form fields (including signature fields) even if
+ // canModifyAnnotations() returns false.
- if (!accessPermission.isOwnerPermission()) {
- throw new PdfAsValidationException("error.pdf.sig.12", null);
+ //canModifyAnnotations()
+ //This will tell if the user can add or modify text annotations and fill in interactive forms fields and, if
+ // canModify() returns true, create or modify interactive form fields (including signature fields).
+ if ((accessPermission.canModify() && accessPermission.canModifyAnnotations())
+ || accessPermission.canFillInForm()) {
+ logger.debug("Document is protected, but Signing is allowed");
+
+ } else {
+ throw new PdfAsValidationException("error.pdf.sig.12", null);
+
+ }
}
+
}
public static int countSignatures(PDDocument doc, String sigName) {
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 0a32d7a5..3cf0853f 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
@@ -64,6 +64,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.COSObjectable;
import org.apache.pdfbox.pdmodel.common.PDMetadata;
import org.apache.pdfbox.pdmodel.common.PDNumberTreeNode;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
@@ -96,7 +97,10 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Calendar;
+import java.util.Collections;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants {
@@ -157,9 +161,11 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants {
signature.setFilter(COSName.getPDFName(signer.getPDFFilter()));
signature.setSubFilter(COSName.getPDFName(signer.getPDFSubFilter()));
- SignaturePlaceholderData signaturePlaceholderDataInit = PlaceholderFilter.checkPlaceholderSignatureLocation(pdfObject.getStatus(), pdfObject.getStatus().getSettings(), placeholder_id);
+// SignaturePlaceholderData signaturePlaceholderDataInit =
+ placeholders =PlaceholderFilter.checkPlaceholderSignatureLocationList(pdfObject.getStatus(),
+ pdfObject.getStatus().getSettings(), placeholder_id);
- placeholders = SignaturePlaceholderExtractor.getPlaceholders();
+// placeholders = SignaturePlaceholderExtractor.getPlaceholders();
availablePlaceholders = listAvailablePlaceholders(placeholders, existingSignatureLocations(doc));
@@ -211,15 +217,16 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants {
}
SignatureProfileSettings signatureProfileSettings = TableFactory
.createProfile(requestedSignature.getSignatureProfileID(), pdfObject.getStatus().getSettings());
- //Check if input document is PDF-A conform
+
+ //Check if input document is PDF-A conform
if (signatureProfileSettings.isPDFA()) {
DataSource origDoc = pdfObject.getOriginalDocument();
InputStream stream = origDoc.getInputStream();
//Run PreflightParser for checking conformity//
//runPDFAPreflight(origDoc);
}
-
ValueResolver resolver = new ValueResolver(requestedSignature, pdfObject.getStatus());
+
String signerName = resolver.resolve("SIG_SUBJECT", signatureProfileSettings.getValue("SIG_SUBJECT"),
signatureProfileSettings);
@@ -508,12 +515,13 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants {
}
}
-
+
PDStructureElement sigBlock = new PDStructureElement("Form", docElement);
// create object dictionary and add as child element
COSDictionary objectDic = new COSDictionary();
objectDic.setName("Type", "OBJR");
+
objectDic.setItem("Pg", signatureField.getWidget().getPage());
objectDic.setItem("Obj", signatureField.getWidget());
@@ -539,7 +547,6 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants {
// Modify number tree
PDNumberTreeNode ntn = structureTreeRoot.getParentTree();
- int parentTreeNextKey = structureTreeRoot.getParentTreeNextKey();
if (ntn == null) {
ntn = new PDNumberTreeNode(objectDic, null);
logger.info("No number-tree-node found!");
@@ -547,9 +554,10 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants {
COSArray ntnKids = (COSArray) ntn.getCOSObject().getDictionaryObject(COSName.KIDS);
COSArray ntnNumbers = (COSArray) ntn.getCOSObject().getDictionaryObject(COSName.NUMS);
-
- if(ntnNumbers == null && ntnKids != null){//no number array, so continue with the kids array
-
+
+ int parentTreeNextKey = getParentTreeNextKey(structureTreeRoot);
+
+ if(ntnNumbers == null && ntnKids != null){//no number array, so continue with the kids array
//create dictionary with limits and nums array
COSDictionary pTreeEntry = new COSDictionary();
COSArray limitsArray = new COSArray();
@@ -628,7 +636,7 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants {
byte[] outputDocument = bos.toByteArray();
pdfObject.setSignedDocument(outputDocument);
}
- /* Check if resulting pdf is PDF-A conform */
+ /* Check if resulting pdf is PDF-A conform */
if (signatureProfileSettings.isPDFA()) {
runPDFAPreflight(new ByteArrayDataSource(pdfObject.getSignedDocument()));
}
@@ -653,7 +661,7 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants {
if (doc != null) {
try {
doc.close();
- SignaturePlaceholderExtractor.getPlaceholders().clear();
+ //SignaturePlaceholderExtractor.getPlaceholders().clear();
} catch (IOException e) {
logger.debug("Failed to close COS Doc!", e);
// Ignore
@@ -663,7 +671,23 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants {
}
}
- /**
+ private int getParentTreeNextKey(PDStructureTreeRoot structureTreeRoot) throws IOException {
+ int nextKey = structureTreeRoot.getParentTreeNextKey();
+ if (nextKey < 0) {
+ Map<Integer, COSObjectable> destNumberTreeAsMap = getNumberTreeAsMap(structureTreeRoot.getParentTree());
+ if (destNumberTreeAsMap.isEmpty()) {
+ nextKey = 0;
+
+ } else {
+ nextKey = Collections.max(destNumberTreeAsMap.keySet()) + 1;
+
+ }
+ }
+
+ return nextKey;
+ }
+
+ /**
* Check via PreFlightParser if PDF-Document is a valid PDFA1
* @param signedDocument: signed Document
* @throws PdfAsException
@@ -914,16 +938,25 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants {
if(placeholders!=null) {
for(int i = 0; i < placeholders.size(); ++i) {
//take smallest id
- if(!existingPlaceholders.contains(placeholders.get(i).getPlaceholderName())) {
+ if(!existingPlaceholders.contains(placeholders.get(i).getPlaceholderName())) {
SignaturePlaceholderData spd = placeholders.get(i);
if (spd.getId() != null) {
if(result == null) {
result = spd;
} else {
- String currentID = result.getId();
- String testID = spd.getId();
- if(testID.compareToIgnoreCase(currentID) < 0) {
- result = spd;
+ try{
+ int currentID = Integer.parseInt(result.getId());
+ int testID = Integer.parseInt(spd.getId());
+ if(testID < currentID) {
+ result = spd;
+ }
+ }catch(Exception e){
+ //fallback to string compare
+ String currentID = result.getId();
+ String testID = spd.getId();
+ if(testID.compareToIgnoreCase(currentID) < 0) {
+ result = spd;
+ }
}
}
}
@@ -936,7 +969,7 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants {
//find first placeholder_id
public List<SignaturePlaceholderData> listAvailablePlaceholders(List<SignaturePlaceholderData> placeholders, List<String> existingPlaceholders) {
- List<SignaturePlaceholderData> result = null;
+ List<SignaturePlaceholderData> result = new ArrayList<>();
if(placeholders!=null) {
for(int i = 0; i < placeholders.size(); ++i) {
@@ -948,4 +981,29 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants {
}
return result;
}
+
+ static Map<Integer, COSObjectable> getNumberTreeAsMap(PDNumberTreeNode tree)
+ throws IOException
+ {
+ Map<Integer, COSObjectable> numbers = tree.getNumbers();
+ if (numbers == null)
+ {
+ numbers = new LinkedHashMap<>();
+ }
+ else
+ {
+ // must copy because the map is read only
+ numbers = new LinkedHashMap<>(numbers);
+ }
+ List<PDNumberTreeNode> kids = tree.getKids();
+ if (kids != null)
+ {
+ for (PDNumberTreeNode kid : kids)
+ {
+ numbers.putAll(getNumberTreeAsMap(kid));
+ }
+ }
+ return numbers;
+ }
+
} \ No newline at end of file