+ * Create an Object implementing this interface using the proper factory.
+ *
+ *
+ * @author wprinz
+ */
+public interface PdfAs
+{
+
+ /**
+ * Signs a PDF document using PDF-AS.
+ *
+ * @param signParameters
+ * The sign parameters.
+ * @return Returns the signed document plus additional information.
+ * @throws PdfAsException
+ * Thrown, if an error occurs.
+ *
+ * @see SignParameters
+ * @see SignResult
+ */
+ public SignResult sign(SignParameters signParameters) throws PdfAsException;
+
+ /**
+ * Verifies a document with (potentially multiple) PDF-AS signatures.
+ *
+ * @param verifyParameters
+ * The verify parameters.
+ * @return Returns the verification results.
+ * @throws PdfAsException
+ * Thrown, if an error occurs.
+ *
+ * @see VerifyParameters
+ * @see VerifyResults
+ * @see VerifyResult
+ */
+ public VerifyResults verify(VerifyParameters verifyParameters) throws PdfAsException;
+
+ /**
+ * Analyzes a document for signatures and returns a verify-able list of such.
+ *
+ * @param analyzeParameters
+ * The analyzation parameters.
+ * @return Returns a list of verify-able signatures that were found in the
+ * document.
+ * @throws PdfAsException
+ * Thrown on error.
+ *
+ * @see AnalyzeParameters
+ * @see AnalyzeResult
+ * @see {@link #verify(AnalyzeResult)}
+ */
+ public AnalyzeResult analyze(AnalyzeParameters analyzeParameters) throws PdfAsException;
+
+ /**
+ * Verifies a list of signatures that have been analyzed previously.
+ *
+ * @param verifyAfterAnalysisParameters The parameters.
+ *
+ * @return Returns the verification results.
+ * @throws PdfAsException
+ * Thrown on error.
+ *
+ * @see AnalyzeResult
+ * @see VerifyAfterAnalysisParameters
+ * @see VerifyResults
+ * @see VerifyResult
+ * @see {@link #analyze(AnalyzeParameters)}
+ */
+ public VerifyResults verify(VerifyAfterAnalysisParameters verifyAfterAnalysisParameters) throws PdfAsException;
+
+ /**
+ * Reloads the configuration from the work directory.
+ *
+ * @throws PdfAsException
+ * Thrown, if an error occurs.
+ */
+ public void reloadConfig() throws PdfAsException;
+
+ /**
+ * Returns the list of information objects about the profiles available in the
+ * configuration.
+ *
+ *
+ * Note: Currently the profile information consists of the profile Id and the
+ * MOA Key Id only.
+ *
+ *
+ * Note: In near future the profile management will be moved out of the config
+ * file into an API class representation of the profiles which may render this
+ * (and related) methods obsolete.
+ *
+ *
+ * @return Returns the list of {@link SignatureProfile} objects with
+ * information about the profiles available in the configuration.
+ * @throws PdfAsException
+ * Thrown on error.
+ *
+ * @see SignatureProfile
+ */
+ public List getProfileInformation() throws PdfAsException;
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/analyze/AnalyzeParameters.java b/src/main/java/at/gv/egiz/pdfas/api/analyze/AnalyzeParameters.java
new file mode 100644
index 0000000..0ab854c
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/analyze/AnalyzeParameters.java
@@ -0,0 +1,69 @@
+/**
+ *
+ */
+package at.gv.egiz.pdfas.api.analyze;
+
+import at.gv.egiz.pdfas.api.commons.Constants;
+import at.gv.egiz.pdfas.api.io.DataSource;
+
+/**
+ * Parameter object that holds the analyze parameters.
+ *
+ * @author wprinz
+ */
+public class AnalyzeParameters
+{
+
+ /**
+ * The document to be analyzed.
+ */
+ protected DataSource document = null;
+
+ /**
+ * The mode of operation how the document is analyzed.
+ *
+ *
+ * May be {@link Constants#VERIFY_MODE_BINARY_ONLY} to check the document for
+ * binary signatures only (very fast). Or may be
+ * {@link Constants#VERIFY_MODE_SEMI_CONSERVATIVE} to perform a semi
+ * conservative (optimized) text and binary verification (slow). Or may be
+ * {@link Constants#VERIFY_MODE_FULL_CONSERVATIVE} to perform a full
+ * conservative text and binary verification (very slow).
+ *
+ */
+ protected String verifyMode = Constants.VERIFY_MODE_FULL_CONSERVATIVE;
+
+ /**
+ * @return the document
+ */
+ public DataSource getDocument()
+ {
+ return this.document;
+ }
+
+ /**
+ * @param document the document to set
+ */
+ public void setDocument(DataSource document)
+ {
+ this.document = document;
+ }
+
+ /**
+ * @return the verifyMode
+ */
+ public String getVerifyMode()
+ {
+ return this.verifyMode;
+ }
+
+ /**
+ * @param verifyMode the verifyMode to set
+ */
+ public void setVerifyMode(String verifyMode)
+ {
+ this.verifyMode = verifyMode;
+ }
+
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/analyze/AnalyzeResult.java b/src/main/java/at/gv/egiz/pdfas/api/analyze/AnalyzeResult.java
new file mode 100644
index 0000000..098f309
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/analyze/AnalyzeResult.java
@@ -0,0 +1,30 @@
+/**
+ *
+ */
+package at.gv.egiz.pdfas.api.analyze;
+
+import java.util.List;
+
+import at.gv.egiz.pdfas.api.commons.SignatureInformation;
+import at.gv.egiz.pdfas.api.exceptions.PdfAsException;
+
+/**
+ * The result of an analyze operation, which is a list of verifyable signatures.
+ *
+ * @author wprinz
+ *
+ */
+public interface AnalyzeResult
+{
+ /**
+ * Returns the list of found signatures.
+ *
+ * @return Returns a list of {@link SignatureInformation} objects representing all
+ * found signatures.
+ * @throws PdfAsException
+ * Thrown on error.
+ *
+ * @see SignatureInformation
+ */
+ public List getSignatures() throws PdfAsException;
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/commons/Constants.java b/src/main/java/at/gv/egiz/pdfas/api/commons/Constants.java
new file mode 100644
index 0000000..e8ebc16
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/commons/Constants.java
@@ -0,0 +1,77 @@
+/**
+ *
+ */
+package at.gv.egiz.pdfas.api.commons;
+
+/**
+ * Contains commonly used constants.
+ *
+ * @author wprinz
+ */
+public final class Constants
+{
+
+ /**
+ * Hidden default constructor.
+ */
+ private Constants()
+ {
+ // empty
+ }
+
+ /**
+ * A binary signature.
+ */
+ public static String SIGNATURE_TYPE_BINARY = "binary";
+
+ /**
+ * A textual signature.
+ */
+ public static String SIGNATURE_TYPE_TEXTUAL = "textual";
+
+ /**
+ * A "detached" textual signature.
+ *
+ *
+ * The document text is signed, but instead of returning the pdf with the signature block,
+ * the sign result XML of the connector is returned.
+ *
+ */
+ public static String SIGNATURE_TYPE_DETACHEDTEXTUAL = "detachedtextual";
+
+ /**
+ * The signature device moa.
+ */
+ public static String SIGNATURE_DEVICE_MOA = "moa";
+
+ /**
+ * The signature device bku.
+ */
+ public static String SIGNATURE_DEVICE_BKU = "bku";
+
+ /**
+ * Only binary signatures are verified.
+ */
+ public static String VERIFY_MODE_BINARY_ONLY = "binaryOnly";
+
+ /**
+ * Binary and textual signatures are verified with time optimization.
+ *
+ *
+ * This mode of operation tries to minimize the numbers of text extractions,
+ * which are very time intensive, at the cost of some rare cases, in which some
+ * signatures may not be found.
+ *
+ */
+ public static String VERIFY_MODE_SEMI_CONSERVATIVE = "semiConservative";
+
+ /**
+ * Binary and textual signatures are verified.
+ */
+ public static String VERIFY_MODE_FULL_CONSERVATIVE = "fullConservative";
+
+ /**
+ * All signatures are verified.
+ */
+ public static int VERIFY_ALL = -1;
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/commons/SignatureInformation.java b/src/main/java/at/gv/egiz/pdfas/api/commons/SignatureInformation.java
new file mode 100644
index 0000000..d8c2a34
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/commons/SignatureInformation.java
@@ -0,0 +1,97 @@
+/**
+ * Copyright (c) 2006 by Know-Center, Graz, Austria
+ *
+ * This software is the confidential and proprietary information of Know-Center,
+ * Graz, Austria. You shall not disclose such Confidential Information and shall
+ * use it only in accordance with the terms of the license agreement you entered
+ * into with Know-Center.
+ *
+ * KNOW-CENTER MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
+ * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ * NON-INFRINGEMENT. KNOW-CENTER SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY
+ * LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
+ * DERIVATIVES.
+ *
+ * $Id: SignatureHolder.java,v 1.3 2006/10/11 07:57:58 wprinz Exp $
+ */
+package at.gv.egiz.pdfas.api.commons;
+
+import java.security.cert.X509Certificate;
+import java.util.Date;
+
+import at.gv.egiz.pdfas.api.io.DataSource;
+
+/**
+ * Holds the information of one found signature block, which is the signed data
+ * and the corresponding signature information.
+ *
+ * @author wprinz
+ */
+public interface SignatureInformation
+{
+ /**
+ * Returns the type of this signature (binary/textual).
+ *
+ *
+ * May be {@link Constants#SIGNATURE_TYPE_BINARY} or
+ * {@link Constants#SIGNATURE_TYPE_TEXTUAL}.
+ *
+ *
+ * @return Returns the type of this signature (binary/textual).
+ */
+ public String getSignatureType();
+
+ /**
+ * Returns the DataSource providing the data that was signed.
+ *
+ *
+ * Note that this is the signed data as sent to the verification device by
+ * PDF-AS. The verification device (e.g. MOA) may perform several other
+ * transformations on the data before feeding it to the signature hash
+ * function. To get the actual hashed data use the ReturnHashInputData mechanism (which is very slow).
+ *
+ *
+ * @return Returns the DataSource providing the data that was signed.
+ *
+ * @see at.gv.egiz.pdfas.api.verify.VerifyParameters#setReturnHashInputData(boolean)
+ * @see at.gv.egiz.pdfas.api.verify.VerifyResult#getHashInputData()
+ *
+ */
+ public DataSource getSignedData();
+
+ /**
+ * Returns the certificate of the signer.
+ *
+ *
+ * Information like subject name, issuer name or serial number can be
+ * retrieved form this certificate.
+ *
+ *
+ * @return Returns the certificate of the signer.
+ */
+ public X509Certificate getSignerCertificate();
+
+ /**
+ * Returns the signing time, which is the time when the signature was created.
+ *
+ * @return Returns the signing time, which is the time when the signature was
+ * created.
+ */
+ public Date getSigningTime();
+
+ /**
+ * Returns additional, internal information about the found signature.
+ *
+ *
+ * Note that this provides a way for developers to gather core information
+ * about the signature. What information is returned strongly depends on the
+ * core implementation.
+ *
+ *
+ * @return Returns additional, internal information about the signature. Null
+ * means that no additional information is available.
+ */
+ public Object getInternalSignatureInformation();
+
+}
\ No newline at end of file
diff --git a/src/main/java/at/gv/egiz/pdfas/api/commons/SignatureProfile.java b/src/main/java/at/gv/egiz/pdfas/api/commons/SignatureProfile.java
new file mode 100644
index 0000000..52bd27f
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/commons/SignatureProfile.java
@@ -0,0 +1,29 @@
+/**
+ *
+ */
+package at.gv.egiz.pdfas.api.commons;
+
+/**
+ * Definition of a signature profile.
+ *
+ * @author wprinz
+ */
+public interface SignatureProfile
+{
+ // TODO: the full profile information will be implemented in future
+
+ /**
+ * Returns the profile id.
+ *
+ * @return Returns the profile id.
+ */
+ public String getProfileId();
+
+ /**
+ * Returns the MOA KeyIdentifier.
+ *
+ * @return Returns the MOA KeyIdentifier.
+ */
+ public String getMOAKeyIdentifier();
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/exceptions/PdfAsException.java b/src/main/java/at/gv/egiz/pdfas/api/exceptions/PdfAsException.java
new file mode 100644
index 0000000..2986f81
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/exceptions/PdfAsException.java
@@ -0,0 +1,78 @@
+/**
+ *
+ */
+package at.gv.egiz.pdfas.api.exceptions;
+
+/**
+ * This exception is the base for all PDF-AS exceptions.
+ *
+ *
+ * Every PDF-AS Exception has an error code.
+ *
+ *
+ * @author wprinz
+ */
+public abstract class PdfAsException extends Exception
+{
+ /**
+ * The error code.
+ */
+ protected int errorCode = -1;
+
+ /**
+ * Constructor.
+ *
+ * @param errorCode
+ * The error code.
+ * @param message
+ * The detail message.
+ */
+ public PdfAsException(int errorCode, String message)
+ {
+ super(message);
+
+ this.errorCode = errorCode;
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param errorCode
+ * The error code.
+ * @param message
+ * The detail message.
+ * @param cause
+ * The cause.
+ */
+ public PdfAsException(int errorCode, String message, Throwable cause)
+ {
+ super(message, cause);
+
+ this.errorCode = errorCode;
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param errorCode
+ * The error code.
+ * @param cause
+ * The cause.
+ */
+ public PdfAsException(int errorCode, Throwable cause)
+ {
+ super(cause);
+
+ this.errorCode = errorCode;
+ }
+
+ /**
+ * Returns the error code of this exception.
+ *
+ * @return Returns the error code of this exception.
+ */
+ public int getErrorCode()
+ {
+ return this.errorCode;
+ }
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/io/DataSink.java b/src/main/java/at/gv/egiz/pdfas/api/io/DataSink.java
new file mode 100644
index 0000000..0136cf7
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/io/DataSink.java
@@ -0,0 +1,75 @@
+package at.gv.egiz.pdfas.api.io;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Output document data sink.
+ *
+ *
+ * Actually, the DataSink can be seen as a factory for creating OutputStreams
+ * with mime type and character encoding provided. This allows the API user to
+ * decide how data is to be stored (e.g. in a file, in a byte array, etc.).
+ *
+ * Note that the stream may be written only once. Creating another stream
+ * overwrites the existing one.
+ *
+ *
+ * @param mimeType
+ * The mime type of the output data.
+ * @return Returns the created output stream.
+ * @throws IOException
+ * Thrown if the stream cannot be created.
+ */
+ public OutputStream createOutputStream(String mimeType) throws IOException;
+
+ /**
+ * Creates an OutputStream for character data.
+ *
+ *
+ * This is basically the same as {@link #createOutputStream(String)}, but
+ * allows to specify the character encoding.
+ *
+ *
+ * @param mimeType
+ * The mime type of the output data.
+ * @param characterEncoding
+ * The character encoding of the data.
+ * @return Returns the created output stream.
+ * @throws IOException
+ * Thrown if the stream cannot be created.
+ */
+ public OutputStream createOutputStream(String mimeType, String characterEncoding) throws IOException;
+
+ /**
+ * Returns the mime type of the data stream.
+ *
+ *
+ * This is only valid after a stream has been created.
+ *
+ *
+ * @return Returns the mime type of the data stream.
+ */
+ public String getMimeType();
+
+ /**
+ * Returns the character encoding of the data stream.
+ *
+ *
+ * This is only valid after a stream has been created. Null means that no
+ * character encoding was specified for the data (e.g. if the data is binary).
+ *
+ *
+ * @return Returns the character encoding of the data stream.
+ */
+ public String getCharacterEncoding();
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/io/DataSource.java b/src/main/java/at/gv/egiz/pdfas/api/io/DataSource.java
new file mode 100644
index 0000000..bd8e0db
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/io/DataSource.java
@@ -0,0 +1,74 @@
+/**
+ *
+ */
+package at.gv.egiz.pdfas.api.io;
+
+import java.io.InputStream;
+
+/**
+ * Input document data source.
+ *
+ *
+ * This allows the holder of the data to decide how the data is to be stored (e.g. in a File or in a byte array).
+ *
+ *
+ * @author wprinz
+ *
+ */
+public interface DataSource
+{
+ /**
+ * Creates a new InputStream that allows to read out the document's binary
+ * data from the beginning.
+ *
+ * @return Returns the InputStream with the binary data.
+ */
+ public InputStream createInputStream();
+
+ /**
+ * Returns the length (number of bytes) of the stream.
+ *
+ * @return Returns the length (number of bytes) of the stream.
+ */
+ public int getLength();
+
+ /**
+ * Returns the data of this DataSource as a byte array for random read only access.
+ *
+ *
+ * Calling this method indicates that you need a byte array for random
+ * read only access. The DataSource implementation should of
+ * course cache this byte array to avoid too much memory usage.
+ *
+ *
+ * Performance analysis has shown that the libraries internally convert the
+ * streams to byte arrays and that file system access is very slow.
+ *
+ *
+ * Never write to this byte array!
+ *
+ *
+ * @return Returns the data of this DataSource as a byte array for random read only access.
+ */
+ public byte[] getAsByteArray();
+
+ /**
+ * Returns the mime type of the data.
+ *
+ * @return Returns the mime type of the data.
+ */
+ public String getMimeType();
+
+ /**
+ * Returns the character encoding of the data.
+ *
+ *
+ * This makes only sense for character based mime types.
+ *
+ *
+ * @return Returns the character encoding of the data or null if no encoding
+ * is applicable (e.g. if the data is binary).
+ */
+ public String getCharacterEncoding();
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/io/FileBased.java b/src/main/java/at/gv/egiz/pdfas/api/io/FileBased.java
new file mode 100644
index 0000000..555b630
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/io/FileBased.java
@@ -0,0 +1,31 @@
+/**
+ *
+ */
+package at.gv.egiz.pdfas.api.io;
+
+import java.io.File;
+
+/**
+ * Tells that the IO element (DataSink or DataSource) is backed by a file in the local file system.
+ *
+ *
+ * This is a hint that may be used by PDF-AS to optimize data access.
+ *
+ * This is usually used to determine the file name itself.
+ *
+ *
+ * @return Returns the File "behind" this io element.
+ */
+ public File getFile ();
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/io/TextBased.java b/src/main/java/at/gv/egiz/pdfas/api/io/TextBased.java
new file mode 100644
index 0000000..68b5729
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/io/TextBased.java
@@ -0,0 +1,30 @@
+/**
+ *
+ */
+package at.gv.egiz.pdfas.api.io;
+
+/**
+ * Tells, that the IO Element (DataSink - but mostly DataSource) is based upon
+ * character data.
+ *
+ *
+ * This can be used to retrieve the character text directly with the correct
+ * encoding etc.
+ *
+ *
+ * This makes most sense for text DataSources.
+ *
+ *
+ * @author wprinz
+ */
+public interface TextBased
+{
+
+ /**
+ * Returns the text.
+ *
+ * @return Returns the text.
+ */
+ public String getText();
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/sign/SignParameters.java b/src/main/java/at/gv/egiz/pdfas/api/sign/SignParameters.java
new file mode 100644
index 0000000..cc59cbd
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/sign/SignParameters.java
@@ -0,0 +1,173 @@
+/**
+ *
+ */
+package at.gv.egiz.pdfas.api.sign;
+
+import at.gv.egiz.pdfas.api.commons.Constants;
+import at.gv.egiz.pdfas.api.io.DataSink;
+import at.gv.egiz.pdfas.api.io.DataSource;
+import at.gv.egiz.pdfas.api.sign.pos.SignaturePositioning;
+
+/**
+ * Parameter object that holds the sign parameters.
+ *
+ * @author wprinz
+ */
+public class SignParameters
+{
+ /**
+ * The document to be signed.
+ *
+ *
+ * The DataSource implementation encapsulates the actual representaion of the
+ * data. E.g. the DataSource may be File based or byte array based. See
+ * package at.gv.egiz.pdfas.framework.input and at.gv.pdfas.impl.input
+ *
+ */
+ protected DataSource document = null;
+
+ /**
+ * The type of the signature.
+ *
+ *
+ * May be {@link Constants#SIGNATURE_TYPE_BINARY} or
+ * {@link Constants#SIGNATURE_TYPE_TEXTUAL}.
+ *
+ */
+ protected String signatureType = Constants.SIGNATURE_TYPE_BINARY;
+
+ /**
+ * The signature device to perform the actual signature.
+ *
+ *
+ * May be {@link Constants#SIGNATURE_DEVICE_MOA} or
+ * {@link Constants#SIGNATURE_DEVICE_BKU}.
+ *
+ */
+ protected String signatureDevice = Constants.SIGNATURE_DEVICE_MOA;
+
+ /**
+ * The signature profile identifier identifying the profile to be used in the
+ * config file.
+ *
+ *
+ * Note: In near future it will be possible to provide a full specified
+ * profile here instead of the profile id.
+ *
+ */
+ protected String signatureProfileId = null;;
+
+ /**
+ * The signature position. Consult the PDF-AS documentation section
+ * Commandline.
+ */
+ protected SignaturePositioning signaturePositioning = null;
+
+ /**
+ * The output DataSink that will receive the signed document.
+ */
+ protected DataSink output = null;
+
+ /**
+ * @return the document
+ */
+ public DataSource getDocument()
+ {
+ return document;
+ }
+
+ /**
+ * @param document
+ * the document to set
+ */
+ public void setDocument(DataSource document)
+ {
+ this.document = document;
+ }
+
+ /**
+ * @return the signatureType
+ */
+ public String getSignatureType()
+ {
+ return signatureType;
+ }
+
+ /**
+ * @param signatureType
+ * the signatureType to set
+ */
+ public void setSignatureType(String signatureType)
+ {
+ this.signatureType = signatureType;
+ }
+
+ /**
+ * @return the signatureDevice
+ */
+ public String getSignatureDevice()
+ {
+ return signatureDevice;
+ }
+
+ /**
+ * @param signatureDevice
+ * the signatureDevice to set
+ */
+ public void setSignatureDevice(String signatureDevice)
+ {
+ this.signatureDevice = signatureDevice;
+ }
+
+ /**
+ * @return the signatureProfileId
+ */
+ public String getSignatureProfileId()
+ {
+ return signatureProfileId;
+ }
+
+ /**
+ * @param signatureProfileId
+ * the signatureProfileId to set
+ */
+ public void setSignatureProfileId(String signatureProfileId)
+ {
+ this.signatureProfileId = signatureProfileId;
+ }
+
+ /**
+ * @return the signaturePositioning
+ */
+ public SignaturePositioning getSignaturePositioning()
+ {
+ return this.signaturePositioning;
+ }
+
+ /**
+ * @param signaturePositioning
+ * the signaturePositioning to set
+ */
+ public void setSignaturePositioning(SignaturePositioning signaturePositioning)
+ {
+ this.signaturePositioning = signaturePositioning;
+ }
+
+ /**
+ * @return the output
+ */
+ public DataSink getOutput()
+ {
+ return output;
+ }
+
+ /**
+ * @param output
+ * the output to set
+ */
+ public void setOutput(DataSink output)
+ {
+ this.output = output;
+ }
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/sign/SignResult.java b/src/main/java/at/gv/egiz/pdfas/api/sign/SignResult.java
new file mode 100644
index 0000000..519a9e1
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/sign/SignResult.java
@@ -0,0 +1,49 @@
+/**
+ *
+ */
+package at.gv.egiz.pdfas.api.sign;
+
+import java.security.cert.X509Certificate;
+
+import at.gv.egiz.pdfas.api.io.DataSink;
+import at.gv.egiz.pdfas.api.sign.pos.SignaturePosition;
+
+/**
+ * The result of a sign operation.
+ *
+ * @author wprinz
+ */
+public interface SignResult
+{
+
+ /**
+ * Returns the filled output data sink.
+ *
+ * @return Returns the filled output data sink.
+ */
+ public DataSink getOutputDocument();
+
+ /**
+ * Returns the certificate of the signer.
+ *
+ * @return Returns the certificate of the signer.
+ */
+ public X509Certificate getSignerCertificate();
+
+ /**
+ * Returns the position where the signature is finally placed.
+ *
+ *
+ * This information can be useful for post-processing the document.
+ *
+ *
+ *
+ * Consult the PDF-AS documentation section Commandline for further
+ * information about positioning.
+ *
+ *
+ * @return Returns the position where the signature is finally placed. May
+ * return null if no position information is available.
+ */
+ public SignaturePosition getSignaturePosition();
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/sign/pos/SignaturePosition.java b/src/main/java/at/gv/egiz/pdfas/api/sign/pos/SignaturePosition.java
new file mode 100644
index 0000000..8dc6b6c
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/sign/pos/SignaturePosition.java
@@ -0,0 +1,52 @@
+/**
+ *
+ */
+package at.gv.egiz.pdfas.api.sign.pos;
+
+/**
+ * Holds the actual, absolute signature position where a signature was placed.
+ *
+ *
+ * This is usually returned after signing.
+ *
+ *
+ * @author wprinz
+ */
+public interface SignaturePosition
+{
+ /**
+ * Returns the page on which the signature was placed.
+ *
+ * @return Returns the page on which the signature was placed.
+ */
+ public int getPage();
+
+ /**
+ * Returns the x position.
+ *
+ * @return Returns the x position.
+ */
+ public float getX();
+
+ /**
+ * Returns the y position.
+ *
+ * @return Returns the y position.
+ */
+ public float getY();
+
+ /**
+ * Returns the width of the signature.
+ *
+ * @return Returns the width of the signature.
+ */
+ public float getWidth();
+
+ /**
+ * Returns the height of the signature.
+ *
+ * @return Returns the height of the signature.
+ */
+ public float getHeight();
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/sign/pos/SignaturePositioning.java b/src/main/java/at/gv/egiz/pdfas/api/sign/pos/SignaturePositioning.java
new file mode 100644
index 0000000..b9e2c8a
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/sign/pos/SignaturePositioning.java
@@ -0,0 +1,189 @@
+/**
+ *
+ */
+package at.gv.egiz.pdfas.api.sign.pos;
+
+import at.gv.egiz.pdfas.api.sign.pos.axis.AbsoluteAxisAlgorithm;
+import at.gv.egiz.pdfas.api.sign.pos.axis.AutoAxisAlgorithm;
+import at.gv.egiz.pdfas.api.sign.pos.axis.AxisAlgorithm;
+import at.gv.egiz.pdfas.api.sign.pos.page.AbsolutePageAlgorithm;
+import at.gv.egiz.pdfas.api.sign.pos.page.AutoPageAlgorithm;
+import at.gv.egiz.pdfas.api.sign.pos.page.NewPageAlgorithm;
+import at.gv.egiz.pdfas.api.sign.pos.page.PageAlgorithm;
+
+/**
+ * Defines how the signature positioning is to be performed.
+ *
+ *
+ * This positioning allows to select the location where the signature block is
+ * placed in the document.
+ *
+ *
+ * @author wprinz
+ */
+public class SignaturePositioning
+{
+ /**
+ * The x axis algorithm.
+ *
+ *
+ * May be {@link AutoAxisAlgorithm} or {@link AbsoluteAxisAlgorithm}
+ *
+ */
+ protected AxisAlgorithm xAlgorithm = new AutoAxisAlgorithm();
+
+ /**
+ * The y axis algorithm.
+ *
+ *
+ * May be {@link AutoAxisAlgorithm} or {@link AbsoluteAxisAlgorithm}
+ *
+ * May be {@link AutoPageAlgorithm}, {@link AbsolutePageAlgorithm} or
+ * {@link NewPageAlgorithm}
+ *
+ */
+ protected PageAlgorithm pageAlgorithm = new AutoPageAlgorithm();
+
+ /**
+ * Provides the position of the footline.
+ *
+ *
+ * Only used if the pageAlgorithm is {@link AutoPageAlgorithm} and the
+ * yAlgorithm is {@link AutoAxisAlgorithm}
+ *
+ */
+ protected float footerLine = 0.0f;
+
+ protected void checkAxisAlgorithm(AxisAlgorithm algorithm)
+ {
+ if (algorithm == null)
+ {
+ throw new IllegalArgumentException("The algorithm must not be null.");
+ }
+ if (!(algorithm instanceof AutoAxisAlgorithm) && !(algorithm instanceof AbsoluteAxisAlgorithm))
+ {
+ throw new IllegalArgumentException("The algorithm must be either Auto or Absolute.");
+ }
+ }
+
+ protected void checkPageAlgorithm(PageAlgorithm algorithm)
+ {
+ if (algorithm == null)
+ {
+ throw new IllegalArgumentException("The algorithm must not be null.");
+ }
+ if (!(algorithm instanceof AutoPageAlgorithm) && !(algorithm instanceof AbsolutePageAlgorithm) && !(algorithm instanceof NewPageAlgorithm))
+ {
+ throw new IllegalArgumentException("The algorithm must be either Auto or Absolute.");
+ }
+
+ }
+
+ /**
+ * @return the xAlgorithm
+ */
+ public AxisAlgorithm getXAlgorithm()
+ {
+ return this.xAlgorithm;
+ }
+
+ /**
+ * @param algorithm
+ * the xAlgorithm to set
+ */
+ public void setXAlgorithm(AxisAlgorithm algorithm)
+ {
+ checkAxisAlgorithm(algorithm);
+ xAlgorithm = algorithm;
+ }
+
+ /**
+ * @return the yAlgorithm
+ */
+ public AxisAlgorithm getYAlgorithm()
+ {
+ return this.yAlgorithm;
+ }
+
+ /**
+ * @param algorithm
+ * the yAlgorithm to set
+ */
+ public void setYAlgorithm(AxisAlgorithm algorithm)
+ {
+ checkAxisAlgorithm(algorithm);
+
+ yAlgorithm = algorithm;
+ }
+
+ /**
+ * @return the widthAlgorithm
+ */
+ public AxisAlgorithm getWidthAlgorithm()
+ {
+ return this.widthAlgorithm;
+ }
+
+ /**
+ * @param widthAlgorithm
+ * the widthAlgorithm to set
+ */
+ public void setWidthAlgorithm(AxisAlgorithm widthAlgorithm)
+ {
+ checkAxisAlgorithm(widthAlgorithm);
+
+ this.widthAlgorithm = widthAlgorithm;
+ }
+
+ /**
+ * @return the pageAlgorithm
+ */
+ public PageAlgorithm getPageAlgorithm()
+ {
+ return this.pageAlgorithm;
+ }
+
+ /**
+ * @param pageAlgorithm
+ * the pageAlgorithm to set
+ */
+ public void setPageAlgorithm(PageAlgorithm pageAlgorithm)
+ {
+ checkPageAlgorithm(pageAlgorithm);
+ this.pageAlgorithm = pageAlgorithm;
+ }
+
+ /**
+ * @return the footerLine
+ */
+ public float getFooterLine()
+ {
+ return this.footerLine;
+ }
+
+ /**
+ * @param footerLine
+ * the footerLine to set
+ */
+ public void setFooterLine(float footerLine)
+ {
+ this.footerLine = footerLine;
+ }
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/sign/pos/axis/AbsoluteAxisAlgorithm.java b/src/main/java/at/gv/egiz/pdfas/api/sign/pos/axis/AbsoluteAxisAlgorithm.java
new file mode 100644
index 0000000..234484c
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/sign/pos/axis/AbsoluteAxisAlgorithm.java
@@ -0,0 +1,35 @@
+/**
+ *
+ */
+package at.gv.egiz.pdfas.api.sign.pos.axis;
+
+/**
+ * An absolute positioned element.
+ * @author wprinz
+ */
+public class AbsoluteAxisAlgorithm extends AxisAlgorithm
+{
+
+ /**
+ * The absolute positioning value on the axis.
+ */
+ protected float absoluteValue = 0.0f;
+
+ /**
+ * Constructor.
+ * @param absoluteValue The absolute positioning value on the axis.
+ */
+ public AbsoluteAxisAlgorithm (float absoluteValue)
+ {
+ this.absoluteValue = absoluteValue;
+ }
+
+ /**
+ * Returns absolute positioning value on the axis.
+ * @return the absoluteValue Returns absolute positioning value on the axis.
+ */
+ public float getAbsoluteValue()
+ {
+ return this.absoluteValue;
+ }
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/sign/pos/axis/AutoAxisAlgorithm.java b/src/main/java/at/gv/egiz/pdfas/api/sign/pos/axis/AutoAxisAlgorithm.java
new file mode 100644
index 0000000..4c5459f
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/sign/pos/axis/AutoAxisAlgorithm.java
@@ -0,0 +1,14 @@
+/**
+ *
+ */
+package at.gv.egiz.pdfas.api.sign.pos.axis;
+
+/**
+ * Auto positioning for this element.
+ *
+ * @author wprinz
+ */
+public class AutoAxisAlgorithm extends AxisAlgorithm
+{
+// empty
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/sign/pos/axis/AxisAlgorithm.java b/src/main/java/at/gv/egiz/pdfas/api/sign/pos/axis/AxisAlgorithm.java
new file mode 100644
index 0000000..a4baac6
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/sign/pos/axis/AxisAlgorithm.java
@@ -0,0 +1,14 @@
+/**
+ *
+ */
+package at.gv.egiz.pdfas.api.sign.pos.axis;
+
+/**
+ * Determines how a certain position is chosen on the axis (x, y, width).
+ *
+ * @author wprinz
+ */
+public abstract class AxisAlgorithm
+{
+// base class
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/AbsolutePageAlgorithm.java b/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/AbsolutePageAlgorithm.java
new file mode 100644
index 0000000..206aa19
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/AbsolutePageAlgorithm.java
@@ -0,0 +1,37 @@
+/**
+ *
+ */
+package at.gv.egiz.pdfas.api.sign.pos.page;
+
+/**
+ * The page is selected absolutely by giving the page number directly.
+ *
+ * @author wprinz
+ */
+public class AbsolutePageAlgorithm extends PageAlgorithm
+{
+ /**
+ * The page.
+ */
+ protected int page = -1;
+
+ /**
+ * Constructor.
+ *
+ * @param page
+ * The page.
+ */
+ public AbsolutePageAlgorithm(int page)
+ {
+ this.page = page;
+ }
+
+ /**
+ * @return the page
+ */
+ public int getPage()
+ {
+ return this.page;
+ }
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/AutoPageAlgorithm.java b/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/AutoPageAlgorithm.java
new file mode 100644
index 0000000..0070d5e
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/AutoPageAlgorithm.java
@@ -0,0 +1,20 @@
+/**
+ *
+ */
+package at.gv.egiz.pdfas.api.sign.pos.page;
+
+/**
+ * The page for placing the signature is selected automatically.
+ *
+ *
+ * The algorithm first tries to place the signature on the free space of the
+ * last page (considering the footer). If there is not enough space on the last
+ * page, a new page is appended and the signature is placed there.
+ *
+ *
+ * @author wprinz
+ */
+public class AutoPageAlgorithm extends PageAlgorithm
+{
+// empty
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/NewPageAlgorithm.java b/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/NewPageAlgorithm.java
new file mode 100644
index 0000000..2a8f67c
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/NewPageAlgorithm.java
@@ -0,0 +1,14 @@
+/**
+ *
+ */
+package at.gv.egiz.pdfas.api.sign.pos.page;
+
+/**
+ * Places the signature on a new Page.
+ *
+ * @author wprinz
+ */
+public class NewPageAlgorithm extends PageAlgorithm
+{
+ // empty block
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/PageAlgorithm.java b/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/PageAlgorithm.java
new file mode 100644
index 0000000..9b0fe8a
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/PageAlgorithm.java
@@ -0,0 +1,14 @@
+/**
+ *
+ */
+package at.gv.egiz.pdfas.api.sign.pos.page;
+
+/**
+ * Determines how the page on which the signature is to be placed is selected.
+ *
+ * @author wprinz
+ */
+public abstract class PageAlgorithm
+{
+ // empty
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/verify/SignatureCheck.java b/src/main/java/at/gv/egiz/pdfas/api/verify/SignatureCheck.java
new file mode 100644
index 0000000..df29570
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/verify/SignatureCheck.java
@@ -0,0 +1,31 @@
+/**
+ *
+ */
+package at.gv.egiz.pdfas.api.verify;
+
+/**
+ * The result of a signature check performed by a verification device.
+ *
+ * @see VerifyResult
+ *
+ * @author wprinz
+ */
+public interface SignatureCheck
+{
+ /**
+ * Returns the response code of the check.
+ *
+ * @return Returns the response code of the check.
+ */
+ public int getCode();
+
+ /**
+ * Returns the textual response message of the check (corresponding to the
+ * code).
+ *
+ * @return Returns the textual response message of the check (corresponding to
+ * the code).
+ */
+ public String getMessage();
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyAfterAnalysisParameters.java b/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyAfterAnalysisParameters.java
new file mode 100644
index 0000000..dd50d79
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyAfterAnalysisParameters.java
@@ -0,0 +1,117 @@
+/**
+ *
+ */
+package at.gv.egiz.pdfas.api.verify;
+
+import java.util.Date;
+
+import at.gv.egiz.pdfas.api.analyze.AnalyzeResult;
+import at.gv.egiz.pdfas.api.commons.Constants;
+
+/**
+ * Parameter object that holds the verify after analysis parameters.
+ *
+ * @author wprinz
+ */
+public class VerifyAfterAnalysisParameters
+{
+
+ /**
+ * The list of signatures to be verified.
+ */
+ protected AnalyzeResult analyzeResult = null;
+
+ /**
+ * The signature device to perform the actual signature.
+ *
+ *
+ * May be {@link Constants#SIGNATURE_DEVICE_MOA} or
+ * {@link Constants#SIGNATURE_DEVICE_BKU}.
+ *
+ */
+ protected String signatureDevice = Constants.SIGNATURE_DEVICE_MOA;
+
+ /**
+ * Allows to pass a VerificationTime to the signature device.
+ */
+ protected Date verificationTime = null;
+
+ /**
+ * Tells the signature device (e.g. MOA) to return the signature hash input
+ * data (which is the probably transformed signed data).
+ *
+ *
+ * Note that this forces MOA to return the potentially large signature data to
+ * be returned in the result XML, which may result in very bad performance.
+ *
+ */
+ protected boolean returnHashInputData = false;
+
+ /**
+ * @return the analyzeResult
+ */
+ public AnalyzeResult getAnalyzeResult()
+ {
+ return this.analyzeResult;
+ }
+
+ /**
+ * @param analyzeResult
+ * the analyzeResult to set
+ */
+ public void setAnalyzeResult(AnalyzeResult analyzeResult)
+ {
+ this.analyzeResult = analyzeResult;
+ }
+
+ /**
+ * @return the signatureDevice
+ */
+ public String getSignatureDevice()
+ {
+ return this.signatureDevice;
+ }
+
+ /**
+ * @param signatureDevice
+ * the signatureDevice to set
+ */
+ public void setSignatureDevice(String signatureDevice)
+ {
+ this.signatureDevice = signatureDevice;
+ }
+
+ /**
+ * @return the verificationTime
+ */
+ public Date getVerificationTime()
+ {
+ return this.verificationTime;
+ }
+
+ /**
+ * @param verificationTime the verificationTime to set
+ */
+ public void setVerificationTime(Date verificationTime)
+ {
+ this.verificationTime = verificationTime;
+ }
+
+ /**
+ * @return the returnHashInputData
+ */
+ public boolean isReturnHashInputData()
+ {
+ return this.returnHashInputData;
+ }
+
+ /**
+ * @param returnHashInputData
+ * the returnHashInputData to set
+ */
+ public void setReturnHashInputData(boolean returnHashInputData)
+ {
+ this.returnHashInputData = returnHashInputData;
+ }
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyParameters.java b/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyParameters.java
new file mode 100644
index 0000000..fb3b8b8
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyParameters.java
@@ -0,0 +1,183 @@
+/**
+ *
+ */
+package at.gv.egiz.pdfas.api.verify;
+
+import java.util.Date;
+
+import at.gv.egiz.pdfas.api.commons.Constants;
+import at.gv.egiz.pdfas.api.io.DataSource;
+
+/**
+ * Parameter object that holds the verify parameters.
+ *
+ * @author wprinz
+ */
+public class VerifyParameters
+{
+ // This would be a perfect point for multiple inheritance in Java.
+ // VerifyParameters extends AnalyzeParameters, VerifyAfterAnalysisParameters
+ // Then a lot of code could be easily reused in the PdfAsObject's check*Parameters methods.
+
+ /**
+ * The document to be verified.
+ */
+ protected DataSource document = null;
+
+ /**
+ * The signature device to perform the actual signature.
+ *
+ *
+ * May be {@link Constants#SIGNATURE_DEVICE_MOA} or
+ * {@link Constants#SIGNATURE_DEVICE_BKU}.
+ *
+ */
+ protected String signatureDevice = Constants.SIGNATURE_DEVICE_MOA;
+
+ /**
+ * The mode of operation how the document is analyzed.
+ *
+ *
+ * May be {@link Constants#VERIFY_MODE_BINARY_ONLY} to check the document for
+ * binary signatures only (very fast). Or may be
+ * {@link Constants#VERIFY_MODE_SEMI_CONSERVATIVE} to perform a semi
+ * conservative (optimized) text and binary verification (slow). Or may be
+ * {@link Constants#VERIFY_MODE_FULL_CONSERVATIVE} to perform a full
+ * conservative text and binary verification (very slow).
+ *
+ */
+ protected String verifyMode = Constants.VERIFY_MODE_FULL_CONSERVATIVE;
+
+ /**
+ * The (zero based) index of the signature to verify.
+ *
+ *
+ * This allows to verify only one found signature instead of all. {@link Constants#VERIFY_ALL} means to
+ * verify all found signatures.
+ *
+ */
+ protected int signatureToVerify = Constants.VERIFY_ALL;
+
+ /**
+ * Allows to pass a VerificationTime to the verification device.
+ *
+ *
+ * Note that the actual usage of this parameter depends on the verification device.
+ *
+ */
+ protected Date verificationTime = null;
+
+ /**
+ * Tells the signature device (e.g. MOA) to return the signature hash input
+ * data (which is the probably transformed signed data).
+ *
+ *
+ * Note that this forces MOA to return the potentially large signature data to
+ * be returned in the result XML, which may result in very bad performance.
+ *
+ */
+ protected boolean returnHashInputData = false;
+
+ /**
+ * @return the document
+ */
+ public DataSource getDocument()
+ {
+ return this.document;
+ }
+
+ /**
+ * @param document
+ * the document to set
+ */
+ public void setDocument(DataSource document)
+ {
+ this.document = document;
+ }
+
+ /**
+ * @return the signatureDevice
+ */
+ public String getSignatureDevice()
+ {
+ return this.signatureDevice;
+ }
+
+ /**
+ * @param signatureDevice
+ * the signatureDevice to set
+ */
+ public void setSignatureDevice(String signatureDevice)
+ {
+ this.signatureDevice = signatureDevice;
+ }
+
+ /**
+ * @return the verifyMode
+ */
+ public String getVerifyMode()
+ {
+ return this.verifyMode;
+ }
+
+ /**
+ * @param verifyMode
+ * the verifyMode to set
+ */
+ public void setVerifyMode(String verifyMode)
+ {
+ this.verifyMode = verifyMode;
+ }
+
+ /**
+ * @return the signatureToVerify
+ */
+ public int getSignatureToVerify()
+ {
+ return this.signatureToVerify;
+ }
+
+ /**
+ * @param signatureToVerify
+ * the signatureToVerify to set
+ */
+ public void setSignatureToVerify(int signatureToVerify)
+ {
+ this.signatureToVerify = signatureToVerify;
+ }
+
+ /**
+ * @return the verificationTime
+ */
+ public Date getVerificationTime()
+ {
+ return this.verificationTime;
+ }
+
+ /**
+ * @param verificationTime
+ * the verificationTime to set
+ */
+ public void setVerificationTime(Date verificationTime)
+ {
+ this.verificationTime = verificationTime;
+ }
+
+ /**
+ * @return the returnHashInputData
+ */
+ public boolean isReturnHashInputData()
+ {
+ return this.returnHashInputData;
+ }
+
+ /**
+ * @param returnHashInputData
+ * the returnHashInputData to set
+ */
+ public void setReturnHashInputData(boolean returnHashInputData)
+ {
+ this.returnHashInputData = returnHashInputData;
+ }
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyResult.java b/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyResult.java
new file mode 100644
index 0000000..be5a88f
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyResult.java
@@ -0,0 +1,97 @@
+package at.gv.egiz.pdfas.api.verify;
+
+import java.util.Date;
+import java.util.List;
+
+import at.gv.egiz.pdfas.api.commons.SignatureInformation;
+
+/**
+ * Encapsulates the data of a verification of one signature.
+ *
+ * @author wprinz
+ */
+public interface VerifyResult extends SignatureInformation
+{
+ /**
+ * Returns the result of the certificate check.
+ *
+ * @return Returns the result of the certificate check.
+ */
+ public SignatureCheck getCertificateCheck();
+
+ /**
+ * Returns the result of the value (and hash) check.
+ *
+ * @return Returns the result of the value (and hash) check.
+ */
+ public SignatureCheck getValueCheckCode();
+
+ /**
+ * Returns the result of the manifest check.
+ *
+ * @return Returns the result of the manifest check.
+ */
+ public SignatureCheck getManifestCheckCode();
+
+ /**
+ * Returns true, if the signer's certificate is a qualified certificate.
+ *
+ * @return Returns true, if the signer's certificate is a qualified
+ * certificate.
+ */
+ public boolean isQualifiedCertificate();
+
+ /**
+ * Returns a list of Strings each stating one public property of the
+ * certificate.
+ *
+ *
+ * Such public properties are certificate extensions each being assigned an
+ * own OID. For example the public property "Verwaltungseigenschaft" has the
+ * OID "1.2.40.0.10.1.1.1".
+ *
+ *
+ * @return Returns the list of Strings representing the public properties of
+ * this certificate, if any.
+ */
+ public List getPublicProperties();
+
+ /**
+ * Returns the verification time, which is the time when the signature was
+ * verified.
+ *
+ *
+ * Note that this is actually the Date passed to the verify methods over
+ * {@link VerifyParameters#setVerificationTime(Date)} or
+ * {@link VerifyAfterAnalysisParameters#setVerificationTime(Date)}. The
+ * signature devices don't respond the actual verification time so there is no
+ * guarantee that the set verification time was actually used as time of
+ * verification. Please consult the device's documentation for more
+ * information.
+ *
+ *
+ * @return Returns the verification time, which is the time when the signature
+ * was verified.
+ */
+ public Date getVerificationTime();
+
+ /**
+ * Returns the hash input data as returned by MOA.
+ *
+ *
+ * This will only return a value other than null if the corresponding
+ * VerifyParameter was set to true.
+ *
+ *
+ * Note that the HashInputData does not necessarily have to be exactly the
+ * same as the signed date return by the
+ * {@link SignatureInformation#getSignedData()} method.
+ *
+ *
+ * @return Returns the hash input data as returned by MOA.
+ *
+ * @see SignatureInformation#getSignedData()
+ */
+ public String getHashInputData();
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyResults.java b/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyResults.java
new file mode 100644
index 0000000..abda1fe
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyResults.java
@@ -0,0 +1,27 @@
+/**
+ *
+ */
+package at.gv.egiz.pdfas.api.verify;
+
+import java.util.List;
+
+/**
+ * The result of the verification of a document.
+ *
+ *
+ * Currently, this is not more than a list of VerifyResult objects, one for each
+ * verified signature. There may be additional items in future PDF-AS versions.
+ *
+ *
+ * @author wprinz
+ */
+public interface VerifyResults
+{
+ /**
+ * Returns the List of VerifyResult objects, one for each verified signature.
+ *
+ * @return Returns the List of VerifyResult objects, one for each verified
+ * signature.
+ */
+ public List getResults();
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/commandline/Main.java b/src/main/java/at/gv/egiz/pdfas/commandline/Main.java
new file mode 100644
index 0000000..415c1fd
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/commandline/Main.java
@@ -0,0 +1,1071 @@
+/**
+ * Copyright (c) 2006 by Know-Center, Graz, Austria
+ *
+ * This software is the confidential and proprietary information of Know-Center,
+ * Graz, Austria. You shall not disclose such Confidential Information and shall
+ * use it only in accordance with the terms of the license agreement you entered
+ * into with Know-Center.
+ *
+ * KNOW-CENTER MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
+ * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+ * NON-INFRINGEMENT. KNOW-CENTER SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY
+ * LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
+ * DERIVATIVES.
+ *
+ * $Id: Main.java,v 1.5 2006/10/31 08:06:56 wprinz Exp $
+ */
+package at.gv.egiz.pdfas.commandline;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.log4j.PropertyConfigurator;
+
+import at.gv.egiz.pdfas.PdfAsFactory;
+import at.gv.egiz.pdfas.api.PdfAs;
+import at.gv.egiz.pdfas.api.commons.Constants;
+import at.gv.egiz.pdfas.api.exceptions.PdfAsException;
+import at.gv.egiz.pdfas.api.io.DataSink;
+import at.gv.egiz.pdfas.api.io.DataSource;
+import at.gv.egiz.pdfas.api.sign.SignParameters;
+import at.gv.egiz.pdfas.api.sign.pos.SignaturePositioning;
+import at.gv.egiz.pdfas.api.sign.pos.axis.AbsoluteAxisAlgorithm;
+import at.gv.egiz.pdfas.api.sign.pos.page.AbsolutePageAlgorithm;
+import at.gv.egiz.pdfas.api.sign.pos.page.NewPageAlgorithm;
+import at.gv.egiz.pdfas.api.verify.VerifyParameters;
+import at.gv.egiz.pdfas.api.verify.VerifyResult;
+import at.gv.egiz.pdfas.api.verify.VerifyResults;
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.gv.egiz.pdfas.exceptions.ErrorCodeHelper;
+import at.gv.egiz.pdfas.exceptions.external.ExternalErrorException;
+import at.gv.egiz.pdfas.framework.config.SettingsHelper;
+import at.gv.egiz.pdfas.framework.vfilter.VerificationFilterParameters;
+import at.gv.egiz.pdfas.io.FileBasedDataSink;
+import at.gv.egiz.pdfas.io.FileBasedDataSource;
+import at.gv.egiz.pdfas.io.StringTextBasedDataSource;
+import at.knowcenter.wag.egov.egiz.PdfAS;
+import at.knowcenter.wag.egov.egiz.PdfASID;
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorFactoryException;
+import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException;
+import at.knowcenter.wag.egov.egiz.exceptions.PlaceholderException;
+import at.knowcenter.wag.egov.egiz.exceptions.PresentableException;
+import at.knowcenter.wag.egov.egiz.exceptions.SettingNotFoundException;
+import at.knowcenter.wag.egov.egiz.exceptions.SignatureTypesException;
+import at.knowcenter.wag.egov.egiz.framework.SignatorFactory;
+import at.knowcenter.wag.egov.egiz.pdf.TablePos;
+import at.knowcenter.wag.egov.egiz.sig.ConnectorFactory;
+import at.knowcenter.wag.egov.egiz.sig.ConnectorInformation;
+import at.knowcenter.wag.egov.egiz.sig.SignatureTypes;
+import at.knowcenter.wag.egov.egiz.web.servlets.VerifyServlet;
+
+/**
+ * The main program entry point of the commandline tool.
+ *
+ *
+ * The commandline uses the PDF-AS API.
+ *
+ *
+ * @author wprinz
+ */
+public abstract class Main
+{
+ /**
+ * Command line parameter setting the application mode sign|verify
+ */
+ protected static final String PARAMETER_MODE = "-mode";
+
+ /**
+ * Command line parameter setting the application to connect
+ */
+ protected static final String PARAMETER_CONNECTOR = "-connector";
+
+ /**
+ * Command line parameter setting the signature mode.
+ */
+ protected static final String PARAMETER_SIGNATURE_MODE = "-sigmode";
+
+ /**
+ * Command line parameter setting the signature type.
+ */
+ protected static final String PARAMETER_SIGNATURE_TYPE = "-sigtype";
+
+ /**
+ * Command line parameter setting the username
+ */
+ protected static final String PARAMETER_USER_NAME = "-username";
+
+ /**
+ * Command line parameter setting the users password
+ */
+ protected static final String PARAMETER_USER_PASSWORD = "-password";
+
+ /**
+ * Command line parameter selecting the position of the signature.
+ */
+ protected static final String PARAMETER_POS = "-pos";
+
+ /**
+ * Command line parameter selecting the signature which is going to be
+ * verified.
+ */
+ protected static final String PARAMETER_VERIFY_WHICH = "-verify_which";
+
+ /**
+ * The application mode sign
+ */
+ public static final String VALUE_MODE_SIGN = "sign";
+
+ /**
+ * The application mode verify
+ */
+ public static final String VALUE_MODE_VERIFY = "verify";
+
+ /**
+ * The application mode sign
+ */
+ public static final String VALUE_SIGNATURE_MODE_BINARY = "binary";
+
+ /**
+ * The application mode verify
+ */
+ public static final String VALUE_SIGNATURE_MODE_TEXTUAL = "textual";
+
+ /**
+ * The application mode verify
+ */
+ public static final String VALUE_SIGNATURE_MODE_DETACHED = "detached";
+
+ /**
+ * The application mode verify
+ */
+ public static final String VALUE_SIGNATURE_MODE_DETACHED_TEXT = "detachedtextual";
+
+ /**
+ * The log.
+ */
+ private static final Log logger_ = LogFactory.getLog(Main.class);
+
+ /**
+ * Main program entry point.
+ *
+ * @param args
+ * The commandline arguments.
+ * @throws IOException
+ */
+ public static void main(String[] args) throws IOException
+ {
+ // ConfigLogger.setLevel(Level.DEBUG);
+
+ SettingsReader.initializeForCommandLine();
+ PropertyConfigurator.configure(SettingsReader.CONFIG_PATH + "log4j.properties");
+
+ // printUsage(System.out);
+
+ String mode = null;
+ String signature_mode = null;
+ String connector = null;
+
+ String signature_type = null;
+ String user_name = null;
+ String user_password = null;
+ String pos_string = null;
+
+ int verify_which = -1;
+
+ String input = null;
+ String output = null;
+
+ try
+ {
+
+ // for (int i = 0; i < args.length; i++)
+ // {
+ // logger_.debug("arg[" + i + "] = " + args[i]);
+ // }
+
+ for (int i = 0; i < args.length; i++)
+ {
+ String cur_arg = args[i].trim();
+
+ if (cur_arg.equals(PARAMETER_MODE))
+ {
+ i++;
+ if (i >= args.length)
+ {
+ printNoValue(PARAMETER_MODE);
+ return;
+ }
+ mode = args[i];
+ if (!checkMode(mode))
+ {
+ printUnrecognizedValue(PARAMETER_MODE, mode);
+ return;
+ }
+ continue;
+ }
+
+ if (cur_arg.equals(PARAMETER_CONNECTOR))
+ {
+ i++;
+ if (i >= args.length)
+ {
+ printNoValue(PARAMETER_CONNECTOR);
+ return;
+ }
+ connector = args[i];
+ if (!checkConnector(connector))
+ {
+ printUnrecognizedValue(PARAMETER_CONNECTOR, connector);
+ return;
+ }
+ continue;
+ }
+
+ if (cur_arg.equals(PARAMETER_SIGNATURE_MODE))
+ {
+ i++;
+ if (i >= args.length)
+ {
+ printNoValue(PARAMETER_SIGNATURE_MODE);
+ return;
+ }
+ signature_mode = args[i];
+ if (!checkSignatureMode(signature_mode))
+ {
+ printUnrecognizedValue(PARAMETER_SIGNATURE_MODE, signature_mode);
+ return;
+ }
+ continue;
+ }
+
+ if (cur_arg.equals(PARAMETER_SIGNATURE_TYPE))
+ {
+ i++;
+ if (i >= args.length)
+ {
+ printNoValue(PARAMETER_SIGNATURE_TYPE);
+ return;
+ }
+ signature_type = args[i];
+ if (!checkSignatureType(signature_type))
+ {
+ printUnrecognizedValue(PARAMETER_SIGNATURE_TYPE, signature_type);
+ return;
+ }
+ continue;
+ }
+
+ if (cur_arg.equals(PARAMETER_USER_NAME))
+ {
+ i++;
+ if (i >= args.length)
+ {
+ printNoValue(PARAMETER_USER_NAME);
+ return;
+ }
+ user_name = args[i];
+ continue;
+ }
+
+ if (cur_arg.equals(PARAMETER_USER_PASSWORD))
+ {
+ i++;
+ if (i >= args.length)
+ {
+ printNoValue(PARAMETER_USER_PASSWORD);
+ return;
+ }
+ user_password = args[i];
+ continue;
+ }
+
+ if (cur_arg.equals(PARAMETER_POS))
+ {
+ i++;
+ if (i >= args.length)
+ {
+ printNoValue(PARAMETER_POS);
+ return;
+ }
+ pos_string = args[i];
+ continue;
+ }
+
+ if (cur_arg.equals(PARAMETER_VERIFY_WHICH))
+ {
+ i++;
+ if (i >= args.length)
+ {
+ printNoValue(PARAMETER_VERIFY_WHICH);
+ return;
+ }
+ String str_verify_which = args[i];
+ try
+ {
+ verify_which = Integer.parseInt(str_verify_which);
+ }
+ catch (NumberFormatException e)
+ {
+ printUnrecognizedValue(PARAMETER_VERIFY_WHICH, str_verify_which);
+ return;
+ }
+
+ continue;
+ }
+
+ if (cur_arg.charAt(0) == '-')
+ {
+ printUnrecognizedOption(cur_arg);
+ return;
+ }
+
+ if (input == null)
+ {
+ input = cur_arg;
+ continue;
+ }
+
+ if (output == null)
+ {
+ output = cur_arg;
+ continue;
+ }
+
+ printUnrecognizedAdditionalCommandlineArgument(cur_arg);
+ return;
+ }
+
+ if (mode == null)
+ {
+ printMissingParameter("a mode", PARAMETER_MODE);
+ return;
+ }
+ if (connector == null)
+ {
+ printMissingParameter("a connector", PARAMETER_CONNECTOR);
+ return;
+ }
+ if (mode.equals(VALUE_MODE_SIGN))
+ {
+ if (signature_mode == null)
+ {
+ printMissingParameter("a signature mode", PARAMETER_SIGNATURE_MODE);
+ return;
+ }
+ if (signature_type == null)
+ {
+ SettingsReader settings = SettingsReader.getInstance();
+ String default_type = settings.getValueFromKey(SignatureTypes.DEFAULT_TYPE);
+ signature_type = default_type;
+ }
+ if (user_name == null)
+ {
+ user_name = "";
+ // printMissingParameter("a user name", PARAMETER_USER_NAME);
+ // return;
+ }
+ if (user_password == null)
+ {
+ user_password = "";
+ // printMissingParameter("a user password", PARAMETER_USER_PASSWORD);
+ // return;
+ }
+ }
+
+ if (input == null)
+ {
+ printMissing("an input document");
+ return;
+ }
+
+ File file = new File(input);
+ if (!file.exists())
+ {
+ System.err.println("The input file '" + input + "' doesn't exist.");
+ return;
+ }
+
+ if (mode.equals(VALUE_MODE_SIGN) && output == null)
+ {
+ output = generateOutputFileNameFromInput(input, signature_mode);
+ }
+
+ carryOutCommand(mode, signature_mode, connector, signature_type, user_name, user_password, verify_which, input, output, pos_string);
+
+ }
+ catch (PdfAsException e)
+ {
+ printPresentableException(e);
+
+ if (output != null)
+ {
+ logger_.debug("Deleting output file on error.");
+ File oFile = new File(output);
+ boolean deleted = oFile.delete();
+ if (!deleted)
+ {
+ logger_.error("Couldn't delete output file " + output);
+ }
+ }
+ }
+ finally
+ {
+ SettingsReader.clearTemporaryDirectory();
+ }
+ }
+
+ protected static void carryOutCommand(final String mode, final String signature_mode, final String connector, final String signature_type, final String user_name, final String user_password,
+ final int verify_which, final String input, String output, final String pos_string) throws PdfAsException
+ {
+ // File file = new File(input);
+ //
+ // byte[] input_bytes = null;
+ // try
+ // {
+ // FileInputStream fis = new FileInputStream(file);
+ // input_bytes = new byte[(int) file.length()];
+ // fis.read(input_bytes);
+ // fis.close();
+ // }
+ // catch (IOException e)
+ // {
+ // throw new PDFDocumentException(201);
+ // }
+
+ PrintWriter messageOutput = new PrintWriter(System.out);
+
+ if (mode.equals(VALUE_MODE_SIGN))
+ {
+ carryOutSign(input, connector, signature_mode, signature_type, pos_string, user_name, user_password, output, messageOutput);
+ }
+ else
+ {
+ carryOutVerify(input, connector, verify_which, messageOutput);
+ }
+ messageOutput.flush();
+ }
+
+ public static void carryOutSign(String input, String connector, String signature_mode, String signature_type, String pos_string, String user_name, String user_password, String output,
+ PrintWriter messageOutput) throws PdfAsException
+ {
+ messageOutput.println("Signing...");
+
+ // for performance measurement
+ long startTime = 0;
+ long fileSize = 0;
+ if (logger_.isInfoEnabled())
+ {
+ startTime = System.currentTimeMillis();
+ }
+
+ DataSource dataSource = null;
+ try
+ {
+ File file = new File(input);
+ dataSource = new FileBasedDataSource(file, "application/pdf");
+ if (logger_.isDebugEnabled())
+ {
+ fileSize = file.length();
+ }
+ }
+ catch (IOException e)
+ {
+ throw new PDFDocumentException(201, e);
+ }
+
+ DataSink dataSink = null;
+ try
+ {
+ File outputFile = new File(output);
+
+ dataSink = new FileBasedDataSink(outputFile);
+ }
+ catch (IOException e)
+ {
+ throw new PDFDocumentException(ErrorCode.CANNOT_WRITE_PDF, e);
+ }
+
+ processSign(dataSource, connector, signature_mode, signature_type, pos_string, dataSink);
+
+ // for performance measurement
+ if (logger_.isInfoEnabled())
+ {
+ long endTime = System.currentTimeMillis();
+ String toReport = "SIGN;" + signature_mode + ";" + input + ";" + fileSize + ";" + (endTime - startTime);
+ logger_.info(toReport);
+ }
+
+ messageOutput.println("Signing was successful.");
+ }
+
+ public static void carryOutVerify(String input, String connector, int verify_which, PrintWriter messageOutput) throws PdfAsException
+ {
+ messageOutput.println("Verifying...");
+
+ // for performance measurement
+ long startTime = 0;
+ long fileSize = 0;
+ if (logger_.isInfoEnabled())
+ {
+ startTime = System.currentTimeMillis();
+ }
+
+ DataSource dataSource = null;
+ try
+ {
+ File file = new File(input);
+ if (logger_.isDebugEnabled())
+ {
+ fileSize = file.length();
+ }
+ String extension = VerifyServlet.extractExtension(input);
+ if (extension != null && extension.equals("txt"))
+ {
+ try
+ {
+ FileInputStream fis = new FileInputStream(file);
+ byte[] input_bytes = new byte[(int) file.length()];
+ fis.read(input_bytes);
+ fis.close();
+
+ String text = new String(input_bytes, "UTF-8");
+ dataSource = new StringTextBasedDataSource(text);
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ throw new RuntimeException("Very strange: UTF-8 character encoding not supported.", e);
+ }
+ }
+ else
+ {
+ dataSource = new FileBasedDataSource(file, "application/pdf");
+ }
+ }
+ catch (IOException e)
+ {
+ throw new PDFDocumentException(ErrorCode.DOCUMENT_CANNOT_BE_READ, e);
+ }
+
+ VerifyResults results = processVerify(dataSource, connector, verify_which);
+
+ messageOutput.println("Verification results:");
+ formatVerifyResults(results, messageOutput);
+
+ // for performance measurement
+ if (logger_.isInfoEnabled())
+ {
+ long endTime = System.currentTimeMillis();
+ String toReport = "VERIFY;" + input + ";" + fileSize + ";" + (endTime - startTime) + ";" + debugVerifyResults(results);
+ logger_.info(toReport);
+ }
+
+ }
+
+ public static void processSign(DataSource dataSource, String connector, String signature_mode, String signature_type, String pos_string, DataSink dataSink) throws PdfAsException
+ {
+ // FIXME implement this
+ // TODO this will change soon due to the document-cleaning change request.
+ //PdfAS.applyStrictMode(pdfDataSource);
+
+ TablePos pos = null;
+ if (pos_string != null)
+ {
+ try
+ {
+ pos = PdfAS.parsePositionFromPosString(pos_string);
+ }
+ catch (PDFDocumentException e)
+ {
+ printUnrecognizedValue(PARAMETER_POS, pos_string);
+ return;
+
+ }
+ }
+ SignaturePositioning posi = null;
+ if (pos != null)
+ {
+ posi = new SignaturePositioning();
+ if (!pos.isXauto())
+ {
+ posi.setXAlgorithm(new AbsoluteAxisAlgorithm(pos.getPosX()));
+ }
+ if (!pos.isYauto())
+ {
+ posi.setYAlgorithm(new AbsoluteAxisAlgorithm(pos.getPosY()));
+ }
+ if (!pos.isWauto())
+ {
+ posi.setWidthAlgorithm(new AbsoluteAxisAlgorithm(pos.getWidth()));
+ }
+ if (pos.isNewPage())
+ {
+ posi.setPageAlgorithm(new NewPageAlgorithm());
+ }
+ if (!pos.isPauto())
+ {
+ posi.setPageAlgorithm(new AbsolutePageAlgorithm(pos.getPage()));
+ }
+ posi.setFooterLine(pos.getFooterLine());
+ }
+
+ PdfAs pdfAs = PdfAsFactory.createPdfAs(new File(SettingsReader.RESOURCES_PATH));
+
+ SignParameters sp = new SignParameters();
+ sp.setDocument(dataSource);
+ sp.setOutput(dataSink);
+ sp.setSignatureType(signature_mode); // TODO detached signaturen!
+ sp.setSignatureDevice(connector);
+ sp.setSignatureProfileId(signature_type);
+ sp.setSignaturePositioning(posi);
+ pdfAs.sign(sp);
+
+ }
+
+ public static VerifyResults processVerify(DataSource dataSource, String connector, int verify_which) throws PdfAsException
+ {
+ String verifyMode = Constants.VERIFY_MODE_FULL_CONSERVATIVE;
+ VerificationFilterParameters parameters = SettingsHelper.readVerificationFilterParametersFromSettings();
+ if (parameters.extractBinarySignaturesOnly())
+ {
+ verifyMode = Constants.VERIFY_MODE_BINARY_ONLY;
+ }
+ else
+ {
+ if (parameters.assumeOnlySignatureUpdateBlocks())
+ {
+ verifyMode = Constants.VERIFY_MODE_SEMI_CONSERVATIVE;
+ }
+ else
+ {
+ verifyMode = Constants.VERIFY_MODE_FULL_CONSERVATIVE;
+ }
+ }
+
+ PdfAs pdfAs = PdfAsFactory.createPdfAs(new File(SettingsReader.RESOURCES_PATH));
+
+ VerifyParameters vp = new VerifyParameters();
+ vp.setDocument(dataSource);
+ vp.setVerifyMode(verifyMode);
+ vp.setSignatureDevice(connector);
+ vp.setReturnHashInputData(false);
+ vp.setVerificationTime(null);
+ vp.setSignatureToVerify(verify_which);
+ VerifyResults vrs = pdfAs.verify(vp);
+
+ return vrs;
+ }
+
+ protected static String generateOutputFileNameFromInput(String input, String sig_mode)
+ {
+ String output = input + "_out";
+ if (sig_mode.startsWith("detached"))
+ {
+ output += ".xml";
+ }
+ else
+ {
+ output += ".pdf";
+ }
+
+ return output;
+ }
+
+ /**
+ * Prints that the provided option was unrecognized.
+ *
+ * @param option
+ * The unrecognized option.
+ * @throws PresentableException
+ * Forwarded exception.
+ */
+ protected static void printUnrecognizedOption(final String option) throws PresentableException
+ {
+ System.err.println("Unrecognized option '" + option + "'.");
+ printUsage(System.out);
+ }
+
+ /**
+ * Prints that the provided value was unrecognized.
+ *
+ * @param parameter
+ * The parameter, which is missing a value.
+ * @throws PresentableException
+ * Forwarded exception.
+ */
+ protected static void printNoValue(final String parameter) throws PresentableException
+ {
+ System.err.println("The parameter " + parameter + " requires a value as next argument.");
+ printUsage(System.out);
+ }
+
+ /**
+ * Prints that the provided value was unrecognized.
+ *
+ * @param value
+ * The unrecognized value.
+ * @throws PresentableException
+ * Forwarded exception.
+ */
+ protected static void printUnrecognizedValue(final String parameter, final String value) throws PresentableException
+ {
+ System.err.println("The parameter " + parameter + " doesn't recognize the provided value '" + value + "'.");
+ printUsage(System.out);
+ }
+
+ /**
+ * Prints that the provided additional commandline argument was unrecognized.
+ *
+ * @param argument
+ * The unrecognized argument.
+ * @throws PresentableException
+ * Forwarded exception.
+ */
+ protected static void printUnrecognizedAdditionalCommandlineArgument(final String argument) throws PresentableException
+ {
+ System.err.println("Unrecognized additional commandline argument '" + argument + "'.");
+ printUsage(System.out);
+ }
+
+ /**
+ * Prints that a certain parameter was missing.
+ *
+ * @param missing_term
+ * A description of the missing parameter ("e.g. a mode").
+ * @param parameter
+ * The missing parameter itself (e.g. "-mode").
+ * @throws PresentableException
+ * Forwarded exception.
+ */
+ protected static void printMissingParameter(final String missing_term, final String parameter) throws PresentableException
+ {
+ printMissing(missing_term + " ('" + parameter + "' parameter)");
+ }
+
+ /**
+ * Prints that something is missing.
+ *
+ * @param missing_term
+ * A descriptive message of the missing thing.
+ * @throws PresentableException
+ * Forwarded exception.
+ */
+ protected static void printMissing(final String missing_term) throws PresentableException
+ {
+ System.err.println("Please specify " + missing_term + ".");
+ printUsage(System.out);
+ }
+
+ /**
+ * Prints out the ErrorCodeException in a descriptive form.
+ *
+ * @param ece
+ * The ErrorCodeException to be printed.
+ */
+ protected static void printPresentableException(final PdfAsException e)
+ {
+ if (e.getErrorCode() == ErrorCode.PLACEHOLDER_EXCEPTION)
+ {
+ PlaceholderException phe = null;
+ if (e instanceof PlaceholderException)
+ {
+ phe = (PlaceholderException) e;
+ }
+ else
+ {
+ phe = (PlaceholderException) e.getCause();
+ }
+
+ System.err.println("Der Platzhalter des Feldes " + phe.getField() + " ist um " + phe.getMissing() + " Bytes zu kurz. ");
+ }
+
+ System.err.println("Fehler " + e.getErrorCode() + ": " + ErrorCodeHelper.getMessageForErrorCode(e.getErrorCode()));
+
+ if (e instanceof ExternalErrorException)
+ {
+ ExternalErrorException eee = (ExternalErrorException) e;
+ System.err.println("Externer Fehlergrund: " + eee.getExternalErrorCode() + ": " + eee.getExternalErrorMessage());
+ }
+
+ logger_.error(e);
+ }
+
+ /**
+ * Prints the usage text.
+ *
+ * @param writer
+ * The writer to print the text to.
+ * @throws PresentableException
+ * Forwarded exception.
+ */
+ public static void printUsage(PrintStream writer) throws PresentableException
+ {
+ writer.println("Usage: pdf-as [OPTIONS] [output file]");
+ writer.println(" Required OPTIONS:");
+
+ writer.println(" " + PARAMETER_MODE + " <" + VALUE_MODE_SIGN + "|" + VALUE_MODE_VERIFY + ">");
+ writer.println(" " + VALUE_MODE_SIGN + " ... signs a document");
+ writer.println(" " + VALUE_MODE_VERIFY + " ... verifies a document");
+
+ writer.print(" " + PARAMETER_CONNECTOR + " ");
+ ConnectorInformation[] ci = ConnectorFactory.getConnectorInformationArray();
+ for (int i = 0; i < ci.length; i++)
+ {
+ String id = ci[i].getIdentifier();
+ if (!ConnectorFactory.isAvailableForCommandline(id))
+ {
+ continue;
+ }
+ writer.print(id);
+ if (i < ci.length - 1)
+ {
+ writer.print("|");
+ }
+ }
+ writer.println();
+ for (int i = 0; i < ci.length; i++)
+ {
+ String id = ci[i].getIdentifier();
+ if (!ConnectorFactory.isAvailableForCommandline(id))
+ {
+ continue;
+ }
+ writer.println(" " + id + " ... " + ci[i].getDescription());
+ }
+
+ writer.println(" OPTIONS for signation:");
+
+ writer.println(" " + PARAMETER_SIGNATURE_MODE + " <" + VALUE_SIGNATURE_MODE_BINARY + "|" + VALUE_SIGNATURE_MODE_TEXTUAL + ">");
+ writer.println(" " + VALUE_SIGNATURE_MODE_BINARY + " ... signs the complete binary document");
+ writer.println(" " + VALUE_SIGNATURE_MODE_TEXTUAL + " ... signs only the textual portion of the document");
+ // @iaik: why is this commented out?
+ //writer.println(" " + VALUE_SIGNATURE_MODE_DETACHED + " ... signs the document using the binary mode and returns the xml signature of it.");
+ writer.println(" " + VALUE_SIGNATURE_MODE_DETACHED_TEXT + " ... signs the document using the textual mode and returns the xml signature of it.");
+
+ writer.print(" " + PARAMETER_SIGNATURE_TYPE + " <");
+ SignatureTypes sig_types = SignatureTypes.getInstance();
+ SettingsReader settings = SettingsReader.getInstance();
+ List types_array = sig_types.getSignatureTypes();
+ Iterator it = types_array.iterator();
+ while (it.hasNext())
+ {
+ String type = (String) it.next();
+ writer.print(type);
+ if (it.hasNext())
+ {
+ writer.print("|");
+ }
+ }
+ writer.println(">");
+ writer.println(" ... [optional] the profile to be used. If omitted, the default");
+ writer.println(" profile is used.");
+ String default_type = settings.getValueFromKey(SignatureTypes.DEFAULT_TYPE);
+ it = types_array.iterator();
+ while (it.hasNext())
+ {
+ String type = (String) it.next();
+ String descr_key = SignatureTypes.SIG_OBJ + type + "." + SignatureTypes.SIG_DESCR;
+ String type_descr = settings.getValueFromKey(descr_key);
+
+ writer.println(" " + type + " ... " + (type.equals(default_type) ? "(default) " : "") + type_descr);
+ }
+
+ writer.println(" " + PARAMETER_USER_NAME + " ... [optional] the user name");
+ writer.println(" " + PARAMETER_USER_PASSWORD + " ... [optional] the user password");
+
+ writer.println(" " + PARAMETER_POS + " ... [optional] the position of the signature block");
+ writer.println(" position has the format [x:x_algo];[y:y_algo];[w:w_algo][p:p_algo];[f:f_algo]");
+ writer.println(" if not present default is set to x:auto;y:auto;w:auto;p:auto;f:0");
+ writer.println(" x_algo:='auto' ... automatic positioning x");
+ writer.println(" floatvalue ... absolute x must be >= 0");
+ writer.println(" y_algo:='auto' ... automatic positioning y");
+ writer.println(" floatvalue ... absolute y must be >= 0");
+ writer.println(" w_algo:='auto' ... automatic width");
+ writer.println(" floatvalue ... absolute width must be > 0");
+ writer.println(" p_algo:='auto' ... automatic last page");
+ writer.println(" 'new' ... new page");
+ writer.println(" intvalue ... pagenumber must be > 0 if p>number of pages in document p-->handled like p:'new'");
+ writer.println(" f_algo floatvalue ... consider footerline must be >= 0 (only if y_algo is auto and p_algo is not 'new')");
+
+ writer.println(" OPTIONS for verification:");
+ writer.println(" " + PARAMETER_VERIFY_WHICH + " ... [optional] zero based number of the signature");
+ writer.println(" to be verified. If omitted, all signatures are verified.");
+
+ writer.println(" Example usage:");
+ writer.println(" pdf-as " + PARAMETER_MODE + " " + VALUE_MODE_SIGN + " " + PARAMETER_CONNECTOR + " moa some_document.pdf");
+ writer.println(" pdf-as " + PARAMETER_MODE + " " + VALUE_MODE_VERIFY + " some_document.pdf_out.pdf");
+ }
+
+ /**
+ * Checks the value for correctness.
+ *
+ * @param mode
+ * The parameter's value.
+ * @return Returns true, if the value is correct, false otherwise.
+ */
+ protected static boolean checkMode(String mode)
+ {
+ return mode.equals(VALUE_MODE_SIGN) || mode.equals(VALUE_MODE_VERIFY);
+ }
+
+ /**
+ * Checks the value for correctness.
+ *
+ * @param signature_mode
+ * The parameter's value.
+ * @return Returns true, if the value is correct, false otherwise.
+ */
+ protected static boolean checkSignatureMode(String signature_mode)
+ {
+ return signature_mode.equals(VALUE_SIGNATURE_MODE_BINARY) || signature_mode.equals(VALUE_SIGNATURE_MODE_TEXTUAL)
+ //|| signature_mode.equals(VALUE_SIGNATURE_MODE_DETACHED)
+ || signature_mode.equals(VALUE_SIGNATURE_MODE_DETACHED_TEXT);
+ }
+
+ /**
+ * Checks the value for correctness.
+ *
+ * @param connector
+ * The parameter's value.
+ * @return Returns true, if the value is correct, false otherwise.
+ * @throws ConnectorFactoryException
+ * F.e.
+ */
+ protected static boolean checkConnector(String connector) throws ConnectorFactoryException
+ {
+ return ConnectorFactory.isValidConnectorIdentifier(connector) && ConnectorFactory.isAvailableForCommandline(connector);
+ }
+
+ /**
+ * Checks the value for correctness.
+ *
+ * @param signature_type
+ * The parameter's value.
+ * @return Returns true, if the value is correct, false otherwise.
+ */
+ protected static boolean checkSignatureType(String signature_type) throws SignatureTypesException
+ {
+ SignatureTypes sig_types = SignatureTypes.getInstance();
+ List types_array = sig_types.getSignatureTypes();
+ Iterator it = types_array.iterator();
+ while (it.hasNext())
+ {
+ String type = (String) it.next();
+ if (type.equals(signature_type))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Translates the commandline argument to a PDF-AS-ID.
+ *
+ * @param signature_mode
+ * The signator mode commandline argument.
+ * @return Returns the corresponding PDFASID.
+ */
+ protected static PdfASID translateSignatureModeToPdfASID(String signature_mode)
+ {
+ if (signature_mode.equals(VALUE_SIGNATURE_MODE_BINARY))
+ {
+ return SignatorFactory.MOST_RECENT_BINARY_SIGNATOR_ID;
+ }
+ if (signature_mode.equals(VALUE_SIGNATURE_MODE_TEXTUAL))
+ {
+ return SignatorFactory.MOST_RECENT_TEXTUAL_SIGNATOR_ID;
+ }
+ if (signature_mode.equals(VALUE_SIGNATURE_MODE_DETACHED))
+ {
+ return SignatorFactory.MOST_RECENT_DETACHED_SIGNATOR_ID;
+ }
+ if (signature_mode.equals(VALUE_SIGNATURE_MODE_DETACHED_TEXT))
+ {
+ return SignatorFactory.MOST_RECENT_DETACHEDTEXT_SIGNATOR_ID;
+ }
+ return null;
+ }
+
+ /**
+ * Formats the verification results.
+ *
+ * @param results
+ * The List of SignatureResponse verification results.
+ * @param writer
+ * The output sink to write the formatted text to.
+ * @throws SettingNotFoundException
+ * Forwarded exception.
+ */
+ protected static void formatVerifyResults(VerifyResults results, PrintWriter writer) throws SettingNotFoundException
+ {
+ Iterator it = results.getResults().iterator();
+ while (it.hasNext())
+ {
+ VerifyResult result = (VerifyResult) it.next();
+ formatVerifyResult(result, writer);
+
+ if (it.hasNext())
+ {
+ writer.println();
+ }
+ }
+ }
+
+ /**
+ * Formats the verification results for debugging. Returns 0 if no error
+ * occurs or the sum of all error-codes.
+ *
+ * @param results
+ *
+ * @param writer
+ * The output sink to write the formatted text to.
+ * @throws SettingNotFoundException
+ * Forwarded exception.
+ */
+ protected static int debugVerifyResults(VerifyResults results) throws SettingNotFoundException
+ {
+ int toreturn = 0;
+ Iterator it = results.getResults().iterator();
+ while (it.hasNext())
+ {
+ VerifyResult result = (VerifyResult) it.next();
+
+ toreturn += result.getValueCheckCode().getCode();
+ }
+ return toreturn;
+ }
+
+ public static void formatVerifyResult(VerifyResult result, PrintWriter writer) throws SettingNotFoundException
+ {
+
+ writer.println(" Zertifikat:");
+ writer.println(" Signator: " + result.getSignerCertificate().getSubjectDN().getName());
+ writer.println(" Aussteller: " + result.getSignerCertificate().getIssuerDN().getName());
+ writer.println(" Seriennummer: " + result.getSignerCertificate().getSerialNumber());
+ List public_properties = result.getPublicProperties();
+ Iterator it = public_properties.iterator();
+ while (it.hasNext())
+ {
+ String public_property = (String) it.next();
+ writer.println(" Eigenschaft: " + public_property);
+ }
+
+ writer.println(" Zertifikat-Check:");
+ writer.println(" " + result.getCertificateCheck().getCode() + " - " + result.getCertificateCheck().getMessage());
+ writer.println(" Signatur-Check:");
+ writer.println(" " + result.getValueCheckCode().getCode() + " - " + result.getValueCheckCode().getMessage());
+ writer.println(" Manifest-Check:");
+ writer.println(" " + result.getManifestCheckCode().getCode() + " - " + result.getManifestCheckCode().getMessage());
+ }
+
+}
diff --git a/src/main/java/at/gv/egiz/pdfas/framework/ConnectorFactory.java b/src/main/java/at/gv/egiz/pdfas/framework/ConnectorFactory.java
index b42c8ed..99d692e 100644
--- a/src/main/java/at/gv/egiz/pdfas/framework/ConnectorFactory.java
+++ b/src/main/java/at/gv/egiz/pdfas/framework/ConnectorFactory.java
@@ -33,34 +33,34 @@ public class ConnectorFactory
- public static Connector createConnector (String connectorId, String profile, String locRef) throws ConnectorFactoryException, ConnectorException
+ public static Connector createConnector (String connectorId, ConnectorParameters connectorParameters) throws ConnectorFactoryException, ConnectorException
{
if (connectorId.equals(DETACHED_MULTIPART_BKU_CONNECTOR))
{
- return new MultipartDetachedBKUConnector(profile);
+ return new MultipartDetachedBKUConnector(connectorParameters);
}
if (connectorId.equals(ENVELOPING_BASE64_BKU_CONNECTOR))
{
- return new EnvelopedBase64BKUConnector(profile);
+ return new EnvelopedBase64BKUConnector(connectorParameters.getProfileId());
}
if (connectorId.equals(OLD_ENVELOPING_BASE64_BKU_CONNECTOR))
{
- return new OldEnvelopingBase64BKUConnector(profile);
+ return new OldEnvelopingBase64BKUConnector(connectorParameters.getProfileId());
}
if (connectorId.equals(DETACHED_LOCREF_MOA_CONNECTOR))
{
// TODO Hier wird der neue Connector verwendet
// return new DetachedLocRefMOAConnector(profile, locRef);
- return new MOASoapWithAttachmentConnector(profile);
+ return new MOASoapWithAttachmentConnector(connectorParameters);
}
if (connectorId.equals(ENVELOPING_BASE64_MOA_CONNECTOR))
{
// TODO Hier wird NICHT der neue Connector verwendet
- return new EnvelopingBase64MOAConnector(profile);
+ return new EnvelopingBase64MOAConnector(connectorParameters.getProfileId());
// return new MOASoapWithAttachmentConnector(profile);
}
diff --git a/src/main/java/at/gv/egiz/pdfas/framework/ConnectorParameters.java b/src/main/java/at/gv/egiz/pdfas/framework/ConnectorParameters.java
new file mode 100644
index 0000000..618624d
--- /dev/null
+++ b/src/main/java/at/gv/egiz/pdfas/framework/ConnectorParameters.java
@@ -0,0 +1,85 @@
+/**
+ *
+ */
+package at.gv.egiz.pdfas.framework;
+
+import java.util.Date;
+
+/**
+ * Parameters passed to the constructor of the Connector.
+ *
+ *
+ * Each Connector must have a constructor accepting this parameter class as an
+ * argument.
+ *
+ *
+ * @author wprinz
+ */
+public class ConnectorParameters
+{
+ /**
+ * The profile Id to get the connector parameters from.
+ *
+ *
+ * The there are no explicit parameters for the connector in the profile, the
+ * default parameters are used.
+ *
+ */
+ protected String profileId = null;
+
+ /**
+ * Tells, if the connector should ask the device to return the hash input
+ * data.
+ *
+ *
+ * Note that not all connectors support to return the hash input data - so
+ * there is no guarantee that the hash value will actually be returned.
+ *
+ */
+ protected boolean returnHashInputData = false;
+
+ /**
+ * Allows to specify an explicit time of verification.
+ *
+ *
+ * If null, the device's default behaviour determines the time of
+ * verification, which is usually the current time.
+ *
+ *
+ * The time of verification usually influences the certificate check. E.g. the
+ * certificate may not be valid at the time of verification.
+ *