diff options
Diffstat (limited to 'pdf-as-pdfbox-2/src/main/java/at')
3 files changed, 178 insertions, 43 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/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 | 
