aboutsummaryrefslogtreecommitdiff
path: root/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/PdfAS.java
diff options
context:
space:
mode:
Diffstat (limited to 'pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/PdfAS.java')
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/PdfAS.java1575
1 files changed, 1575 insertions, 0 deletions
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/PdfAS.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/PdfAS.java
new file mode 100644
index 0000000..c222259
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/PdfAS.java
@@ -0,0 +1,1575 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: PdfAS.java,v 1.5 2006/10/31 08:04:50 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
+import java.util.Properties;
+import java.util.Vector;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import at.gv.egiz.pdfas.api.analyze.NonTextObjectInfo;
+import at.gv.egiz.pdfas.api.commons.DynamicSignatureProfileImpl;
+import at.gv.egiz.pdfas.api.commons.SignatureInformation;
+import at.gv.egiz.pdfas.api.timestamp.TimeStamper;
+import at.gv.egiz.pdfas.api.verify.VerifyParameters;
+import at.gv.egiz.pdfas.api.xmldsig.ExtendedSignatureInformation;
+import at.gv.egiz.pdfas.api.xmldsig.XMLDsigData;
+import at.gv.egiz.pdfas.commandline.CommandlineConnectorChooser;
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.gv.egiz.pdfas.exceptions.framework.CorrectorException;
+import at.gv.egiz.pdfas.framework.ConnectorParameters;
+import at.gv.egiz.pdfas.framework.input.PdfDataSource;
+import at.gv.egiz.pdfas.framework.input.correction.Corrector;
+import at.gv.egiz.pdfas.framework.input.correction.CorrectorFactory;
+import at.gv.egiz.pdfas.framework.output.DataSink;
+import at.gv.egiz.pdfas.framework.signator.SignatorInformation;
+import at.gv.egiz.pdfas.impl.api.commons.PdfDataSourceAdapter;
+import at.gv.egiz.pdfas.impl.input.ByteArrayPdfDataSourceImpl;
+import at.gv.egiz.pdfas.impl.input.helper.DataSourceHelper;
+import at.gv.egiz.pdfas.utils.PDFASUtils;
+import at.knowcenter.wag.egov.egiz.cfg.OverridePropertyHolder;
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorFactoryException;
+import at.knowcenter.wag.egov.egiz.exceptions.NormalizeException;
+import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException;
+import at.knowcenter.wag.egov.egiz.exceptions.PresentableException;
+import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
+import at.knowcenter.wag.egov.egiz.exceptions.SignatureException;
+import at.knowcenter.wag.egov.egiz.exceptions.SignatureTypesException;
+import at.knowcenter.wag.egov.egiz.framework.FoundBlock;
+import at.knowcenter.wag.egov.egiz.framework.FoundKey;
+import at.knowcenter.wag.egov.egiz.pdf.AbsoluteTextSignature;
+import at.knowcenter.wag.egov.egiz.pdf.BinarySignatureHolder;
+import at.knowcenter.wag.egov.egiz.pdf.ObjectExtractor;
+import at.knowcenter.wag.egov.egiz.pdf.PDFSignatureCreation;
+import at.knowcenter.wag.egov.egiz.pdf.PDFSignatureObject;
+import at.knowcenter.wag.egov.egiz.pdf.PDFUtilities;
+import at.knowcenter.wag.egov.egiz.pdf.PositioningInstruction;
+import at.knowcenter.wag.egov.egiz.pdf.SignatureHolder;
+import at.knowcenter.wag.egov.egiz.pdf.TablePos;
+import at.knowcenter.wag.egov.egiz.pdf.TextualSignature;
+import at.knowcenter.wag.egov.egiz.pdf.TextualSignatureHolder;
+import at.knowcenter.wag.egov.egiz.sig.SignatureData;
+import at.knowcenter.wag.egov.egiz.sig.SignatureDataImpl;
+import at.knowcenter.wag.egov.egiz.sig.SignatureObject;
+import at.knowcenter.wag.egov.egiz.sig.SignatureResponse;
+import at.knowcenter.wag.egov.egiz.sig.SignatureTypeDefinition;
+import at.knowcenter.wag.egov.egiz.sig.SignatureTypes;
+import at.knowcenter.wag.egov.egiz.sig.connectors.Connector;
+import at.knowcenter.wag.egov.egiz.sig.connectors.ConnectorChooser;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject;
+import at.knowcenter.wag.egov.egiz.sig.signatureobject.SignatureObjectHelper;
+import at.knowcenter.wag.egov.egiz.tools.Normalizer;
+import at.knowcenter.wag.exactparser.ParseDocument;
+import at.knowcenter.wag.exactparser.parsing.PDFUtils;
+import at.knowcenter.wag.exactparser.parsing.results.HeaderParseResult;
+
+import com.lowagie.text.Rectangle;
+import com.lowagie.text.pdf.PdfPTable;
+import com.lowagie.text.pdf.PdfReader;
+
+/**
+ * This class contains the major methods used by both, the commandline and the
+ * webapp, to perform signation and verification.
+ *
+ * @author wprinz
+ * @author mruhmer
+ */
+public abstract class PdfAS
+{
+//23.11.2010 changed by exthex - added method: verifyExtendedSignatureHolders(List extended_signature_info, String connectorType, boolean returnHashInputData, Date verificationTime)
+
+ /**
+ * The current version of the pdf-as library. This version string is logged on every invocation
+ * of the api or the web application.
+ */
+ public static final String PDFAS_VERSION = "3.2";
+
+ /**
+ * The key of the strict mode setting.
+ */
+ public static final String STRICT_MODE_KEY = "strict_mode";
+
+ /**
+ * The left/right border.
+ */
+ public static final float SIGNATURE_BORDER = 100f;
+
+ /**
+ * The top/bottom border.
+ */
+ public static final float SIGNATURE_MARGIN = 20f;
+
+ /**
+ * The Mime Type of a PDF document.
+ */
+ public static final String PDF_MIME_TYPE = "application/pdf";
+
+ public static final String CORRECT_DOCUMENT_IF_NECESSARY_KEY = "correct_document_if_necessary";
+
+ /**
+ * The logger definition.
+ */
+ private static final Log log = LogFactory.getLog(PdfAS.class);
+
+ /**
+ * Tells, if strict PDF checking the PDF version is enabled.
+ *
+ * @return Returns true, if incoming PDFs should be checked strictly.
+ */
+ public static boolean isStrictPdfChecking()
+ {
+ try
+ {
+ SettingsReader settings = SettingsReader.getInstance();
+ String strict_mode = settings.getSetting(STRICT_MODE_KEY, "false");
+ if (strict_mode.equals("true"))
+ {
+ return true;
+ }
+ }
+ catch (SettingsException e)
+ {
+ log.error(e.getMessage(), e);
+ }
+ return false;
+ }
+
+ /**
+ * Checks the version of the given PDF to be 1.4 or lower.
+ *
+ * <p>
+ * This scans the first 1000 bytes of the PDF for the pdf Header.
+ * </p>
+ *
+ * @param pdfDataSource
+ * The PDF.
+ * @return Returns true, if the given PDF is strict 1.4, false otherwise.
+ * @throws PDFDocumentException
+ * Forwarded exception.
+ */
+ public static boolean isPdf14(PdfDataSource pdfDataSource) throws PDFDocumentException
+ {
+ try
+ {
+ byte[] firstBytes = new byte[1000];
+ InputStream is = pdfDataSource.createInputStream();
+ is.read(firstBytes);
+ is.close();
+
+ HeaderParseResult hpr = PDFUtils.parseHeader(firstBytes, 0);
+
+ if (hpr.major <= 1 && hpr.minor <= 4)
+ {
+ return true;
+ }
+ return false;
+ }
+ catch (Exception e)
+ {
+ throw new PDFDocumentException(201, e);
+ }
+ }
+
+ /**
+ * Applies strict version mode on the PDF and throws an exception, if the pdf
+ * is not 1.4.
+ *
+ * <p>
+ * Furthermore (independently of strict mode) the PDF is checked for
+ * parsability.
+ * </p>
+ *
+ * @param pdfDataSource
+ * The pdf to be checked against strict mode.
+ * @throws PDFDocumentException
+ * @throws SettingsException
+ * @throws CorrectorException
+ */
+ public static PdfDataSource applyStrictMode(PdfDataSource pdfDataSource) throws PDFDocumentException, SettingsException, CorrectorException
+ {
+ if (isStrictPdfChecking())
+ {
+ if (!isPdf14(pdfDataSource))
+ {
+ throw new PDFDocumentException(201, "StrictMode: The pdf version is not 1.4 or lower.");
+ }
+ }
+ try
+ {
+ byte[] pdf = DataSourceHelper.convertDataSourceToByteArray(pdfDataSource);
+ ParseDocument.parseDocument(pdf);
+ }
+ catch (Exception e)
+ {
+ log.debug("Error while parsing Document.", e);
+
+ boolean tryToCorrect = SettingsReader.getInstance().getSetting(CORRECT_DOCUMENT_IF_NECESSARY_KEY, "false").equals("true");
+ if (!tryToCorrect)
+ {
+ throw new PDFDocumentException(201, e);
+ }
+ log.info("Correcting document...");
+ Corrector cor = CorrectorFactory.createCorrector();
+ PdfDataSource correctedDS = cor.correctDocument(pdfDataSource);
+ log.info("Correction finished.");
+
+ return correctedDS;
+ }
+
+ return pdfDataSource;
+ }
+
+ public static at.gv.egiz.pdfas.api.io.DataSource applyStrictMode (at.gv.egiz.pdfas.api.io.DataSource dataSource) throws PDFDocumentException, SettingsException, CorrectorException
+ {
+ if (dataSource.getMimeType().equals("application/pdf"))
+ {
+ PdfDataSource pdfDS = new PdfDataSourceAdapter(dataSource);
+ PdfDataSource correctedDS = applyStrictMode(pdfDS);
+ if (correctedDS != pdfDS)
+ {
+ return new at.gv.egiz.pdfas.impl.api.commons.DataSourceApiAdapter(correctedDS);
+ }
+ }
+ return dataSource;
+ }
+
+ // TODO: unused method - remove
+ // /**
+ // * Verifies the given PDF document.
+ // *
+ // * @param pdf
+ // * The PDF document.
+ // * @param connector
+ // * The connector.
+ // * @return Returns the List of results.
+ // * @throws PresentableException
+ // * Forwarded exception.
+ // */
+ // public static List verifyPdf(final byte[] pdf, final String connector)
+ // throws PresentableException
+ // {
+ // VerificationFilter vf = new VerificationFilter();
+ // List signature_holders = vf.extractSignaturesFromPdf(pdf);
+ // if (signature_holders.isEmpty())
+ // {
+ // throw new PDFDocumentException(206);
+ // }
+ //
+ // List results = verifySignatureHolders(signature_holders, connector);
+ //
+ // return results;
+ // }
+
+ // TODO: unused method - remove
+ // /**
+ // * Verifies the given text that is supposed to be extracted from a PDF
+ // * document using text extraction mechanisms.
+ // *
+ // * @param text
+ // * The text to be verified.
+ // * @param connector
+ // * The connecor.
+ // * @return Returns the List of results.
+ // * @throws PresentableException
+ // * Forwarded exception.
+ // */
+ // public static List verifyText(final String text, final String connector)
+ // throws PresentableException
+ // {
+ // VerificationFilter vf = new VerificationFilter();
+ // List signature_holders = vf.extractSignaturesFromPlainText(text);
+ // if (signature_holders.isEmpty())
+ // {
+ // throw new PDFDocumentException(206);
+ // }
+ //
+ // List results = verifySignatureHolders(signature_holders, connector);
+ //
+ // return results;
+ // }
+
+ /**
+ * Extracts all signature blocks from the given raw text using textual mode.
+ *
+ * @param raw_text
+ * The raw text.
+ * @return Returns a List of all SignatureHolders extracted from the text.
+ * @throws PDFDocumentException
+ * F.e.
+ * @throws SignatureException
+ * F.e.
+ * @throws SignatureTypesException
+ * @throws NormalizeException
+ */
+ public static List extractSignatureHoldersTextual(String raw_text, boolean old_style) throws PDFDocumentException, SignatureException, SignatureTypesException, NormalizeException
+ {
+ List signature_holders = new ArrayList();
+
+ String text = raw_text;
+ for (;;)
+ {
+ TextualSignatureHolder holder = extractSignatureHolderTextual(text, old_style);
+ if (holder == null)
+ {
+ break;
+ }
+ {
+ log.debug("Found holder: " + holder.getSignatureObject().getSignationType());
+ }
+ signature_holders.add(0, holder);
+
+ text = holder.getSignedText();
+ }
+
+ return signature_holders;
+ }
+
+ /**
+ * Extracts the last signature holder from the given text.
+ *
+ * @param raw_text
+ * @param old_style
+ * @return Returns the found singature holder, or null, if none could be
+ * found.
+ * @throws SignatureException
+ * @throws SignatureTypesException
+ * @throws NormalizeException
+ */
+ public static TextualSignatureHolder extractSignatureHolderTextual(String raw_text, boolean old_style) throws SignatureException, SignatureTypesException, NormalizeException
+ {
+ List signatureTypes_ = AbsoluteTextSignature.getSignatureTypesForTextAnalysis();
+
+ List found_blocks = new ArrayList();
+ for (int cur_type = 0; cur_type < signatureTypes_.size(); cur_type++)
+ {
+ SignatureTypeDefinition cur_std = (SignatureTypeDefinition) signatureTypes_.get(cur_type);
+
+ List found_keys = findBlockInText(raw_text, cur_std, old_style);
+ if (found_keys != null)
+ {
+ FoundBlock found_block = new FoundBlock();
+ found_block.found_keys = found_keys;
+ found_block.end_index = raw_text.length();
+ found_block.std = cur_std;
+ found_blocks.add(found_block);
+ }
+ }
+
+ List last_most_blocks = sortOutEarlyBlocks(found_blocks);
+
+ List minimum_blocks = sortOutLargeBlocks(last_most_blocks);
+
+ if (minimum_blocks.size() > 1)
+ {
+ log.debug("There are still " + minimum_blocks.size() + " candidates:");
+
+ for (int i = 0; i < minimum_blocks.size(); i++)
+ {
+ FoundBlock fb = (FoundBlock) minimum_blocks.get(i);
+ log.debug(" fb: " + fb.std.getType());
+ }
+
+ log.debug("... checking for Semantic Equality.");
+ }
+
+ boolean semantic_equality = checkForSemanticEquality(minimum_blocks);
+
+ if (minimum_blocks.size() > 1)
+ {
+ log.debug("... Semantic Equality = " + semantic_equality);
+ }
+
+ if (!semantic_equality)
+ {
+ throw new SignatureException(ErrorCode.NOT_SEMANTICALLY_EQUAL, "The found blocks are not semantically equal.");
+ }
+
+ if (!minimum_blocks.isEmpty())
+ {
+ FoundBlock actual_block = (FoundBlock) minimum_blocks.get(0);
+
+ String signed_text = raw_text.substring(0, actual_block.getFirstKey().start_index);
+
+ SignatureObject signatureObject_ = new SignatureObject();
+ signatureObject_.setSigType(actual_block.std.getType());
+ signatureObject_.initByType();
+
+ int end_index = actual_block.end_index;
+ for (int i = 0; i < actual_block.found_keys.size(); i++)
+ {
+ FoundKey cur_key = (FoundKey) actual_block.found_keys.get(i);
+ int start_index = cur_key.getStartIndex() + cur_key.caption.length();
+
+ String value = raw_text.substring(start_index, end_index);
+
+ signatureObject_.setSigValueCaption(cur_key.getKey(), value, cur_key.caption);
+
+ end_index = cur_key.getStartIndex();
+ }
+
+ // this normalization is required to get rid of possible trailing
+ // newlines.
+ String normalized_text = normalizeText(signed_text);
+ TextualSignatureHolder holder = new TextualSignatureHolder(normalized_text, signatureObject_);
+ return holder;
+ }
+
+ return null;
+ }
+
+ /**
+ * Tries to find a block of the given type in the text.
+ *
+ * @param text
+ * The text.
+ * @param sig_type_def
+ * The type of the block.
+ * @param old_style
+ * Tells, if the block is old style (SIG_KZ will be ignored), or if
+ * it is a new block.
+ * @return Returns a List of the found keys of the block, or null, if the
+ * block could not be found.
+ */
+ public static List findBlockInText(String text, SignatureTypeDefinition sig_type_def, boolean old_style)
+ {
+ Vector keys = sig_type_def.getRevertSortedKeys();
+ Vector captions = sig_type_def.getRevertSortedCaptions();
+
+ int last_index = text.length();
+ List found_keys = new ArrayList();
+ for (int key_idx = 0; key_idx < keys.size(); key_idx++)
+ {
+ String key = (String) keys.get(key_idx);
+ // logger_.debug("Key="+key);
+ if (old_style && key.equals(SignatureTypes.SIG_KZ))
+ {
+ // If separating the old style way - skip The "Kennzeichnung"
+ // key, because it wasn't present in old profiles.
+ continue;
+ }
+
+ String caption = (String) captions.get(key_idx);
+
+ // int found_index = text.lastIndexOf(caption);
+ // we're searching for captions that start at the beginning of the line.
+ int found_index = text.lastIndexOf("\n" + caption) + 1;// text.lastIndexOf("\n"
+ // + caption) + 1;
+ // // the +1
+ // text.lastIndexOf(caption)
+ // + 1; //
+ // compensates the
+ // \n
+ if (found_index == 0)
+ {
+ // try without /n
+ found_index = text.lastIndexOf(caption);
+
+ // fix #331 here ??
+ }
+ log.debug("found key:" + caption + " at index:" + found_index);
+ if (key.equals(SignatureTypes.SIG_ID))
+ {
+ if (found_index < 0 || found_index >= last_index)
+ {
+ // not found, SIG_ID is not required
+ continue;
+ }
+ FoundKey fk = new FoundKey(key, caption, found_index);
+ found_keys.add(fk);
+ }
+ else
+ {
+ if (found_index < 0 || found_index >= last_index)
+ {
+ // one key is not found - the profile doesn't match.
+ return null;
+ }
+
+ FoundKey fk = new FoundKey(key, caption, found_index);
+ found_keys.add(fk);
+ last_index = found_index;
+ }
+ }
+
+ sortFoundKeysDescendingly(found_keys);
+
+ boolean matched = checkThatOrderIsCorrectAndCorrectFoundKeys(found_keys, keys, old_style);
+ // boolean found_required = checkFoundRequiredKeys(found_keys, old_style);
+ // logger_.debug("KKKKKKKKKKmatched="+matched);
+ if (matched)
+ {
+ return found_keys;
+ }
+ return null;
+ }
+
+ /**
+ * Sorts the FoundKeys List descendingly according to the start indices of the
+ * found keys (the first found key in the list will have the highest start
+ * index, the second one the second highest and so forth).
+ *
+ * @param found_keys
+ * The List of FoundKey objects to be sorted.
+ */
+ public static void sortFoundKeysDescendingly(List found_keys)
+ {
+ // sort the found_keys according to their start pos reversely.
+
+ Collections.sort(found_keys, new Comparator() {
+ public int compare(Object arg0, Object arg1)
+ {
+ FoundKey fk0 = (FoundKey) arg0;
+ FoundKey fk1 = (FoundKey) arg1;
+ // sort reversely!
+ return fk1.start_index - fk0.start_index;
+ }
+ });
+ }
+
+ /**
+ * Sorts the FoundKeys List ascendingly according to the start indices of the
+ * found keys (the first found key in the list will have the lowest start
+ * index, the second one the second lowest and so forth).
+ *
+ * @param found_keys
+ * The List of FoundKey objects to be sorted.
+ */
+ public static void sortFoundKeysAscendingly(List found_keys)
+ {
+ // sort the found_keys according to their start pos.
+
+ Collections.sort(found_keys, new Comparator() {
+ public int compare(Object arg0, Object arg1)
+ {
+ FoundKey fk0 = (FoundKey) arg0;
+ FoundKey fk1 = (FoundKey) arg1;
+ return fk0.start_index - fk1.start_index;
+ }
+ });
+ }
+
+ /**
+ * Checks that the found keys are in correct order regarding SIG_ID as
+ * optional key.
+ *
+ * <p>
+ * If the SIG_ID key is misplaced, it will be removed from the found keys
+ * list.
+ * </p>
+ *
+ * @param found_keys
+ * The found keys ordered descendingly to their start position
+ * @param profile_keys
+ * The profile keys.
+ * @param old_style
+ * Tells, if SIG_KZ should be ignored, or not.
+ * @return Returns true, if the keys are correct.
+ */
+ public static boolean checkThatOrderIsCorrectAndCorrectFoundKeys(List found_keys, List profile_keys, boolean old_style)
+ {
+
+ int found_index = 0;
+ for (int profile_index = 0; profile_index < profile_keys.size(); profile_index++)
+ {
+ String key = (String) profile_keys.get(profile_index);
+
+ if (old_style && key.equals(SignatureTypes.SIG_KZ))
+ {
+ continue;
+ }
+
+ FoundKey found_key = (FoundKey) found_keys.get(found_index);
+
+ boolean match = key.equals(found_key.getKey());
+ if (match)
+ {
+ found_index++;
+ continue;
+ }
+
+ if (key.equals(SignatureTypes.SIG_ID))
+ {
+ continue;
+ }
+
+ // doesn't match
+ return false;
+ }
+
+ // remove all fields above the found_index - they are not correctly matched
+ // indices (should be only the ID
+ int size = found_keys.size();
+ for (int i = found_index; i < size; i++)
+ {
+ // this removes all (size - found_index) objects above found_index
+ found_keys.remove(found_index);
+ }
+
+ return true;
+ }
+
+ /**
+ * Sorts out early blocks and leaves only those at the bottom of the text.
+ *
+ * @param found_blocks
+ * The found blocks.
+ * @return Returns a list of the last blocks.
+ */
+ public static List sortOutEarlyBlocks(List found_blocks)
+ {
+ int last_most_index = Integer.MIN_VALUE;
+
+ List last_most_blocks = new ArrayList();
+ for (int block_index = 0; block_index < found_blocks.size(); block_index++)
+ {
+ FoundBlock block = (FoundBlock) found_blocks.get(block_index);
+
+ int this_last_index = block.getLastKey().start_index;
+ if (this_last_index < last_most_index)
+ {
+ // this block cannot be the last most block.
+ continue;
+ }
+ if (this_last_index == last_most_index)
+ {
+ last_most_blocks.add(block);
+ continue;
+ }
+ if (this_last_index > last_most_index)
+ {
+ last_most_blocks = new ArrayList();
+ last_most_blocks.add(block);
+ last_most_index = this_last_index;
+ }
+ }
+
+ return last_most_blocks;
+ }
+
+ /**
+ * Sorts out large blocks.
+ *
+ * @param found_blocks
+ * The found blocks.
+ * @return Returns a list of the smallest blocks.
+ */
+ public static List sortOutLargeBlocks(List found_blocks)
+ {
+ int last_min_size = Integer.MAX_VALUE;
+
+ List min_size_blocks = new ArrayList();
+ for (int block_index = 0; block_index < found_blocks.size(); block_index++)
+ {
+ FoundBlock block = (FoundBlock) found_blocks.get(block_index);
+
+ int size = block.getSize();
+
+ if (size > last_min_size)
+ {
+ // this block is larger
+ continue;
+ }
+ if (size == last_min_size)
+ {
+ min_size_blocks.add(block);
+ continue;
+ }
+ if (size < last_min_size)
+ {
+ min_size_blocks = new ArrayList();
+ min_size_blocks.add(block);
+ last_min_size = size;
+ }
+ }
+
+ return min_size_blocks;
+ }
+
+ /**
+ * Checks the list of blocks for semantic equality.
+ *
+ * @param found_blocks
+ * The list of found blocks.
+ * @return Returns true if all blocks are semantically equal.
+ */
+ public static boolean checkForSemanticEquality(List found_blocks)
+ {
+ if (found_blocks.size() <= 1)
+ {
+ return true;
+ }
+
+ for (int block_index = 0; block_index < found_blocks.size() - 1; block_index++)
+ {
+ FoundBlock first_block = (FoundBlock) found_blocks.get(block_index);
+ FoundBlock second_block = (FoundBlock) found_blocks.get(block_index + 1);
+
+ if (!first_block.isSemanticallyEqual(second_block))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public static int getIndexOfFoundKey(List found_keys, String key)
+ {
+ for (int i = 0; i < found_keys.size(); i++)
+ {
+ FoundKey fk = (FoundKey) found_keys.get(i);
+ if (fk.getKey().equals(key))
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public static boolean containsFoundKey(List found_keys, String key)
+ {
+ return getIndexOfFoundKey(found_keys, key) >= 0;
+ }
+
+ /**
+ * Checks the found keys for the required keys regarding the old style.
+ *
+ * @param found_keys
+ * The found keys.
+ * @param old_style
+ * Flag that tells, if KZ is not required.
+ * @return Returns true, if all required keys were found.
+ */
+ public static boolean checkFoundRequiredKeys(List found_keys, boolean old_style)
+ {
+ if (!containsFoundKey(found_keys, SignatureTypes.SIG_DATE))
+ {
+ return false;
+ }
+ if (!containsFoundKey(found_keys, SignatureTypes.SIG_ISSUER))
+ {
+ return false;
+ }
+ if (!containsFoundKey(found_keys, SignatureTypes.SIG_NUMBER))
+ {
+ return false;
+ }
+ if (!containsFoundKey(found_keys, SignatureTypes.SIG_VALUE))
+ {
+ return false;
+ }
+ if (!old_style && !containsFoundKey(found_keys, SignatureTypes.SIG_KZ))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ public static List verifySignatureHolders(List signature_holders, String connectorType, boolean returnHashInputData, Date verificationTime) throws PDFDocumentException, NormalizeException, SignatureException, ConnectorException, ConnectorFactoryException
+ {
+ List results = new ArrayList();
+ for (int i = 0; i < signature_holders.size(); i++)
+ {
+ SignatureHolder holder = (SignatureHolder) signature_holders.get(i);
+
+ // logger_.debug();
+ // logger_.debug();
+ // logger_.debug("Verifying Holder " + i + "...");
+ // logger_.debug("holder[" + i + "].signed_text = " +
+ // holder.signed_text);
+ // logger_.debug("holder[" + i + "].sig_obj = ");
+ // logger_.debug("holder[" + i + "].type = " +
+ // (holder.signature_object.isTextual() ? "textual" : "binary"));
+ // logger_.debug(holder.signature_object.toString());
+
+ SignatureResponse result = verify(holder, connectorType, returnHashInputData, verificationTime, null);
+ results.add(result);
+
+ // logger_.debug();
+ // logger_.debug("check[" + i + "].cert = " +
+ // result.getCertificateCheckInfo());
+ // logger_.debug("check[" + i + "].sig = " +
+ // result.getSignatureCheckInfo().trim());
+ // logger_.debug("check[" + i + "].manifest = " +
+ // result.getSignatureManifestCheckInfo());
+ // logger_.debug();
+ }
+ return results;
+ }
+
+ /**
+ * Verify a list of signatures
+ *
+ * @param extended_signature_info a list of {@link ExtendedSignatureInformation} to be verified
+ * @param connectorType the connector to use for verification
+ * @param returnHashInputData
+ * @param verificationTime
+ * @param verifySignatureAtIndex only verify the signature at the given index in the extended_signature_info list. A value < 0 means to verify all signatures in the list.
+ * @return a list of {@link SignatureResponse}s
+ * @throws PDFDocumentException
+ * @throws NormalizeException
+ * @throws SignatureException
+ * @throws ConnectorException
+ * @throws ConnectorFactoryException
+ */
+ public static List verifyExtendedSignatureHolders(List extended_signature_info, String connectorType, boolean returnHashInputData, Date verificationTime, int verifySignatureAtIndex) throws PDFDocumentException, NormalizeException, SignatureException, ConnectorException, ConnectorFactoryException
+ {
+ List results = new ArrayList();
+ for (int i = 0; i < extended_signature_info.size(); i++)
+ {
+ if (verifySignatureAtIndex < 0 || verifySignatureAtIndex == i)
+ {
+ ExtendedSignatureInformation sigInfo = (ExtendedSignatureInformation) extended_signature_info.get(i);
+ SignatureInformation si = sigInfo.getSignatureInformation();
+ SignatureHolder holder = (SignatureHolder) si.getInternalSignatureInformation();
+
+ SignatureResponse result = verify(holder, connectorType, returnHashInputData, verificationTime, sigInfo.getXmlDsigData());
+ results.add(result);
+ }
+ }
+ return results;
+ }
+
+ /**
+ * Verifies a SignatureHolder using the given connector.
+ *
+ * @param signature_holder
+ * The SignatureHolder to be verified.
+ * @param connector
+ * The connector.
+ * @return Returns the SignatureResponse object.
+ * @throws NormalizeException
+ * F.e.
+ * @throws PDFDocumentException
+ * F.e.
+ * @throws SignatureException
+ * F.e.
+ * @throws ConnectorException
+ * @throws ConnectorFactoryException
+ */
+ public static SignatureResponse verify(SignatureHolder signature_holder, String connectorType, boolean returnHashInputData, Date verificationTime, XMLDsigData dsig) throws NormalizeException, PDFDocumentException, SignatureException, ConnectorException, ConnectorFactoryException
+ {
+ // String text_to_be_verified = signature_holder.getSignedText();
+ // logger_.debug("verify text_to_be_verified"+text_to_be_verified);
+ SignatureObject so_to_be_verified = signature_holder.getSignatureObject();
+
+ // if (text_to_be_verified == null)
+ // {
+ // throw new SignatureException(311, "Document can not be verified because
+ // the text to be verified is either null.");
+ // }
+ // if (text_to_be_verified.length() <= 0)
+ // {
+ // throw new SignatureException(311, "Document can not be verified because
+ // the length of the text to be verified is 0. (length = " +
+ // text_to_be_verified.length() + ")");
+ // }
+
+ if (so_to_be_verified == null)
+ {
+ throw new SignatureException(312, "Document can not be verified because no signature object are set.");
+ }
+
+ // fixed by tknall
+ if (so_to_be_verified.getX509Cert() == null)
+ {
+ throw new SignatureException(ErrorCode.CERTIFICATE_NOT_FOUND, "Document certificate is not defined.");
+ }
+
+ SignSignatureObject so = SignatureObjectHelper.convertSignatureObjectToSignSignatureObject(so_to_be_verified);
+ SignatureData sd = convertSignatureHolderToSignatureData(signature_holder);
+
+ String profile = so_to_be_verified.getSignatureTypeDefinition().getType();
+// Connector c = ConnectorChooser.chooseCommandlineConnectorForVerify(connector, so_to_be_verified.getKZ(), so.id, profile);
+ String connectorId = CommandlineConnectorChooser.chooseCommandlineConnectorForVerify(connectorType, so_to_be_verified.getKZ(), so.id, profile);
+
+ ConnectorParameters cp = new ConnectorParameters();
+ cp.setProfileId(profile);
+ cp.setReturnHashInputData(returnHashInputData);
+ cp.setVerificationTime(verificationTime);
+ Connector c = at.gv.egiz.pdfas.framework.ConnectorFactory.createConnector(connectorId, cp);
+
+ return executeVerify(dsig, so, sd, c);
+ }
+
+ private static SignatureResponse executeVerify(XMLDsigData dsig, SignSignatureObject so,
+ SignatureData sd, Connector c) throws ConnectorException {
+ SignatureResponse res = null;
+ try {
+ return c.doVerify(sd, so, dsig);
+ } catch (ConnectorException e) {
+ if (VerifyParameters.isSuppressVerifyExceptions()) {
+ res = new SignatureResponse();
+ res.setVerificationImpossibleEx(e);
+ } else {
+ throw e;
+ }
+ }
+ return res;
+ }
+
+ public static SignatureResponse verifyWeb(SignatureHolder signature_holder, String connector, String loc_ref) throws NormalizeException, PDFDocumentException, SignatureException, ConnectorException
+ {
+ // String text_to_be_verified = signature_holder.getSignedText();
+ // logger_.debug("verify text_to_be_verified"+text_to_be_verified);
+ SignatureObject so_to_be_verified = signature_holder.getSignatureObject();
+
+ // if (text_to_be_verified == null)
+ // {
+ // throw new SignatureException(311, "Document can not be verified because
+ // the text to be verified is either null.");
+ // }
+ // if (text_to_be_verified.length() <= 0)
+ // {
+ // throw new SignatureException(311, "Document can not be verified because
+ // the length of the text to be verified is 0. (length = " +
+ // text_to_be_verified.length() + ")");
+ // }
+
+ if (so_to_be_verified == null)
+ {
+ throw new SignatureException(312, "Document can not be verified because no signature object are set.");
+ }
+
+ // added by tknall
+ if (so_to_be_verified.getX509Cert() == null)
+ {
+ throw new SignatureException(ErrorCode.CERTIFICATE_NOT_FOUND, "Document certificate is not defined.");
+ }
+
+
+ SignSignatureObject so = SignatureObjectHelper.convertSignatureObjectToSignSignatureObject(so_to_be_verified);
+ SignatureData sd = convertSignatureHolderToSignatureData(signature_holder);
+
+ String profile = so_to_be_verified.getSignatureTypeDefinition().getType();
+ Connector c = ConnectorChooser.chooseWebConnectorForVerify(connector, so_to_be_verified.getKZ(), so.id, profile, loc_ref);
+
+ return executeVerify(null, so, sd, c);
+
+ }
+
+ public static SignatureData convertSignatureHolderToSignatureData(SignatureHolder signature_holder)
+ {
+ SignatureData sd = null;
+ if (signature_holder instanceof BinarySignatureHolder)
+ {
+ BinarySignatureHolder bsh = (BinarySignatureHolder) signature_holder;
+ sd = new SignatureDataImpl(bsh.getDataSource(), "application/pdf");
+ }
+ else
+ {
+ TextualSignatureHolder tsh = (TextualSignatureHolder)signature_holder;
+ sd = new SignatureDataImpl(tsh.getDataSource(), "text/plain", "UTF-8");
+ }
+ return sd;
+ }
+
+ /**
+ * Signs the given text with the provided connector using the given signature
+ * type.
+ *
+ * @param data_to_sign
+ * The data to be signed.
+ * @param signature_type
+ * The type of the signature.
+ * @param connector
+ * The connector.
+ * @return Returns the corresponding SignatureObject.
+ * @throws SignatureException
+ * F.e.
+ * @throws PDFDocumentException
+ * F.e.
+ * @throws ConnectorException
+ */
+ public static SignSignatureObject sign(final SignatureData data_to_sign, final Connector connector, final TimeStamper timeStamper) throws SignatureException, PDFDocumentException, ConnectorException
+ {
+// if (data_to_sign == null || data_to_sign.getData() == null)
+// {
+// throw new SignatureException(301, "Signature can not be produced. Data is null."); //$NON-NLS-1$
+// }
+ // if (data_to_sign.getData().length <= 0)
+ // {
+ // throw new SignatureException(301, "Signature can not be produced. Data is
+ // empty. (length = " + data_to_sign.getData().length + ")"); //$NON-NLS-1$
+ // //$NON-NLS-2$
+ // }
+
+ SignSignatureObject signed_signature_object = connector.doSign(data_to_sign);
+
+ // call timestamper if available
+ if (timeStamper != null) {
+ log.debug("execute timestamping with stamper: " + timeStamper.getClass());
+ signed_signature_object.sigTimeStamp = timeStamper.applyTimeStamp(signed_signature_object.getSignatureValue());
+ }
+
+ return signed_signature_object;
+ }
+
+ /**
+ * Helper method that creates a SignatureObject and initializes it with the
+ * given type.
+ *
+ * @param signature_type
+ * The type.
+ * @return Returns the created SignatureObject.
+ * @throws SignatureException
+ * f.e.
+ * @throws SignatureTypesException
+ * f.e.
+ */
+ public static SignatureObject createSignatureObjectFromType(final String signature_type) throws SignatureException, SignatureTypesException
+ {
+ SignatureObject sig_obj = new SignatureObject();
+ sig_obj.setSigType(signature_type);
+ sig_obj.initByType();
+
+ return sig_obj;
+ }
+
+// /**
+// * @deprecated moved to Main.processSign use signCommandline instead
+// * @param pdfDataSource
+// * @param dataSink
+// * @param signatorId
+// * @param connectorType
+// * @param profile
+// * @param pos
+// * @throws PresentableException
+// */
+// public static void sign(PdfDataSource pdfDataSource, DataSink dataSink, PdfASID signatorId, final String connectorType, final String profile, TablePos pos) throws PresentableException
+// {
+//// //Signator signator = SignatorFactory.createSignator(algorithm);
+//// at.gv.egiz.pdfas.framework.signator.Signator signator = at.gv.egiz.pdfas.framework.SignatorFactory.createSignator(algorithm);
+////
+//// //IncrementalUpdateInformation iui = signator.prepareSign(pdfDataSource, signature_type, pos, ConnectorFactory.needsSIG_ID(connector));
+//// SignatorInformation si = signator.prepareSign(pdfDataSource, signature_type, pos, ConnectorFactory.needsSIG_ID(connector));
+//
+// // Connector c = ConnectorChooser.chooseCommandlineConnectorForSign(connector, signature_type);
+//
+//// SignSignatureObject sso = sign(si.getSignatureData(), c);
+////
+//// si.setSignSignatureObject(sso);
+////
+//// signator.finishSign(si, dataSink);
+//
+// String connectorId = CommandlineConnectorChooser.chooseCommandlineConnectorForSign(connectorType);
+//
+// signCommandline(pdfDataSource, dataSink, signatorId, connectorId, profile, pos);
+// }
+
+ public static SignatorInformation signCommandline(PdfDataSource pdfDataSource, DataSink dataSink, PdfASID signatorId, String connectorId, final String profile, final String signatureKeyIdentifier, TablePos pos, TimeStamper timeStamper, Properties overrideProps) throws PresentableException
+ {
+ try {
+ at.gv.egiz.pdfas.framework.signator.Signator signator = at.gv.egiz.pdfas.framework.SignatorFactory.createSignator(signatorId);
+ if (overrideProps != null) {
+ OverridePropertyHolder.setOverrideProps(overrideProps);
+ }
+
+ ConnectorParameters cp = new ConnectorParameters();
+ cp.setProfileId(profile);
+ cp.setSignatureKeyIdentifier(signatureKeyIdentifier);
+ Connector c = at.gv.egiz.pdfas.framework.ConnectorFactory.createConnector(connectorId, cp);
+
+ // SignatorInformation si = signator.prepareSign(pdfDataSource, profile, pos, ConnectorFactory.needsSIG_ID(connector));
+ SignatorInformation si = signator.prepareSign(pdfDataSource, profile, pos, timeStamper);
+
+ SignSignatureObject sso = sign(si.getSignatureData(), c, timeStamper);
+
+ si.setSignSignatureObject(sso);
+
+ signator.finishSign(si, dataSink);
+
+ return si;
+ } finally {
+ OverridePropertyHolder.removeProperties();
+ DynamicSignatureProfileImpl.disposeLocalProfile();
+ }
+ }
+
+ public static SignatorInformation signCommandline(PdfDataSource pdfDataSource, DataSink dataSink, PdfASID signatorId, String connectorId, final String profile, TablePos pos) throws PresentableException {
+ return signCommandline(pdfDataSource, dataSink, signatorId, connectorId, profile, null, pos, null, null);
+ }
+
+ /**
+ * Extracts and normalizes the text from the pdf.
+ *
+ * @param pdf
+ * The PDF document.
+ * @return Returns the text String.
+ * @throws PresentableException
+ * F.e.
+ */
+// public static String extractNormalizedTextTextual(final byte[] pdf) throws PresentableException
+// {
+// // ByteArrayInputStream bais = new ByteArrayInputStream(pdf);
+// // String raw_document_text = TextualSignature.extractTextTextual(bais);
+// //
+// // String document_text = normalizeText(raw_document_text);
+//
+// return extractNormalizedTextTextual(pdf, pdf.length);
+// }
+
+
+ /**
+ *
+ * @param pdfDs
+ * @return List of {@link NonTextObjectInfo}
+ */
+ public static List extractNonTextualObjects(PdfDataSource pdfDs) {
+ return ObjectExtractor.extractNonTextInfo(pdfDs);
+ }
+
+
+ /**
+ * @deprecated
+ * Use version with explicit encoding {@link PdfAS#extractNormalizedTextTextual(PdfDataSource, String)}.
+ * This one uses cp1252.
+ *
+ * @param pdfDataSource
+ * @return
+ * @throws PresentableException
+ */
+ public static String extractNormalizedTextTextual(PdfDataSource pdfDataSource) throws PresentableException {
+ return extractNormalizedTextTextual(pdfDataSource, "cp1252");
+
+ }
+
+ public static String extractNormalizedTextTextual(PdfDataSource pdfDataSource, String encoding) throws PresentableException
+ {
+ String raw_document_text = TextualSignature.extractTextTextual(pdfDataSource, encoding);
+ String document_text = normalizeText(raw_document_text);
+ return document_text;
+ }
+ /**
+ @deprecated
+ */
+ public static String extractNormalizedTextTextual(byte [] pdf, int length) throws PresentableException
+ {
+ ByteArrayPdfDataSourceImpl pdfDataSource = new ByteArrayPdfDataSourceImpl(pdf, length);
+ String raw_document_text = TextualSignature.extractTextTextual(pdfDataSource, "cp1252");
+ String document_text = normalizeText(raw_document_text);
+ return document_text;
+ }
+
+// public static String extractNormalizedTextTextual(InputStream pdfInputStream, int length) throws PresentableException
+// {
+// DelimitedInputStream dis = new DelimitedInputStream(pdfInputStream, length);
+// String raw_document_text = TextualSignature.extractTextTextual(dis);
+// String document_text = normalizeText(raw_document_text);
+// return document_text;
+// }
+// /**
+// * Extracts and normalizes the text from the pdf.
+// *
+// * @param pdf
+// * The PDF document.
+// * @param length
+// * The length of the PDF document. The decument is considered to be
+// * that long even if the byte array is longer.
+// * @return Returns the text String.
+// * @throws PresentableException
+// * F.e.
+// */
+// public static String extractNormalizedTextTextual(final byte[] pdf, final int length) throws PresentableException
+// {
+// ByteArrayInputStream bais = new ByteArrayInputStream(pdf, 0, length);
+// String raw_document_text = TextualSignature.extractTextTextual(bais);
+// // logger_.info("extractNormalizedTextTextual
+// // raw_document_text="+raw_document_text);
+// String document_text = normalizeText(raw_document_text);
+// // logger_.info("extractNormalizedTextTextual document_text
+// // ="+document_text);
+// return document_text;
+// }
+
+ /**
+ * Normalizes the given text.
+ *
+ * @param text
+ * The text to be normalized.
+ * @return Returns the normalized text.
+ * @throws NormalizeException
+ * F.e.
+ */
+ public static String normalizeText(final String text) throws NormalizeException
+ {
+ Normalizer normalizer = new Normalizer();
+ String normalized_text = normalizer.normalize(text, false);
+ // fix #331 ??
+ //normalized_text = normalized_text.replaceAll("\n", "");
+ return normalized_text;
+ }
+
+ /**
+ * Creates the iText PDFPTable from a given SignatureObject.
+ *
+ * @param signature_object
+ * The SignatureObject.
+ * @return Returns the created PDFPTable.
+ * @throws PDFDocumentException
+ * F.e.
+ * @throws SignatureException
+ * F.e.
+ */
+ public static PdfPTable createPdfPTableFromSignatureObject(final SignatureObject signature_object) throws PDFDocumentException, SignatureException
+ {
+ PDFSignatureCreation creation = new PDFSignatureCreation(signature_object);
+ PDFSignatureObject pdf_sig_obj = creation.getPDFSignatureObject();
+ PdfPTable pdf_table = (PdfPTable) pdf_sig_obj.getSignatureObject();
+
+ return pdf_table;
+ }
+
+ /**
+ * 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 pdf
+ * The pdf.
+ * @param pdf_table
+ * The pdf table to be written.
+ * @return Returns the PositioningInformation.
+ * @throws PDFDocumentException
+ * F.e.
+ * @throws SettingsException
+ * F.e.
+ */
+ public static PositioningInstruction determineTablePositioning(TablePos pos, String signature_type, PdfDataSource pdfDataSource, PdfPTable pdf_table) throws PDFDocumentException, SettingsException
+ {
+ if (pos == null)
+ {
+ String pos_string = SettingsReader.getInstance().getSetting(SignatureTypes.SIG_OBJ + signature_type + ".pos", null);
+ if (pos_string != null)
+ {
+ pos = PdfAS.parsePositionFromPosString(pos_string);
+ }
+ }
+ if (pos == null)
+ {
+ // The default algorithm. x,y,w =auto ,p=lastpage, f:ignored because
+ // y:auto
+ pos = new TablePos();
+ }
+ // System.out.println("Tablepos="+pos);
+ return PdfAS.adjustSignatureTableandCalculatePosition(pdfDataSource, pdf_table, pos);
+ }
+
+ /**
+ * 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 pdf
+ * The PDF document.
+ * @param pdf_table
+ * The PDFPTable to be placed.
+ * @return Returns the position where the PDFPTable should be placed.
+ * @throws PDFDocumentException
+ * F.e.
+ */
+ public static PositioningInstruction adjustSignatureTableandCalculatePosition(final PdfDataSource pdfDataSource, PdfPTable pdf_table, TablePos pos) throws PDFDocumentException
+ {
+ // first check pageinstruction in TablePos-object
+ // new,auto,absolut
+ PdfReader reader = readInPdfDocument(pdfDataSource);
+ PDFASUtils.checkReaderPermissions(reader);
+ // get pages of currentdocument
+ int doc_pages = reader.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.");
+ }
+ }
+
+ // getPagedimensions
+ Rectangle psize = reader.getPageSizeWithRotation(page);
+ int page_rotation = reader.getPageRotation(page);
+
+// [tknall] for iText 1.x.x:
+// float page_width = psize.width();
+// float page_height = psize.height();
+
+// [tknall] for iText 2.x.x:
+// float page_width = psize.getWidth();
+// float page_height = psize.getHeight();
+
+ float page_width = psize.getWidth();
+ float page_height = psize.getHeight();
+
+ // now we can calculate x-position
+ float pre_pos_x = SIGNATURE_BORDER / 2;
+ if (!pos.isXauto())
+ {
+ // we do have absolute x
+ pre_pos_x = pos.getPosX();
+ }
+ // calculate width
+ // center
+ float pre_width = page_width - pre_pos_x - 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.setTotalWidth(width);
+ pdf_table.setLockedWidth(true);
+ final float table_height = pdf_table.getTotalHeight();
+ // now check pos_y
+ float pos_y = pos.getPosY();
+ if (!pos.isYauto())
+ {
+ // 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_y is auto
+ if (make_new_page)
+ {
+ // ignore footer in new page
+ page++;
+ pos_y = page_height - SIGNATURE_BORDER / 2;
+ return new PositioningInstruction(make_new_page, page, pos_x, pos_y);
+ }
+ // 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);
+ 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_BORDER / 2;
+ if (pos_y - footer_line <= table_height)
+ {
+ make_new_page = true;
+ if (!pos.isPauto())
+ {
+ // we have to correct pagenumber
+ page = reader.getNumberOfPages();
+ }
+ page++;
+ // no text --> SIGNATURE_BORDER
+ pos_y = page_height - SIGNATURE_BORDER / 2;
+ }
+ return new PositioningInstruction(make_new_page, page, pos_x, pos_y);
+ }
+ final float page_length = pre_page_length;
+ // we do have text take SIGNATURE_MARGIN
+ pos_y = page_height - page_length - SIGNATURE_MARGIN;
+ 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 = reader.getNumberOfPages();
+ }
+ page++;
+ // no text --> SIGNATURE_BORDER
+ pos_y = page_height - SIGNATURE_BORDER / 2;
+ }
+ return new PositioningInstruction(make_new_page, page, pos_x, pos_y);
+ }
+
+// /**
+// * Sets the width of the table according to the layout of the document and
+// * calculates the y position where the PDFPTable should be placed.
+// *
+// * @deprecated
+// * @param pdf
+// * The PDF document.
+// * @param pdf_table
+// * The PDFPTable to be placed.
+// * @return Returns the position where the PDFPTable should be placed.
+// * @throws PDFDocumentException
+// * F.e.
+// */
+// public static PositioningInstruction adjustTableAndCalculatePosition(final byte[] pdf, PdfPTable pdf_table) throws PDFDocumentException
+// {
+// boolean make_new_page = false;
+//
+// PdfReader reader = readInPdfDocument(pdf);
+//
+// int page = reader.getNumberOfPages();
+// Rectangle psize = reader.getPageSizeWithRotation(page);
+// float page_width = psize.width();
+// float page_height = psize.height();
+//
+// final float width = page_width - SIGNATURE_BORDER;
+// pdf_table.setTotalWidth(width);
+// pdf_table.setLockedWidth(true);
+//
+// final float pos_x = SIGNATURE_BORDER / 2;
+//
+// final float table_height = pdf_table.getTotalHeight();
+// final float page_length = PDFUtilities.calculateLastPageLength(pdf, page_height);
+// float pos_y = page_height - page_length - SIGNATURE_MARGIN;
+//
+// if (pos_y <= table_height)
+// {
+// make_new_page = true;
+// page++;
+//
+// pos_y = page_height - SIGNATURE_BORDER / 2;
+// }
+//
+// return new PositioningInstruction(make_new_page, page, pos_x, pos_y);
+// }
+
+// /**
+// * Sets the width of the table according to the layout of the document and
+// * calculates the y position where the PDFPTable should be placed.
+// *
+// * <p>
+// * This algorithm tries to position the table between the end of the text and
+// * the footer line.
+// * </p>
+// *
+// * @deprecated
+// * @param pdf
+// * The PDF document.
+// * @param pdf_table
+// * The PDFPTable to be placed.
+// * @return Returns the position where the PDFPTable should be placed.
+// * @throws PDFDocumentException
+// * F.e.
+// */
+// public static PositioningInstruction adjustTableAndCalculatePositionRegardingFooter(final byte[] pdf, PdfPTable pdf_table, float footer_line) throws PDFDocumentException
+// {
+// boolean make_new_page = false;
+//
+// PdfReader reader = readInPdfDocument(pdf);
+//
+// int page = reader.getNumberOfPages();
+// Rectangle psize = reader.getPageSizeWithRotation(page);
+// float page_width = psize.width();
+// float page_height = psize.height();
+//
+// final float width = page_width - SIGNATURE_BORDER;
+// pdf_table.setTotalWidth(width);
+// pdf_table.setLockedWidth(true);
+//
+// final float pos_x = SIGNATURE_BORDER / 2;
+//
+// final float table_height = pdf_table.getTotalHeight();
+//
+// final float page_length = PDFUtilities.calculateLastPageLength(pdf, page_height - footer_line);
+// float pos_y = page_height - page_length - SIGNATURE_MARGIN;
+//
+// if (pos_y - footer_line <= table_height)
+// {
+// make_new_page = true;
+// page++;
+//
+// pos_y = page_height - SIGNATURE_BORDER / 2;
+// }
+//
+// return new PositioningInstruction(make_new_page, page, pos_x, pos_y);
+// }
+
+ /**
+ * Creates an iText Reader that parses the document.
+ * <p>
+ * This is a convenience function for wrapping the Reader's exceptions into
+ * PDFDocumentException.
+ * </p>
+ *
+ * @param pdf
+ * The PDF document.
+ * @return Returns the created PdfReader.
+ * @throws PDFDocumentException
+ * F.e.
+ */
+ public static PdfReader readInPdfDocument(final PdfDataSource pdfDataSource) throws PDFDocumentException
+ {
+ try
+ {
+ //InputStream is = pdfDataSource.createInputStream();
+ // PERF: byte array instead of stream
+ byte [] pdf_data = pdfDataSource.getAsByteArray();
+ PdfReader reader = new PdfReader(pdf_data);
+ //is.close();
+ return reader;
+ }
+ catch (IOException e)
+ {
+ throw new PDFDocumentException(201, e);
+ }
+ }
+
+ /**
+ * Parses the TablePos object from a given String with the appropriate format.
+ *
+ * @param pos_string
+ * The pos string. e.g. x:40.0;y:auto;w:auto;p:1;f:300.0
+ * @return Returns the parsed TablePos object.
+ * @throws PDFDocumentException
+ * Thrown, if the String doesn't have the proper format.
+ */
+ public static TablePos parsePositionFromPosString(String pos_string) throws PDFDocumentException
+ {
+ TablePos pos = new TablePos(pos_string);
+ return pos;
+ }
+
+}