diff options
10 files changed, 532 insertions, 514 deletions
diff --git a/pdf-as-cli/src/main/java/at/gv/egiz/pdfas/cli/Main.java b/pdf-as-cli/src/main/java/at/gv/egiz/pdfas/cli/Main.java index 34e384ad..dcd94b77 100644 --- a/pdf-as-cli/src/main/java/at/gv/egiz/pdfas/cli/Main.java +++ b/pdf-as-cli/src/main/java/at/gv/egiz/pdfas/cli/Main.java @@ -28,6 +28,7 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.util.Iterator; import java.util.List; +import java.util.Scanner; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; @@ -183,6 +184,8 @@ public class Main { public static void main(String[] args) { // create the command line parser + + CommandLineParser parser = new GnuParser(); ModeOfOperation mode = ModeOfOperation.INVALID; try { @@ -218,7 +221,6 @@ public class Main { } else if (mode == ModeOfOperation.VERIFY) { perform_verify(cli); } - } catch (ParseException e) { System.err.println("Invalid arguments: " + e.getMessage()); usage(); 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 7946f966..25e57188 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 @@ -95,22 +95,23 @@ public class PdfAsImpl implements PdfAs, IConfigurationConstants { } } - if(parameter.getDataSource() == null || parameter.getDataSource().getByteData() == null) { + if (parameter.getDataSource() == null + || parameter.getDataSource().getByteData() == null) { throw new PdfAsValidationException("error.pdf.sig.10", null); } - - if(parameter.getOutput() == null) { + + if (parameter.getOutput() == null) { throw new PdfAsValidationException("error.pdf.sig.11", null); } - - try { - PDDocument doc = PDDocument.load(new ByteArrayInputStream(parameter.getDataSource().getByteData())); - PDFUtils.checkPDFPermissions(doc); - doc.close(); - } catch(IOException e) { - throw new PdfAsValidationException("error.pdf.sig.12", null, e); - } - + + /* + * try { PDDocument doc = PDDocument.load(new + * ByteArrayInputStream(parameter.getDataSource().getByteData())); + * PDFUtils.checkPDFPermissions(doc); doc.close(); } catch(IOException + * e) { throw new PdfAsValidationException("error.pdf.sig.12", null, e); + * } + */ + // TODO: verify Sign Parameter } @@ -120,8 +121,9 @@ public class PdfAsImpl implements PdfAs, IConfigurationConstants { if (!(parameter.getConfiguration() instanceof ISettings)) { throw new PdfAsSettingsException("Invalid settings object!"); } - - if(parameter.getDataSource() == null || parameter.getDataSource().getByteData() == null) { + + if (parameter.getDataSource() == null + || parameter.getDataSource().getByteData() == null) { throw new PdfAsValidationException("error.pdf.verify.01", null); } @@ -142,8 +144,16 @@ public class PdfAsImpl implements PdfAs, IConfigurationConstants { ISettings settings = (ISettings) parameter.getConfiguration(); OperationStatus status = new OperationStatus(settings, parameter); - //PlaceholderConfiguration placeholderConfiguration = status - // .getPlaceholderConfiguration(); + + // set Original PDF Document Data + status.getPdfObject().setOriginalDocument( + parameter.getDataSource().getByteData()); + + PDDocument doc = status.getPdfObject().getDocument(); + PDFUtils.checkPDFPermissions(doc); + + // PlaceholderConfiguration placeholderConfiguration = status + // .getPlaceholderConfiguration(); RequestedSignature requestedSignature = new RequestedSignature( status); @@ -164,11 +174,7 @@ public class PdfAsImpl implements PdfAs, IConfigurationConstants { // status // .getSignatureProfileConfiguration(signatureProfileID); - // set Original PDF Document Data - status.getPdfObject().setOriginalDocument( - parameter.getDataSource().getByteData()); - - //this.stampPdf(status); + // this.stampPdf(status); // Create signature IPdfSigner signer = PdfSignerFactory.createPdfSigner(); @@ -272,7 +278,7 @@ public class PdfAsImpl implements PdfAs, IConfigurationConstants { if (verifyFilter != null) { List<VerifyResult> results = verifyFilter.verify( contentData.toByteArray(), - content.getBytes(), + content.getBytes(), parameter.getVerificationTime(), bytes); if (results != null && !results.isEmpty()) { result.addAll(results); @@ -308,7 +314,7 @@ public class PdfAsImpl implements PdfAs, IConfigurationConstants { throws PdfAsException { verifySignParameter(parameter); - + StatusRequestImpl request = new StatusRequestImpl(); try { @@ -355,7 +361,7 @@ public class PdfAsImpl implements PdfAs, IConfigurationConstants { status.getSignParamter().getDataSource().getByteData()); // STAMPER! - //stampPdf(status); + // stampPdf(status); request.setNeedCertificate(false); status.setSigningDate(Calendar.getInstance()); diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/placeholder/PlaceholderFilter.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/placeholder/PlaceholderFilter.java index a4d2c7aa..8e0171fb 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/placeholder/PlaceholderFilter.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/placeholder/PlaceholderFilter.java @@ -1,6 +1,5 @@ package at.gv.egiz.pdfas.lib.impl.placeholder; -import java.io.ByteArrayInputStream; import java.io.IOException; import at.gv.egiz.pdfas.common.exceptions.PdfAsException; @@ -16,8 +15,7 @@ public class PlaceholderFilter implements IConfigurationConstants { if (status.getPlaceholderConfiguration().isGlobalPlaceholderEnabled()) { SignaturePlaceholderData signaturePlaceholderData = SignaturePlaceholderExtractor - .extract(new ByteArrayInputStream(status.getPdfObject() - .getOriginalDocument()), null, 1); + .extract(status.getPdfObject().getDocument(), null, 1); return signaturePlaceholderData; /* diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/placeholder/SignaturePlaceholderExtractor.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/placeholder/SignaturePlaceholderExtractor.java index 816ca04f..93162bd3 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/placeholder/SignaturePlaceholderExtractor.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/placeholder/SignaturePlaceholderExtractor.java @@ -89,8 +89,6 @@ import com.google.zxing.common.HybridBinarizer; ////// - - /** * Extract all relevant information from a placeholder image. * @@ -98,279 +96,276 @@ import com.google.zxing.common.HybridBinarizer; * */ public class SignaturePlaceholderExtractor extends PDFStreamEngine { - /** - * The log. - */ - private static Log log = LogFactory.getLog(SignaturePlaceholderExtractor.class); - - public static final String QR_PLACEHOLDER_IDENTIFIER = "PDF-AS-POS"; - public static final int PLACEHOLDER_MATCH_MODE_STRICT = 0; - public static final int PLACEHOLDER_MATCH_MODE_MODERATE = 1; - public static final int PLACEHOLDER_MATCH_MODE_LENIENT = 2; - - private List<SignaturePlaceholderData> placeholders = new Vector<SignaturePlaceholderData>(); - private int currentPage = 0; - - private SignaturePlaceholderExtractor(String placeholderId, int placeholderMatchMode) throws IOException { - super(ResourceLoader.loadProperties("placeholder/pdfbox-reader.properties", - true)); - } - - /** - * Search the document for placeholder images and possibly included - * 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 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(InputStream inputStream, String placeholderId, int matchMode) - throws PdfAsException { - SignaturePlaceholderContext.setSignaturePlaceholderData(null); - PDDocument doc = null; - try - { - try { - doc = PDDocument.load(inputStream); - } catch (IOException e) { - throw new PDFIOException("error.pdf.io.04", e); - } - SignaturePlaceholderExtractor extractor; - try - { - extractor = new SignaturePlaceholderExtractor(placeholderId, matchMode); - } catch (IOException e2) { - throw new PDFIOException("error.pdf.io.04", e2); - } - List<?> pages = doc.getDocumentCatalog().getAllPages(); - Iterator<?> iter = pages.iterator(); - int pageNr = 0; - while (iter.hasNext()) { - pageNr++; - PDPage page = (PDPage) iter.next(); - try { - extractor.setCurrentPage(pageNr); - extractor.processStream( page, page.findResources(), page.getContents().getStream() ); - SignaturePlaceholderData ret = matchPlaceholderPage(extractor.placeholders, placeholderId, matchMode); - if (ret != null){ - SignaturePlaceholderContext.setSignaturePlaceholderData(ret); - return ret; - } - } catch (IOException e1) { - throw new PDFIOException("error.pdf.io.04", e1); - } - - } - if (extractor.placeholders.size() > 0){ - SignaturePlaceholderData ret = matchPlaceholderDocument(extractor.placeholders, placeholderId, matchMode); - SignaturePlaceholderContext.setSignaturePlaceholderData(ret); - return ret; - } - // no placeholders found, apply strict mode if set - if (matchMode == PLACEHOLDER_MATCH_MODE_STRICT) { - throw new PlaceholderExtractionException("error.pdf.stamp.09"); - } - - return null; - } finally { - if (doc != null) - try { - doc.close(); - } catch (IOException e) { - log.debug("Could not close document.", e); - } - } - - } - - private static SignaturePlaceholderData matchPlaceholderDocument( - List<SignaturePlaceholderData> placeholders, String placeholderId, int matchMode) throws PlaceholderExtractionException { - - if (matchMode == PLACEHOLDER_MATCH_MODE_STRICT) - throw new PlaceholderExtractionException("error.pdf.stamp.09"); - - if (placeholders.size() == 0) - return null; - - for (int i = 0; i < placeholders.size(); i++) - { - SignaturePlaceholderData spd = placeholders.get(i); - if (spd.getId() == null) - return spd; - } - - if (matchMode == PLACEHOLDER_MATCH_MODE_LENIENT) - return placeholders.get(0); - - return null; - } - - private static SignaturePlaceholderData matchPlaceholderPage(List<SignaturePlaceholderData> placeholders, - String placeholderId, int matchMode) { - if (placeholders.size() == 0) - return null; - for (int i = 0; i < placeholders.size(); i++) - { - SignaturePlaceholderData data = placeholders.get(i); - if (placeholderId != null && placeholderId.equals(data.getId())) - return data; - if (placeholderId == null && data.getId() == null) - return data; - } - return null; - } - - private void setCurrentPage(int pageNr) { - this.currentPage = pageNr; - } - - @Override - protected void processOperator(PDFOperator operator, List<COSBase> arguments) throws IOException - { - String operation = operator.getOperation(); - if( operation.equals( "Do" ) ) - { - COSName objectName = (COSName)arguments.get( 0 ); - Map<?, ?> xobjects = getResources().getXObjects(); - PDXObject xobject = (PDXObject)xobjects.get( objectName.getName() ); - if( xobject instanceof PDXObjectImage ) - { - try - { - PDXObjectImage image = (PDXObjectImage)xobject; - SignaturePlaceholderData data = checkImage(image); - if (data != null) - { - PDPage page = getCurrentPage(); - Matrix ctm = getGraphicsState().getCurrentTransformationMatrix(); - double rotationInRadians = (page.findRotation() * Math.PI)/180; - - AffineTransform rotation = new AffineTransform(); - rotation.setToRotation( rotationInRadians ); - AffineTransform rotationInverse = rotation.createInverse(); - Matrix rotationInverseMatrix = new Matrix(); - rotationInverseMatrix.setFromAffineTransform( rotationInverse ); - Matrix rotationMatrix = new Matrix(); - rotationMatrix.setFromAffineTransform( rotation ); - - Matrix unrotatedCTM = ctm.multiply( rotationInverseMatrix ); - - float x = unrotatedCTM.getXPosition(); - float y = unrotatedCTM.getYPosition() + unrotatedCTM.getYScale(); - float w = unrotatedCTM.getXScale(); - - String posString = "p:" + currentPage + ";x:" + x + ";y:" + y + ";w:" + w; - try - { - data.setTablePos(new TablePos(posString)); - data.setPlaceholderName(objectName.getName()); - placeholders.add(data); - } catch (PdfAsException e) { - throw new WrappedIOException(e); - } - } - } - catch( NoninvertibleTransformException e ) - { - throw new WrappedIOException( e ); - } - } - } - else - { - super.processOperator(operator, arguments); - } - } - - /** - * Checks an image if it is a placeholder for a signature. - * - * @param image - * @return - * @throws IOException - */ - private SignaturePlaceholderData checkImage(PDXObjectImage image) throws IOException { - BufferedImage bimg = image.getRGBImage(); - if (bimg == null) { - String type = image.getSuffix(); - if (type != null) { - type = type.toUpperCase() + " images"; - } else { - type = "Image type"; - } - log.info("Unable to extract image for QRCode analysis. " + type + " not supported. Add additional JAI Image filters to your classpath. Refer to https://jai.dev.java.net. Skipping image."); - return null; - } - if(bimg.getHeight() < 10 || bimg.getWidth() < 10) { - log.debug("Image too small for QRCode. Skipping image."); - return null; - } - - LuminanceSource source = new BufferedImageLuminanceSource(bimg); - BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); - Result result; - long before = System.currentTimeMillis(); - try { - Hashtable<DecodeHintType, Vector<BarcodeFormat>> hints = new Hashtable<DecodeHintType, Vector<BarcodeFormat>>(); - Vector<BarcodeFormat> formats = new Vector<BarcodeFormat>(); - formats.add(BarcodeFormat.QR_CODE); - hints.put(DecodeHintType.POSSIBLE_FORMATS, formats); - result = new MultiFormatReader().decode(bitmap, hints); - - String text = result.getText(); - String profile = null; - String type = null; - String sigKey = null; - String id = null; - if (text != null) { - if (text.startsWith(QR_PLACEHOLDER_IDENTIFIER)) { - String[] data = text.split(";"); - if (data.length > 1) { - for (int i = 1; i < data.length; i++) { - String kvPair = data[i]; - String[] kv = kvPair.split("="); - if (kv.length != 2) { - log.debug("Invalid parameter in placeholder data: " + kvPair); - } else { - if (kv[0].equalsIgnoreCase(SignaturePlaceholderData.ID_KEY)) { - id = kv[1]; - } else if (kv[0].equalsIgnoreCase(SignaturePlaceholderData.PROFILE_KEY)) { - profile = kv[1]; - } else if (kv[0] - .equalsIgnoreCase(SignaturePlaceholderData.SIG_KEY_KEY)) { - sigKey = kv[1]; - } else if (kv[0] - .equalsIgnoreCase(SignaturePlaceholderData.TYPE_KEY)) { - type = kv[1]; - } - } - } - } - return new SignaturePlaceholderData(profile, type, sigKey, id); - } else { - log.warn("QR-Code found but does not start with \"" + QR_PLACEHOLDER_IDENTIFIER + "\". Ignoring QR placeholder."); - } - } - } catch (ReaderException re) { - if (log.isDebugEnabled()) { - log.debug("Could not decode - not a placeholder. needed: " - + (System.currentTimeMillis() - before)); - } - if (!(re instanceof NotFoundException)){ - if (log.isInfoEnabled()) { - log.info("Failed to decode image", re); - } - } - } catch(ArrayIndexOutOfBoundsException e){ - if (log.isInfoEnabled()) { - log.info("Failed to decode image. Probably a zxing bug", e); - } - } - return null; - } + /** + * The log. + */ + private static Log log = LogFactory + .getLog(SignaturePlaceholderExtractor.class); + + public static final String QR_PLACEHOLDER_IDENTIFIER = "PDF-AS-POS"; + public static final int PLACEHOLDER_MATCH_MODE_STRICT = 0; + public static final int PLACEHOLDER_MATCH_MODE_MODERATE = 1; + public static final int PLACEHOLDER_MATCH_MODE_LENIENT = 2; + + private List<SignaturePlaceholderData> placeholders = new Vector<SignaturePlaceholderData>(); + private int currentPage = 0; + + private SignaturePlaceholderExtractor(String placeholderId, + int placeholderMatchMode) throws IOException { + super(ResourceLoader.loadProperties( + "placeholder/pdfbox-reader.properties", true)); + } + + /** + * Search the document for placeholder images and possibly included + * 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 + * 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, + String placeholderId, int matchMode) throws PdfAsException { + SignaturePlaceholderContext.setSignaturePlaceholderData(null); + + SignaturePlaceholderExtractor extractor; + try { + extractor = new SignaturePlaceholderExtractor(placeholderId, + matchMode); + } catch (IOException e2) { + throw new PDFIOException("error.pdf.io.04", e2); + } + List<?> pages = doc.getDocumentCatalog().getAllPages(); + Iterator<?> iter = pages.iterator(); + int pageNr = 0; + while (iter.hasNext()) { + pageNr++; + PDPage page = (PDPage) iter.next(); + try { + extractor.setCurrentPage(pageNr); + extractor.processStream(page, page.findResources(), page + .getContents().getStream()); + SignaturePlaceholderData ret = matchPlaceholderPage( + extractor.placeholders, placeholderId, matchMode); + if (ret != null) { + SignaturePlaceholderContext + .setSignaturePlaceholderData(ret); + return ret; + } + } catch (IOException e1) { + throw new PDFIOException("error.pdf.io.04", e1); + } + + } + if (extractor.placeholders.size() > 0) { + SignaturePlaceholderData ret = matchPlaceholderDocument( + extractor.placeholders, placeholderId, matchMode); + SignaturePlaceholderContext.setSignaturePlaceholderData(ret); + return ret; + } + // no placeholders found, apply strict mode if set + if (matchMode == PLACEHOLDER_MATCH_MODE_STRICT) { + throw new PlaceholderExtractionException("error.pdf.stamp.09"); + } + + return null; + } + + private static SignaturePlaceholderData matchPlaceholderDocument( + List<SignaturePlaceholderData> placeholders, String placeholderId, + int matchMode) throws PlaceholderExtractionException { + + if (matchMode == PLACEHOLDER_MATCH_MODE_STRICT) + throw new PlaceholderExtractionException("error.pdf.stamp.09"); + + if (placeholders.size() == 0) + return null; + + for (int i = 0; i < placeholders.size(); i++) { + SignaturePlaceholderData spd = placeholders.get(i); + if (spd.getId() == null) + return spd; + } + + if (matchMode == PLACEHOLDER_MATCH_MODE_LENIENT) + return placeholders.get(0); + + return null; + } + + private static SignaturePlaceholderData matchPlaceholderPage( + List<SignaturePlaceholderData> placeholders, String placeholderId, + int matchMode) { + if (placeholders.size() == 0) + return null; + for (int i = 0; i < placeholders.size(); i++) { + SignaturePlaceholderData data = placeholders.get(i); + if (placeholderId != null && placeholderId.equals(data.getId())) + return data; + if (placeholderId == null && data.getId() == null) + return data; + } + return null; + } + + private void setCurrentPage(int pageNr) { + this.currentPage = pageNr; + } + + @Override + protected void processOperator(PDFOperator operator, List<COSBase> arguments) + throws IOException { + String operation = operator.getOperation(); + if (operation.equals("Do")) { + COSName objectName = (COSName) arguments.get(0); + Map<?, ?> xobjects = getResources().getXObjects(); + PDXObject xobject = (PDXObject) xobjects.get(objectName.getName()); + if (xobject instanceof PDXObjectImage) { + try { + PDXObjectImage image = (PDXObjectImage) xobject; + SignaturePlaceholderData data = checkImage(image); + if (data != null) { + PDPage page = getCurrentPage(); + Matrix ctm = getGraphicsState() + .getCurrentTransformationMatrix(); + double rotationInRadians = (page.findRotation() * Math.PI) / 180; + + AffineTransform rotation = new AffineTransform(); + rotation.setToRotation(rotationInRadians); + AffineTransform rotationInverse = rotation + .createInverse(); + Matrix rotationInverseMatrix = new Matrix(); + rotationInverseMatrix + .setFromAffineTransform(rotationInverse); + Matrix rotationMatrix = new Matrix(); + rotationMatrix.setFromAffineTransform(rotation); + + Matrix unrotatedCTM = ctm + .multiply(rotationInverseMatrix); + + float x = unrotatedCTM.getXPosition(); + float y = unrotatedCTM.getYPosition() + + unrotatedCTM.getYScale(); + float w = unrotatedCTM.getXScale(); + + String posString = "p:" + currentPage + ";x:" + x + + ";y:" + y + ";w:" + w; + try { + data.setTablePos(new TablePos(posString)); + data.setPlaceholderName(objectName.getName()); + placeholders.add(data); + } catch (PdfAsException e) { + throw new WrappedIOException(e); + } + } + } catch (NoninvertibleTransformException e) { + throw new WrappedIOException(e); + } + } + } else { + super.processOperator(operator, arguments); + } + } + + /** + * Checks an image if it is a placeholder for a signature. + * + * @param image + * @return + * @throws IOException + */ + private SignaturePlaceholderData checkImage(PDXObjectImage image) + throws IOException { + BufferedImage bimg = image.getRGBImage(); + if (bimg == null) { + String type = image.getSuffix(); + if (type != null) { + type = type.toUpperCase() + " images"; + } else { + type = "Image type"; + } + log.info("Unable to extract image for QRCode analysis. " + + type + + " not supported. Add additional JAI Image filters to your classpath. Refer to https://jai.dev.java.net. Skipping image."); + return null; + } + if (bimg.getHeight() < 10 || bimg.getWidth() < 10) { + log.debug("Image too small for QRCode. Skipping image."); + return null; + } + + LuminanceSource source = new BufferedImageLuminanceSource(bimg); + BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); + Result result; + long before = System.currentTimeMillis(); + try { + Hashtable<DecodeHintType, Vector<BarcodeFormat>> hints = new Hashtable<DecodeHintType, Vector<BarcodeFormat>>(); + Vector<BarcodeFormat> formats = new Vector<BarcodeFormat>(); + formats.add(BarcodeFormat.QR_CODE); + hints.put(DecodeHintType.POSSIBLE_FORMATS, formats); + result = new MultiFormatReader().decode(bitmap, hints); + + String text = result.getText(); + String profile = null; + String type = null; + String sigKey = null; + String id = null; + if (text != null) { + if (text.startsWith(QR_PLACEHOLDER_IDENTIFIER)) { + String[] data = text.split(";"); + if (data.length > 1) { + for (int i = 1; i < data.length; i++) { + String kvPair = data[i]; + String[] kv = kvPair.split("="); + if (kv.length != 2) { + log.debug("Invalid parameter in placeholder data: " + + kvPair); + } else { + if (kv[0] + .equalsIgnoreCase(SignaturePlaceholderData.ID_KEY)) { + id = kv[1]; + } else if (kv[0] + .equalsIgnoreCase(SignaturePlaceholderData.PROFILE_KEY)) { + profile = kv[1]; + } else if (kv[0] + .equalsIgnoreCase(SignaturePlaceholderData.SIG_KEY_KEY)) { + sigKey = kv[1]; + } else if (kv[0] + .equalsIgnoreCase(SignaturePlaceholderData.TYPE_KEY)) { + type = kv[1]; + } + } + } + } + return new SignaturePlaceholderData(profile, type, sigKey, + id); + } else { + log.warn("QR-Code found but does not start with \"" + + QR_PLACEHOLDER_IDENTIFIER + + "\". Ignoring QR placeholder."); + } + } + } catch (ReaderException re) { + if (log.isDebugEnabled()) { + log.debug("Could not decode - not a placeholder. needed: " + + (System.currentTimeMillis() - before)); + } + if (!(re instanceof NotFoundException)) { + if (log.isInfoEnabled()) { + log.info("Failed to decode image", re); + } + } + } catch (ArrayIndexOutOfBoundsException e) { + if (log.isInfoEnabled()) { + log.info("Failed to decode image. Probably a zxing bug", e); + } + } + return null; + } } - - diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/positioning/Positioning.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/positioning/Positioning.java index c8c2f99f..b6405c2d 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/positioning/Positioning.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/positioning/Positioning.java @@ -34,210 +34,196 @@ import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.common.PDRectangle; /** - * Created with IntelliJ IDEA. - * User: afitzek - * Date: 8/29/13 - * Time: 4:30 PM - * To change this template use File | Settings | File Templates. + * Created with IntelliJ IDEA. User: afitzek Date: 8/29/13 Time: 4:30 PM To + * change this template use File | Settings | File Templates. */ public class Positioning { - /** - * The left/right margin. - */ - public static final float SIGNATURE_MARGIN_HORIZONTAL = 50f; - - /** - * The top/bottom margin. - */ - public static final float SIGNATURE_MARGIN_VERTICAL = 20f; - - /** - * Evalutates absolute positioning and prepares the PositioningInstruction for - * placing the table. - * - * @param pos - * The absolute positioning parameter. If null it is sought in the - * profile definition. - * @param signature_type - * The profile definition of the table to be written. - * @param pdfDataSource - * The pdf. - * @param pdf_table - * The pdf table to be written. - * @return Returns the PositioningInformation. - * @throws PdfAsException - * F.e. - */ - public static PositioningInstruction determineTablePositioning(TablePos pos, String signature_type, - PDDocument pdfDataSource, IPDFVisualObject pdf_table, boolean legacy32) throws PdfAsException - { - return adjustSignatureTableandCalculatePosition(pdfDataSource, pdf_table, pos, legacy32); - } - - /** - * Sets the width of the table according to the layout of the document and - * calculates the y position where the PDFPTable should be placed. - * - * @param pdfDataSource - * The PDF document. - * @param pdf_table - * The PDFPTable to be placed. - * @return Returns the position where the PDFPTable should be placed. - * @throws PdfAsException - * F.e. - */ - public static PositioningInstruction adjustSignatureTableandCalculatePosition(final PDDocument pdfDataSource, - IPDFVisualObject pdf_table, TablePos pos, boolean legacy32) throws PdfAsException - { - - try { - PDFUtils.checkPDFPermissions(pdfDataSource); - // get pages of currentdocument - - int doc_pages = pdfDataSource.getNumberOfPages(); - int page = doc_pages; - boolean make_new_page = pos.isNewPage(); - if (!(pos.isNewPage() || pos.isPauto())) - { - // we should posit signaturtable on this page - - page = pos.getPage(); - // System.out.println("XXXXPAGE="+page+" doc_pages="+doc_pages); - if (page > doc_pages) - { - make_new_page = true; - page = doc_pages; - // throw new PDFDocumentException(227, "Page number is to big(=" + page+ - // ") cannot be parsed."); - } - } - - PDPage pdPage = (PDPage)pdfDataSource.getDocumentCatalog().getAllPages().get(page - 1); - PDRectangle cropBox = pdPage.getCropBox(); - - if(cropBox == null) { - cropBox = pdPage.findCropBox(); - } - - - if(cropBox == null) { - cropBox = pdPage.findMediaBox(); - } - - //TODO: fallback to MediaBox if Cropbox not available! - - // getPagedimensions - //Rectangle psize = reader.getPageSizeWithRotation(page); - //int page_rotation = reader.getPageRotation(page); - - //Integer rotation = pdPage.getRotation(); - //int page_rotation = rotation.intValue(); - - float page_width = cropBox.getWidth(); - float page_height = cropBox.getHeight(); - - // now we can calculate x-position - float pre_pos_x = SIGNATURE_MARGIN_HORIZONTAL; - if (!pos.isXauto()) - { - // we do have absolute x - pre_pos_x = pos.getPosX(); - } - // calculate width - // center - float pre_width = page_width - 2*pre_pos_x; - if (!pos.isWauto()) - { - // we do have absolute width - pre_width = pos.getWidth(); - if (pos.isXauto()) - { // center x - pre_pos_x = (page_width - pre_width) / 2; - } - } - final float pos_x = pre_pos_x; - final float width = pre_width; - // Signatur table dimensions are complete - pdf_table.setWidth(width); - pdf_table.fixWidth(); - //pdf_table.setTotalWidth(width); - //pdf_table.setLockedWidth(true); - - final float table_height = pdf_table.getHeight(); - // now check pos_y - float pos_y = pos.getPosY(); - - // in case an absolute y position is already given OR - // if the table is related to an invisible signature - // there is no need for further calculations - // (fixed adding new page in case of invisible signatures) - if (!pos.isYauto() || table_height == 0) - { - // we do have y-position too --> all parameters but page ok - if (make_new_page) - { - page++; - } - return new PositioningInstruction(make_new_page, page, pos_x, pos_y, pos.rotation); - } - // pos_y is auto - if (make_new_page) - { - // ignore footer in new page - page++; - pos_y = page_height - SIGNATURE_MARGIN_VERTICAL; - return new PositioningInstruction(make_new_page, page, pos_x, pos_y, pos.rotation); - } - // up to here no checks have to be made if Tablesize and Pagesize are fit - // Now we have to getfreespace in page and reguard footerline - float footer_line = pos.getFooterLine(); - float pre_page_length = PDFUtilities.calculatePageLength(pdfDataSource, page - 1, page_height - footer_line, /*page_rotation,*/ legacy32); - if (pre_page_length == Float.NEGATIVE_INFINITY) - { - // we do have an empty page or nothing in area above footerline - pre_page_length = page_height; - // no text --> SIGNATURE_BORDER - pos_y = page_height - SIGNATURE_MARGIN_VERTICAL; - if (pos_y - footer_line <= table_height) - { - make_new_page = true; - if (!pos.isPauto()) - { - // we have to correct pagenumber - page = pdfDataSource.getNumberOfPages(); - } - page++; - // no text --> SIGNATURE_BORDER - pos_y = page_height - SIGNATURE_MARGIN_VERTICAL; - } - return new PositioningInstruction(make_new_page, page, pos_x, pos_y, pos.rotation); - } - final float page_length = pre_page_length; - // we do have text take SIGNATURE_MARGIN - pos_y = page_height - page_length - SIGNATURE_MARGIN_VERTICAL; - if (pos_y - footer_line <= table_height) - { - make_new_page = true; - if (!pos.isPauto()) - { - // we have to correct pagenumber in case of absolute page and not enough - // space - page = pdfDataSource.getNumberOfPages(); - } - page++; - // no text --> SIGNATURE_BORDER - pos_y = page_height - SIGNATURE_MARGIN_VERTICAL; - } - return new PositioningInstruction(make_new_page, page, pos_x, pos_y, pos.rotation); - } finally { - if (pdfDataSource != null) { - try { - pdfDataSource.close(); - } catch (Exception e) { - } - } - } - } + /** + * The left/right margin. + */ + public static final float SIGNATURE_MARGIN_HORIZONTAL = 50f; + + /** + * The top/bottom margin. + */ + public static final float SIGNATURE_MARGIN_VERTICAL = 20f; + + /** + * Evalutates absolute positioning and prepares the PositioningInstruction + * for placing the table. + * + * @param pos + * The absolute positioning parameter. If null it is sought in + * the profile definition. + * @param signature_type + * The profile definition of the table to be written. + * @param pdfDataSource + * The pdf. + * @param pdf_table + * The pdf table to be written. + * @return Returns the PositioningInformation. + * @throws PdfAsException + * F.e. + */ + public static PositioningInstruction determineTablePositioning( + TablePos pos, String signature_type, PDDocument pdfDataSource, + IPDFVisualObject pdf_table, boolean legacy32) throws PdfAsException { + return adjustSignatureTableandCalculatePosition(pdfDataSource, + pdf_table, pos, legacy32); + } + + /** + * Sets the width of the table according to the layout of the document and + * calculates the y position where the PDFPTable should be placed. + * + * @param pdfDataSource + * The PDF document. + * @param pdf_table + * The PDFPTable to be placed. + * @return Returns the position where the PDFPTable should be placed. + * @throws PdfAsException + * F.e. + */ + public static PositioningInstruction adjustSignatureTableandCalculatePosition( + final PDDocument pdfDataSource, IPDFVisualObject pdf_table, + TablePos pos, boolean legacy32) throws PdfAsException { + + PDFUtils.checkPDFPermissions(pdfDataSource); + // get pages of currentdocument + + int doc_pages = pdfDataSource.getNumberOfPages(); + int page = doc_pages; + boolean make_new_page = pos.isNewPage(); + if (!(pos.isNewPage() || pos.isPauto())) { + // we should posit signaturtable on this page + + page = pos.getPage(); + // System.out.println("XXXXPAGE="+page+" doc_pages="+doc_pages); + if (page > doc_pages) { + make_new_page = true; + page = doc_pages; + // throw new PDFDocumentException(227, "Page number is to big(=" + // + page+ + // ") cannot be parsed."); + } + } + + PDPage pdPage = (PDPage) pdfDataSource.getDocumentCatalog() + .getAllPages().get(page - 1); + PDRectangle cropBox = pdPage.getCropBox(); + + if (cropBox == null) { + cropBox = pdPage.findCropBox(); + } + + if (cropBox == null) { + cropBox = pdPage.findMediaBox(); + } + + // TODO: fallback to MediaBox if Cropbox not available! + + // getPagedimensions + // Rectangle psize = reader.getPageSizeWithRotation(page); + // int page_rotation = reader.getPageRotation(page); + + // Integer rotation = pdPage.getRotation(); + // int page_rotation = rotation.intValue(); + + float page_width = cropBox.getWidth(); + float page_height = cropBox.getHeight(); + + // now we can calculate x-position + float pre_pos_x = SIGNATURE_MARGIN_HORIZONTAL; + if (!pos.isXauto()) { + // we do have absolute x + pre_pos_x = pos.getPosX(); + } + // calculate width + // center + float pre_width = page_width - 2 * pre_pos_x; + if (!pos.isWauto()) { + // we do have absolute width + pre_width = pos.getWidth(); + if (pos.isXauto()) { // center x + pre_pos_x = (page_width - pre_width) / 2; + } + } + final float pos_x = pre_pos_x; + final float width = pre_width; + // Signatur table dimensions are complete + pdf_table.setWidth(width); + pdf_table.fixWidth(); + // pdf_table.setTotalWidth(width); + // pdf_table.setLockedWidth(true); + + final float table_height = pdf_table.getHeight(); + // now check pos_y + float pos_y = pos.getPosY(); + + // in case an absolute y position is already given OR + // if the table is related to an invisible signature + // there is no need for further calculations + // (fixed adding new page in case of invisible signatures) + if (!pos.isYauto() || table_height == 0) { + // we do have y-position too --> all parameters but page ok + if (make_new_page) { + page++; + } + return new PositioningInstruction(make_new_page, page, pos_x, + pos_y, pos.rotation); + } + // pos_y is auto + if (make_new_page) { + // ignore footer in new page + page++; + pos_y = page_height - SIGNATURE_MARGIN_VERTICAL; + return new PositioningInstruction(make_new_page, page, pos_x, + pos_y, pos.rotation); + } + // up to here no checks have to be made if Tablesize and Pagesize are + // fit + // Now we have to getfreespace in page and reguard footerline + float footer_line = pos.getFooterLine(); + float pre_page_length = PDFUtilities.calculatePageLength(pdfDataSource, + page - 1, page_height - footer_line, /* page_rotation, */ + legacy32); + if (pre_page_length == Float.NEGATIVE_INFINITY) { + // we do have an empty page or nothing in area above footerline + pre_page_length = page_height; + // no text --> SIGNATURE_BORDER + pos_y = page_height - SIGNATURE_MARGIN_VERTICAL; + if (pos_y - footer_line <= table_height) { + make_new_page = true; + if (!pos.isPauto()) { + // we have to correct pagenumber + page = pdfDataSource.getNumberOfPages(); + } + page++; + // no text --> SIGNATURE_BORDER + pos_y = page_height - SIGNATURE_MARGIN_VERTICAL; + } + return new PositioningInstruction(make_new_page, page, pos_x, + pos_y, pos.rotation); + } + final float page_length = pre_page_length; + // we do have text take SIGNATURE_MARGIN + pos_y = page_height - page_length - SIGNATURE_MARGIN_VERTICAL; + if (pos_y - footer_line <= table_height) { + make_new_page = true; + if (!pos.isPauto()) { + // we have to correct pagenumber in case of absolute page and + // not enough + // space + page = pdfDataSource.getNumberOfPages(); + } + page++; + // no text --> SIGNATURE_BORDER + pos_y = page_height - SIGNATURE_MARGIN_VERTICAL; + } + return new PositioningInstruction(make_new_page, page, pos_x, pos_y, + pos.rotation); + + } } 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 c04dca59..43d501f1 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 @@ -99,8 +99,7 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { FileInputStream fis = new FileInputStream(new File(fisTmpFile)); - PDDocument doc = PDDocument.load(new ByteArrayInputStream(pdfObject - .getOriginalDocument())); + PDDocument doc = pdfObject.getDocument(); PDSignature signature = new PDSignature(); signature.setFilter(COSName.getPDFName(signer.getPDFFilter())); // default @@ -198,13 +197,13 @@ public class PADESPDFBOXSigner implements IPdfSigner, IConfigurationConstants { IPDFVisualObject visualObject = stamper.createVisualPDFObject( pdfObject, main); - PDDocument originalDocument = PDDocument + /*PDDocument originalDocument = PDDocument .load(new ByteArrayInputStream(pdfObject.getStatus() - .getPdfObject().getOriginalDocument())); + .getPdfObject().getOriginalDocument()));*/ PositioningInstruction positioningInstruction = Positioning .determineTablePositioning(tablePos, "", - originalDocument, visualObject, + doc, visualObject, legacy32Position); SignaturePositionImpl position = new SignaturePositionImpl(); diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureProperties.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureProperties.java index 05cce46d..6b1edf13 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureProperties.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/stamping/pdfbox/PDFAsVisualSignatureProperties.java @@ -32,8 +32,7 @@ public class PDFAsVisualSignatureProperties extends PDVisibleSigProperties { e.printStackTrace(); } try { - PDDocument origDoc = PDDocument.load(new ByteArrayInputStream( - object.getOriginalDocument())); + PDDocument origDoc = object.getDocument(); designer = new PDFAsVisualSignatureDesigner(origDoc, pos.getPage(), this, pos.isMakeNewPage()); float posy = designer.getPageHeight() - pos.getY(); diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/status/PDFObject.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/status/PDFObject.java index b402d0d2..f8ca3567 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/status/PDFObject.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/status/PDFObject.java @@ -23,25 +23,47 @@ ******************************************************************************/ package at.gv.egiz.pdfas.lib.impl.status; +import java.io.ByteArrayInputStream; +import java.io.IOException; + +import org.apache.pdfbox.pdmodel.PDDocument; + public class PDFObject { private OperationStatus status; + private PDDocument doc; private byte[] originalDocument; private byte[] signedDocument; public PDFObject(OperationStatus operationStatus) { this.status = operationStatus; } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + if(doc != null) { + doc.close(); + } + } public byte[] getOriginalDocument() { return originalDocument; } - public void setOriginalDocument(byte[] originalDocument) { + public void setOriginalDocument(byte[] originalDocument) throws IOException { this.originalDocument = originalDocument; + if(doc != null) { + doc.close(); + } + this.doc = PDDocument.load(new ByteArrayInputStream(this.originalDocument)); } + public PDDocument getDocument() { + return this.doc; + } + public byte[] getSignedDocument() { return signedDocument; } diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/PdfAsHelper.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/PdfAsHelper.java index 47243a43..f9d3e720 100644 --- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/PdfAsHelper.java +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/PdfAsHelper.java @@ -809,4 +809,12 @@ public class PdfAsHelper { } return false; } + + public static String getVersion() { + return PdfAsFactory.getVersion(); + } + + public static String getSCMRevision() { + return PdfAsFactory.getSCMRevision(); + } } diff --git a/pdf-as-web/src/main/webapp/index.jsp b/pdf-as-web/src/main/webapp/index.jsp index 82458f77..42f2a168 100644 --- a/pdf-as-web/src/main/webapp/index.jsp +++ b/pdf-as-web/src/main/webapp/index.jsp @@ -1,4 +1,5 @@ <%@page import="at.gv.egiz.pdfas.web.config.WebConfiguration"%> +<%@page import="at.gv.egiz.pdfas.web.helper.PdfAsHelper"%> <html> <head> <title>PDF-Signatur</title> @@ -60,5 +61,7 @@ } %> </form> + + <p><small>Version: <%= PdfAsHelper.getVersion() %> - <%= PdfAsHelper.getSCMRevision() %></small></p> </body> </html>
\ No newline at end of file |