From db52e4d66d60184d53a27ba4d6772461daacc03d Mon Sep 17 00:00:00 2001
From: tknall
* This usually contains sub directories for the templates, the configuration
* files, etc.
*
* Subsequent calls to getInstance will return the new settings.
* Note: IAIK JCE and IAIK ECC security providers are automatically registered.
*
* Subsequent calls to getInstance will return the new settings.
*
* If the directory doesn't exist, it is created.
*
* This should be used to clear temporary files when the application shuts
* down.
@@ -784,19 +791,19 @@ public class SettingsReader implements Serializable
{
TempDirHelper.clearTemporaryDirectory();
}
-
+
public static synchronized void initialize(String configdir, String tmpdir) {
-
+
String defaultConfigDeployedTo = null;
// resolve work directory
// configuration explicitely given ?
if (configdir == null) {
-
+
// configuration via system property ?
logger_.debug("No configuration directory given. Looking for system property \"" + Constants.CONFIG_DIR_SYSTEM_PROPERTY + "\".");
configdir = System.getProperty(Constants.CONFIG_DIR_SYSTEM_PROPERTY);
if (configdir == null) {
-
+
// configuration via user's home directory ?
logger_.debug("System property not set. Trying to locate configuration within the user's home directory.");
String userHome = System.getProperty("user.home");
@@ -808,7 +815,7 @@ public class SettingsReader implements Serializable
defaultConfigDeployedTo = ConfigUtils.deployDefaultConfiguration(configdir, false);
} catch (ConfigUtilsException e) {
throw new RuntimeException(e);
- }
+ }
if (defaultConfigDeployedTo != null) {
logger_.info("** Default configuration successfully deployed to \"" + defaultConfigDeployedTo + "\" **");
} else {
@@ -833,7 +840,7 @@ public class SettingsReader implements Serializable
{
throw new IllegalArgumentException("The config directory \"" + configdir + "\" does not exist or is not a directory.");
}
-
+
// resolve temporary dir
if (tmpdir == null) {
logger_.debug("Temporary directory not explicitely set. Looking for user's temp directory.");
@@ -851,14 +858,14 @@ public class SettingsReader implements Serializable
} catch (IOException e) {
tmpdir = ConfigUtils.assertFileSeparator(tmpdirFile.getPath());
}
-
+
RESOURCES_PATH = configdir;
TMP_PATH = tmpdir;
CONFIG_PATH = RESOURCES_PATH + CFG + FILE_SEP;
CERT_PATH = RESOURCES_PATH + CERT + FILE_SEP;
// ConfigUtils.printConfigInfo(logger_);
-
+
if (defaultConfigDeployedTo != null) {
logger_.debug("** Default configuration successfully deployed to \"" + defaultConfigDeployedTo + "\" **");
}
@@ -870,10 +877,10 @@ public class SettingsReader implements Serializable
{
initialize(base_dir, null);
}
-
+
/**
* Initializes the paths of the SettingsReader for web application usage.
- *
+ *
* @param base_dir
* The base directory of this web application. E.g.
* TOMCAT_HOME/webapps/pdf-as
@@ -890,14 +897,14 @@ public class SettingsReader implements Serializable
{
initialize(null);
}
-
+
static {
-
+
String versionString = "* PDF-AS library version " + PdfAS.PDFAS_VERSION + " *";
String paddingString = StringUtils.repeat("*", versionString.length());
logger_.info("PDF-AS info\n" + paddingString + "\n" + versionString + "\n" + paddingString);
}
-
+
public Properties getProperties() {
return this.properties_;
}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/commandline/Main.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/commandline/Main.java
index 1b66f53..0468160 100644
--- a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/commandline/Main.java
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/commandline/Main.java
@@ -73,7 +73,7 @@ import at.knowcenter.wag.egov.egiz.sig.SignatureTypes;
/**
* The main program entry point of the commandline tool.
- *
+ *
* @author wprinz
*/
public abstract class Main
@@ -156,18 +156,18 @@ public abstract class Main
/**
* Main program entry point.
- *
+ *
* @param args
* The commandline arguments.
* @throws IOException
- *
+ *
* @deprecated use {@link at.gv.egiz.pdfas.commandline.Main} instead
*/
public static void main(String[] args) throws IOException {
System.out.println("\nWarning: The entry point at.knowcenter.wag.egov.egiz.commandline.Main is deprecated. Use at.gv.egiz.pdfas.commandline.Main instead.\n");
at.gv.egiz.pdfas.commandline.Main.main(args);
}
-
+
/*
public static void main(String[] args) throws IOException
{
@@ -413,7 +413,7 @@ public abstract class Main
catch (PresentableException e)
{
printPresentableException(e);
-
+
if (output != null)
{
logger_.debug("Deleting output file on error.");
@@ -451,10 +451,10 @@ public abstract class Main
// }
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
@@ -468,22 +468,12 @@ public abstract class Main
PrintWriter messageOutput) throws PresentableException
{
messageOutput.println("Signing...");
-
- // for performance measurement
- long startTime = 0;
- long fileSize = 0;
- if (logger_.isInfoEnabled()) {
- startTime = System.currentTimeMillis();
- }
PdfDataSource pdfDataSource;
try
{
File file = new File(input);
pdfDataSource = new FileBasedPdfDataSourceImpl(file, (int)file.length());
- if (logger_.isDebugEnabled())
- fileSize = file.length();
-
}
catch (IOException e)
{
@@ -495,7 +485,7 @@ public abstract class Main
try
{
outputFile = new File(output);
-
+
dataSink = new FileBasedDataSink(outputFile);
}
catch (IOException e)
@@ -523,39 +513,23 @@ public abstract class Main
}
}
- // 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 PresentableException
{
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 = extractExtension(input);
if (extension != null && extension.equals("txt"))
{
try
{
- FileInputStream fis = new FileInputStream(file);
+ FileInputStream fis = new FileInputStream(file);
byte[] input_bytes = new byte[(int) file.length()];
fis.read(input_bytes);
fis.close();
@@ -582,24 +556,16 @@ public abstract class Main
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);
- }
-
-
+
}
/**
* Extracts the extension from a file name string.
- *
+ *
*
* The extension of a file name is whatever text follows the last '.'.
*
* In prepareSign, an Incremental Update is created that contains the Signature
* block and the egiz dictionary. For formatting the layout, variable values are
@@ -72,9 +72,9 @@ import com.lowagie.text.pdf.PdfPTable;
* In finishSign, the variable fields (values, /Cert) are replaced with the
* values according to the encoding.
*
* It doesn't modify the original document, but simply returns the XML signature
* response as the signed document.
*
* In prepareSign, the document text is extracted and normalized.
*
+ * In order to include further Properties use the following instruction:
+ *
+ * include = [path/to/]foo.properties
+ *
+ * Note that wildcard imports are allowed, e.g.
+ *
+ * include = [path/to/]profile.*.properties
+ *
+ * In order to use more than one include instruction within a file append an arbitary postfix to include.
+ * in order to make each include key unique within a properties file, e.g.
+ *
+ * include = profile.SIGNATURBLOCK*.properties
+ * include.amtssignaturen = profile.AMTSSIGNATURBLOCK*.properties
+ * include.1 = myProfiles1/*.properties
+ * include.2 = myProfiles2/*.properties
+ *
+ * Note that
+ *
+ *
+ *
+ * Mind creating circular includes!
+ *
+ * @author Datentechnik Innovation GmbH
+ */
+public class NestedProperties extends Properties {
+
+ private static final long serialVersionUID = 1L;
+
+ private Log log = LogFactory.getLog(getClass());
+
+ /**
+ * Creates an empty property list with no default values.
+ */
+ public NestedProperties() {
+ super();
+ }
+
+ /**
+ * Creates an empty property list with the specified defaults.
+ * @param defaults The defaults.
+ */
+ public NestedProperties(Properties defaults) {
+ super(defaults);
+ }
+
+ /**
+ * The name of the key that triggers including of other properties.
+ */
+ private final String INCLUDE_KEY_NAME = "include";
+
+ /**
+ * Defines the default behaviour of the file matching filter.
+ */
+ private final IOCase DEFAULT_IOCASE = IOCase.SENSITIVE;
+
+ /**
+ * The maximum depth of includes before being regarded as circular (throwing a {@link CircularIncludeException}).
+ */
+ private final int MAX_NESTED_INCLUDE_DEPTH = 25;
+
+ @Override
+ /**
+ * Warning: When Properties are loaded using InputStreams include instructions are not supported.
+ */
+ public synchronized void load(InputStream inStream) throws IOException {
+ log.debug("Loading properties from input stream. Include instructions are not supported.");
+ super.load(inStream);
+ }
+
+ @Override
+ public synchronized void loadFromXML(InputStream in) throws IOException, InvalidPropertiesFormatException {
+ // Loading from InputStream is not supported since including further property files that have been declared
+ // using relative paths need a context directory which cannot be retrieved from InputStreams.
+ throw new UnsupportedOperationException("Imports from XML files are not supported.");
+ }
+
+ /**
+ * Reads a property list from a certain file including other properties files if include instructions are present.
+ * Note that include instructions that do not match any files do not result in an exception. A respective message at
+ * WARN level is logged.
+ *
+ * @param file
+ * The file to be read.
+ * @throws IOException
+ * Thrown in case of an I/O error.
+ * @throws CircularIncludeException
+ * Thrown if circular includes have been detected (@link {@link RuntimeException}).
+ */
+ public synchronized void load(File file) throws IOException, CircularIncludeException {
+ load(file, 0);
+ }
+
+ /**
+ * Reads a property list from a certain file including other properties files if include instructions are present.
+ * Note that include instructions that do not match any files do not result in an exception. A respective message at
+ * WARN level is logged.
+ *
+ * @param file
+ * The file to be read.
+ * @param currentDepth
+ * The current include depth.
+ * @throws IOException
+ * Thrown in case of an I/O error.
+ * @throws CircularIncludeException
+ * Thrown if circular includes have been detected (@link {@link RuntimeException}).
+ */
+ private synchronized void load(File file, int currentDepth) throws IOException, CircularIncludeException {
+ if (currentDepth > MAX_NESTED_INCLUDE_DEPTH) {
+ throw new CircularIncludeException("Circular include instruction(s) detected.");
+ }
+ InputStream in = null;
+ try {
+ in = new FileInputStream(file);
+ log.debug("Loading '" + file.getCanonicalPath() + "'.");
+ super.load(in);
+ } finally {
+ IOUtils.closeQuietly(in);
+ }
+ // Properties have been loaded. Apply preprocessing step in order to process include instructions.
+ // Provide a context directory in order to be able to resolve relative path instructions.
+ processIncludes(file.getParentFile(), currentDepth);
+ }
+
+ /**
+ * Resolves all include instructions as part of a postprocessing step.
+ *
+ * @param contextFolder
+ * The folder that should be assumed as starting folder for relative include instructions.
+ * @param currentDepth
+ * The current include depth.
+ * @throws IOException
+ * Thrown in case of error.
+ */
+ private void processIncludes(File contextFolder, int currentDepth) throws IOException {
+ SortedMap
* Example: setKeyValue("key.1_level.2_level","the value for k_1_2")
null if the key is not a subtree referece
*/
@@ -129,7 +129,7 @@ public class PropertyTree implements Serializable {
* This method return the subtree that corresponds to a particular key. The key does not split.
* Therefore the key must be a children of the current node. Search only in the key map of the
* current node.
- *
+ *
* @param key the key that has to be a sub node
* @return a sub tree (PropertyTree) or null
if the key is not a children of the
* current node
@@ -142,7 +142,7 @@ public class PropertyTree implements Serializable {
* Returns the last value (keys can be overloaded) of a key. The key are splitted into subnodes
* and the last node of the key is the current value holder. If a key or subnode is not in the sub
* tree the return value is null.
- *
+ *
* @param key the key that holds the value (can be a nested key like "key.1.2.3"
)
* @return the value of the key (last node of the key) or null
otherwise
*/
@@ -162,7 +162,7 @@ public class PropertyTree implements Serializable {
* Returns the first value (keys can be overloaded) of a key. The key are splitted into subnodes
* and the last node of the key is the current value holder. If a key or subnode is not in the sub
* tree the return value is null
.
- *
+ *
* @param key the key that holds the value (can be a nested key like "key.1.2.3"
)
* @return the value of the key (last node of the key) or null
otherwise
*/
@@ -180,7 +180,7 @@ public class PropertyTree implements Serializable {
/**
* This method return all values of the current node. The values are stored as String values.
- *
+ *
* @return the values (type String) of the current node
* @see Vector
*/
@@ -191,7 +191,7 @@ public class PropertyTree implements Serializable {
/**
* This method return all keys (sub tree references) of the current node as a Map. The keys are
* stored as String values.
- *
+ *
* @return the keys (type String) of the current node
* @see Map
*/
@@ -202,7 +202,7 @@ public class PropertyTree implements Serializable {
/**
* This method return all keys (sub tree references) of the current node as an ArrayList. The keys
* are stored as String values.
- *
+ *
* @return the keys (type String) of the current node
* @see ArrayList
*/
@@ -219,10 +219,10 @@ public class PropertyTree implements Serializable {
}
/**
- *
+ *
* This method return all sub tree references of a key as an ArrayList. The keys are stored as
* String values.
- *
+ *
* @param key (can be a nested key like "key.1.2.3"
)
* @return the keys (type String) of the current node
* @see ArrayList
@@ -237,7 +237,7 @@ public class PropertyTree implements Serializable {
/**
* This method return all values of a key. The values are stored as String values.
- *
+ *
* @param key (can be a nested key like "key.1.2.3"
)
* @return the values (type Vector) of the key or null
if the key is not in the sub
* tree of the current node
@@ -254,7 +254,7 @@ public class PropertyTree implements Serializable {
/**
* Store a sub tree (type PropertyTree) in the current node. The key and it's sub tree are stored
* in a HashMap.
- *
+ *
* @param key the reference of the sub tree
* @param tree the sub tree of the key
* @see HashMap
@@ -270,7 +270,7 @@ public class PropertyTree implements Serializable {
* Extracts a sub tree of a nested key. The Method returns the last sub tree of the nested key.
* Example: if the key is like: key.1.2.3
the sub tree of the last
* node 3
is returned.
- *
+ *
* @param key the reference of the sub tree
* @return a sub tree of the key or null
if the key can not be found
*/
@@ -280,7 +280,7 @@ public class PropertyTree implements Serializable {
/**
* This method checks if a key is a reference to a sub tree in the current node.
- *
+ *
* @param key a simple key that is a parent reference of a sub tree
* @return true if the key is found, false otherwise
*/
@@ -291,7 +291,7 @@ public class PropertyTree implements Serializable {
/**
* The default toString method. It starts with the current node recursively downwards and return
* the String representation of the node.
- *
+ *
* @return the string representation of the node
*/
public String toString() {
@@ -300,9 +300,9 @@ public class PropertyTree implements Serializable {
/**
* This is a helper function to define the prefix for different levels in the toString method, not
- * realy nice ;-).
- * It replaces all "." chars with " ".
- *
+ * realy nice ;-).
+ * In other words: Fills {@code key} with spaces (of same length).
+ *
* @param key
* @return a replaces prefix string
*/
@@ -312,7 +312,7 @@ public class PropertyTree implements Serializable {
/**
* This method concatenates all values of the current node and return them as a combinded string.
- *
+ *
* @param prefix
* @param tree
* @return the string representation of the node values
@@ -330,7 +330,7 @@ public class PropertyTree implements Serializable {
/**
* The toString method. It starts with a special level prefix, sub tree and recursively adds all
* sub trees.
- *
+ *
* @param prefix the prefix for this node
* @param tree the current node
* @return the string representation of the node
@@ -351,8 +351,40 @@ public class PropertyTree implements Serializable {
}
return os;
}
-
+
public void removeEntry(String key) {
- this.keys_.remove(key);
+ this.keys_.remove(key);
}
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((keys_ == null) ? 0 : keys_.hashCode());
+ result = prime * result + ((values_ == null) ? 0 : values_.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ PropertyTree other = (PropertyTree) obj;
+ if (keys_ == null) {
+ if (other.keys_ != null)
+ return false;
+ } else if (!keys_.equals(other.keys_))
+ return false;
+ if (values_ == null) {
+ if (other.values_ != null)
+ return false;
+ } else if (!values_.equals(other.values_))
+ return false;
+ return true;
+ }
+
}
\ No newline at end of file
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/SettingsReader.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/SettingsReader.java
index 352c594..832f952 100644
--- a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/SettingsReader.java
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/SettingsReader.java
@@ -32,7 +32,6 @@ import iaik.security.provider.IAIK;
import iaik.utils.RFC2253NameParser;
import java.io.File;
-import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
@@ -42,6 +41,7 @@ import java.util.Enumeration;
import java.util.Properties;
import java.util.Vector;
+import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.text.StrSubstitutor;
import org.apache.commons.logging.Log;
@@ -49,6 +49,7 @@ import org.apache.commons.logging.LogFactory;
import at.gv.egiz.pdfas.api.commons.Constants;
import at.gv.egiz.pdfas.api.exceptions.ConfigUtilsException;
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
import at.gv.egiz.pdfas.utils.ConfigUtils;
import at.gv.egiz.pdfas.utils.TempDirHelper;
import at.knowcenter.wag.egov.egiz.PdfAS;
@@ -61,36 +62,36 @@ import at.knowcenter.wag.egov.egiz.tools.FileHelper;
* The SettingsReader reads the settings.txt
file. The
* settings.txt
is a simple java property file that collects all
* parameters used in different modules.
- *
+ *
* The SettingsReader provides methods to get the property keys and the
* corresponding values. The keys could be defined as combinations of single
* keys. Therefore it is possible to combine differen classes of keys. An
* example could be:
- *
+ *
*
- *
+ *
* #SettingNotFoundException
* error.code.100=Interner Fehler
* error.code.101=Die Konfigurationsdatei konnte nicht geladen werden
- *
+ *
* #PDFDocumentException
* error.code.200=Das Dokument konnte nicht geladen werden
- *
+ *
* #SignatureException
* error.code.300=Die Signatur ist ungültig
- *
+ *
* #NormalizeException
* error.code.400=Die angegebene Version ist nicht bekannt
- *
+ *
* normalizer.version=V01
- *
+ *
*
- *
+ *
* The internal representation of the example above is:
- *
+ *
*
- *
+ *
* .error|
* |.code|
@@ -100,10 +101,10 @@ import at.knowcenter.wag.egov.egiz.tools.FileHelper;
* | |.101=Die Konfigurationsdatei konnte nicht geladen werden
* | |.300=Die Signatur ist ungueltig
* .normalizer|
- * |.version=V01
- *
+ * |.version=V01
+ *
*
- *
+ *
* @author wlackner
*/
public class SettingsReader implements Serializable
@@ -145,17 +146,22 @@ public class SettingsReader implements Serializable
* The file path postfix where certificates are stored
*/
private static final String CERT = "certificates";
-
+
/**
* pdf-as internal properties resource path
*/
private static final String PDF_AS_PROP_RESOURCE = "/config/pdf-as.properties";
-
+
+ /**
+ * The default configuration properties. These settings can be overridden by any local configuration.
+ */
+ private static final String DEFAULT_CFG_PROPERTIES_RESOURCE = "/config/defaultconfig.properties";
+
/**
* internal help file
*/
private static final String HELP_TEXT_PROP_RESOURCE = "/config/help_text.properties";
-
+
public static final boolean REGISTER_IAIK_PROVIDERS_ON_DEFAULT = true;
// /**
@@ -165,14 +171,14 @@ public class SettingsReader implements Serializable
/**
* The path of the resources repository.
- *
+ *
* settingsFile == null
the
* default settings ({@link SettingsReader#CONFIG_FILE_DEFAULT_NAME})
@@ -271,39 +277,45 @@ public class SettingsReader implements Serializable
try
{
String cfg_path = CONFIG_PATH;
- properties_ = new Properties();
if (settingsFile == null)
{
settingsFile = cfg_path + CONFIG_FILE_DEFAULT_NAME;
}
- settingsFile_ = settingsFile;
- if (logger_.isInfoEnabled())
- {
- File file = new File(settingsFile_);
- logger_.debug("load Settings:" + file.getAbsolutePath());
- // Properties sys_prop = System.getProperties();
- // Enumeration prop_keys = sys_prop.propertyNames();
- // while (prop_keys.hasMoreElements()) {
- // String key = (String) prop_keys.nextElement();
- // String value = sys_prop.getProperty(key);
- // logger_.info(key + "=" + value);
- // }
- }
- FileInputStream sfs = new FileInputStream(settingsFile_);
- properties_.load(sfs);
-
+ settingsFile_ = new File(settingsFile);
+ logger_.debug("load Settings:" + settingsFile_.getAbsolutePath());
+
+ // DTI
+ // (1) first load default properties which may be overloaded by local configurations
+ Properties defaultConfiguration = new Properties();
+ InputStream in = null;
+ try {
+ defaultConfiguration.load(in = getClass().getResourceAsStream(DEFAULT_CFG_PROPERTIES_RESOURCE));
+ } catch (Exception e) {
+ throw new SettingsException(ErrorCode.UNABLE_TO_LOAD_DEFAULT_CONFIG,
+ "Unable to load default configuration.", e);
+ } finally {
+ IOUtils.closeQuietly(in);
+ }
+
+ // (2) then load main configuration (considers include instructions)
+ NestedProperties includeAwareProperties = new NestedProperties(defaultConfiguration);
+ try {
+ includeAwareProperties.load(settingsFile_);
+ properties_ = includeAwareProperties;
+ } catch (CircularIncludeException e) {
+ throw new SettingsException(ErrorCode.CIRCULAR_INCLUDE_INSTRUCTION_DETECTED, e);
+ }
+
+ // (3) then forcedly overwrite some system settings
// dferbas override with system props
properties_.load(SettingsReader.class.getResourceAsStream(PDF_AS_PROP_RESOURCE));
+ // (4) and finally add help texts.
Properties help_prop = new Properties();
-// FileInputStream hfs = new FileInputStream(cfg_path + HELP_TEXT_FILE_DEFAULT_NAME);
-// help_prop.load(hfs);
help_prop.load(SettingsReader.class.getResourceAsStream(HELP_TEXT_PROP_RESOURCE));
- // load properties from current package!
- // properties_.load(getClass().getResourceAsStream(settingsFile_));
+ // (5) Build PropertyTree configuration.
Enumeration prop_keys = properties_.propertyNames();
-
while (prop_keys.hasMoreElements())
{
String key = (String) prop_keys.nextElement();
@@ -319,10 +331,12 @@ public class SettingsReader implements Serializable
pTree_.setKeyValue(key, value);
}
}
+
catch (IOException e)
{
throw new SettingsException("Couldn't load settings from file " + settingsFile, e);
}
+
}
/**
@@ -331,7 +345,7 @@ public class SettingsReader implements Serializable
* holding the definitions of the default settings file. Default file:
* {@link SettingsReader#CONFIG_FILE_DEFAULT_NAME}: "settings.txt".
* Note: IAIK JCE and IAIK ECC security providers are automatically registered.
- *
+ *
* @return an instance of the SettingsReader
* @throws SettingsException
* if the default settings file could not be read
@@ -340,15 +354,15 @@ public class SettingsReader implements Serializable
{
return getInstance(null);
}
-
+
/**
* Reloads the Settings file.
- *
+ *
* true
: automatically registers IAIK JCE and ECC Provider;
* false
: providers will NOT be automatically registered, providers
- * needed have to be registered by the API user
+ * needed have to be registered by the API user
* @throws SettingsException f.e.
*/
public synchronized static void createInstance(boolean registerProvider) throws SettingsException
@@ -381,18 +395,18 @@ public class SettingsReader implements Serializable
* settingsFile == null
the default settings file will be load.
* Default file: {@link SettingsReader#CONFIG_FILE_DEFAULT_NAME}:
* "settings.txt"
- *
+ *
* If an instance of this class exist, the input param is ignored! The
* SettingsReader is singleton and therefore the first
* {@link SettingsReader#getInstance()}defines the settings file that has to
* be loaded. This means changes between a application lifecyle can not be
* done!
- *
+ *
* @param settingsFile
* the settings file that should be load.
* @param registerProvider true
: automatically registers IAIK JCE and ECC Provider;
* false
: providers will NOT be automatically registered, providers
- * needed have to be registered by the API user
+ * needed have to be registered by the API user
* @return an instance of the SettingsReader
* @throws SettingsException
* if the settings file could not be read
@@ -402,7 +416,7 @@ public class SettingsReader implements Serializable
if (instance_ == null)
{
int length = Utils.max(new int[] { RESOURCES_PATH.length(), TMP_PATH.length(), CONFIG_PATH.length(), CERT_PATH.length() });
-
+
logger_.info(StringUtils.repeat("*", length + 25));
logger_.info(" resources path = \"" + RESOURCES_PATH + "\"");
logger_.info(" configuration path = \"" + CONFIG_PATH + "\"");
@@ -410,7 +424,7 @@ public class SettingsReader implements Serializable
logger_.info(" temporary path = \"" + TMP_PATH + "\"");
logger_.debug(" file.encoding = \"" + System.getProperty("file.encoding") + "\"");
logger_.info(StringUtils.repeat("*", length + 25));
-
+
if (registerProvider) {
IAIK.addAsProvider();
ECCProvider.addAsProvider();
@@ -429,12 +443,12 @@ public class SettingsReader implements Serializable
// Does not conform with PKIX, but is used by belgium citizen card
// log.info("Registering RDN \"SERIALNUMBER\" as " + ObjectID.serialNumber + ".");
RFC2253NameParser.register("SERIALNUMBER", ObjectID.serialNumber);
-
+
instance_ = new SettingsReader(settingsFile);
}
return instance_;
}
-
+
/**
* This method returns an synchronized instance of this class. The settings
* file is read only once using this class. This method returns the instance
@@ -443,13 +457,13 @@ public class SettingsReader implements Serializable
* Default file: {@link SettingsReader#CONFIG_FILE_DEFAULT_NAME}:
* "settings.txt".
* Note: IAIK JCE and IAIK ECC security providers are automatically registered.
- *
+ *
* If an instance of this class exist, the input param is ignored! The
* SettingsReader is singleton and therefore the first
* {@link SettingsReader#getInstance()}defines the settings file that has to
* be loaded. This means changes between a application lifecyle can not be
* done!
- *
+ *
* @param settingsFile
* the settings file that should be load.
* @return an instance of the SettingsReader
@@ -464,7 +478,7 @@ public class SettingsReader implements Serializable
/**
* This method returns a property value to the corresponding key. If the key
* is not found in the property file a SettingNotFoundException is thrown.
- *
+ *
* @param key
* get the value for that key in the property file
* @return the value of the property key.
@@ -490,17 +504,10 @@ public class SettingsReader implements Serializable
return result;
}
-
- // TODO in the next change request, the Setting system will be refactored
- // this is just for testing purposes.
- public void setSetting(String key, String value)
- {
- properties_.setProperty(key, value);
- }
/**
* Relocates the relative file.
- *
+ *
* @param file
* The relative file.
* @return Returns the usable file.
@@ -519,7 +526,7 @@ public class SettingsReader implements Serializable
/**
* This method returns a property value to the corresponding key. If the key
* is not found in the property file the input param defaultValue is returned.
- *
+ *
* @param key
* get the value for that key in the property file
* @param defaultValue
@@ -545,7 +552,7 @@ public class SettingsReader implements Serializable
* This method returns a property value to the corresponding key. If the key
* is not found in the property file the input param defaultKey is searched.
* If the default key is not found the input param defaultValue is returned.
- *
+ *
* @param primaryKey
* get the value for that key in the property file
* @param defaultKey
@@ -580,7 +587,7 @@ public class SettingsReader implements Serializable
* keyPrefix. The method search all keys in the property file that has the
* keyPrefix as leading substring. The Object[]
collects all
* sub keys without the keyPrefix.
- *
+ *
* @param keyPrefix
* to search for sub keys
* @return alls keys starting with the keyPrefix
@@ -604,7 +611,7 @@ public class SettingsReader implements Serializable
* If a property value is number (interger) this method extracts the value and
* convert it to an int. If the key ist not found or the conversion fails, the
* defaultValue is returned.
- *
+ *
* @param key
* get the value for that key in the property file
* @param defaultValue
@@ -641,7 +648,7 @@ public class SettingsReader implements Serializable
* This method returns an array of sub keys (children references) of the key.
* The method is a wrapper calling the method
* {@link PropertyTree#getKeys(String key)}.
- *
+ *
* @param key
* get all sub keys for that key in the property file
* @return an list of sub keys (type String)
@@ -659,7 +666,7 @@ public class SettingsReader implements Serializable
* not overload keys. If a key is defined more than one times the last
* definition is stored it the property list. The method is a wrapper calling
* the method {@link PropertyTree#getFirstValue(String key)}.
- *
+ *
* @param key
* get the value for that key in the property file
* @return the value of the property key
@@ -678,7 +685,7 @@ public class SettingsReader implements Serializable
/**
* This method returns the PropertyTree representation of the configuration
* file.
- *
+ *
* @return Returns the pTree.
* @see PropertyTree
*/
@@ -686,20 +693,20 @@ public class SettingsReader implements Serializable
{
return pTree_;
}
-
+
/**
* Reads internal resource as string.
* @param relativePath
* @return null in case of error
*/
public String readInternalResourceAsString(String relativePath) {
-// return readAsString(getInternalResource(relativePath));
- return FileHelper.readFromInputStream(getInternalResource(relativePath));
+// return readAsString(getInternalResource(relativePath));
+ return FileHelper.readFromInputStream(getInternalResource(relativePath));
}
-
+
/**
* Get resource as stream, relative to internal resource path {@value #INTERNAL_RESOURCE_PATH}
- *
+ *
* @param relativePath
* @return
*/
@@ -717,9 +724,9 @@ public class SettingsReader implements Serializable
}
return stream;
}
-
+
/**
- * Read resource as utf8 string.
+ * Read resource as utf8 string.
* @param is
* @return null
in case of error
*/
@@ -730,7 +737,7 @@ public class SettingsReader implements Serializable
return IOUtils.toString(is, "utf-8");
} catch (IOException e) {
logger_.info("error reading stream to string ", e);
- }
+ }
return null;
}
*/
@@ -758,11 +765,11 @@ public class SettingsReader implements Serializable
/**
* Returns the directory where temporary files should be stored.
- *
+ *
*
* These functions are used to replace parts of the original Egiz plain text * signature mechanism. *
- * + * * @author wprinz */ public abstract class BinarySignature { //23.11.2010 changed by exthex - added replacePlaceholder(PdfStamper stamper, int pageNr, String placeholderName) method - + protected static Log logger = LogFactory.getLog(BinarySignature.class); + + /** + * The resource path of the srgb profile to be embedded in case of PDF/A-1b. + */ + private static final String srgbProfileResource = "/at/gv/egiz/pdfas/itext/srgb.profile"; + + /** + * The color profile to be embedded in case of PDF/A-1b. + */ + private static final byte[] SRGB_PROFILE; + + static { + try { + logger.debug("Preloading srgb color profile '" + srgbProfileResource + "."); + SRGB_PROFILE = IOUtils.toByteArray(BinarySignature.class.getResourceAsStream(srgbProfileResource)); + } catch (IOException e) { + throw new RuntimeException("Unable to preload srgb color profile.", e); + } + } + /** * The tolerance area of the line break algorithm. - * + * * @see Placeholder#replacePlaceholderWithTolerance(byte[], List, byte[], int) */ public static final int LINE_BREAK_TOLERANCE = 10; @@ -116,11 +138,11 @@ public abstract class BinarySignature * The number of bytes left out for the certificate placeholder. */ public static final int CERTIFICATE_PLACEHOLDER_LENGTH = 10000; - + /** * The number of bytes left out for the timestamp placeholder. */ - public static final int TIMESTAMP_PLACEHOLDER_LENGTH = 5000; + public static final int TIMESTAMP_PLACEHOLDER_LENGTH = 5000; /** * The placeholder character used to fill out Strings in the layout process. @@ -162,11 +184,11 @@ public abstract class BinarySignature * The SIG_ID brev. */ public static final byte[] BREV_SID = { 's', 'i', 'd' }; - + /** * The SIG_ALG brev. */ - public static final byte[] BREV_ALG = { 'a', 'l', 'g' }; + public static final byte[] BREV_ALG = { 'a', 'l', 'g' }; /** * No explicit encoding. @@ -185,7 +207,7 @@ public abstract class BinarySignature /** * The PDFName of the Egiz Dictionary. - * + * ** Used to locate and identify the Egiz Dictionary in the document. *
@@ -195,7 +217,7 @@ public abstract class BinarySignature /** * The PDFName of the Original Document Size (ODS) field in an Egiz * Dictionary. - * + * ** The ODS must be a positive integral number. *
@@ -226,7 +248,7 @@ public abstract class BinarySignature * The PdfName of the certificate array. */ public static final PdfName EGIZ_CERTIFICATE_NAME = new PdfName("Cert"); - + /** * The PdfName of the Timestamp */ @@ -239,7 +261,7 @@ public abstract class BinarySignature /** * The PDFName of the Signature XObject field in an Egiz Dictionary. - * + * ** This must be an indirect reference to the XObject containing the Signature * table. @@ -251,17 +273,17 @@ public abstract class BinarySignature * The number placeholder that is used to give numbers a fixed length. */ protected static final PdfNumber NUMBER_PLACEHOLDER = new PdfNumber(999999999); - + /** * Extracts the signature text only. - * + * *
* The signature text is the text of the Signature XObject. *
- * + * * @param egiz_dict * The Egiz Dictionary. - * + * * @return Returns the signature text. */ public static String extractSignatureTextOnly(PdfDictionary egiz_dict) throws IOException @@ -276,7 +298,7 @@ public abstract class BinarySignature /** * Retrieves the size of the original document from the Egiz Dictionary. - * + * * @param egiz_dict * The Egiz Dictionary. * @return Returns the size (in bytes) of the original document. @@ -292,7 +314,7 @@ public abstract class BinarySignature /** * Retrieves the previous Egiz dictionary from the given one, if a previous * dictionary exists. - * + * * @param egiz_dict * The Egiz Dictionary. * @return Returns the previous Egiz Dictionary, or null if there is none. @@ -306,7 +328,7 @@ public abstract class BinarySignature /** * Retrieves the Egiz Dictionary from the document if present. - * + * * @param reader * The reader to retrieve the dictionary from. * @return Returns the Egiz Dictionary, if present, or returns null, if no @@ -327,7 +349,7 @@ public abstract class BinarySignature /** * Retrieves the Egiz Dictionary's indirect reference from the reader. - * + * * @param reader * The reader. * @return Returns the indirect reference of the Egiz Dictionary, or null, if @@ -342,14 +364,14 @@ public abstract class BinarySignature /** * Retrieves the chain of Egiz Dictionaries from the reader. - * + * ** The first element in the List will be the top most (oldest) Egiz * Dictionary. The last element in the List will be the bottom most (latest) * Egiz Dictionary. If the list is empty, no dictionary could be found at all, * which means that the document is not digitally signed. *
- * + * * @param reader * The reader. * @return Returns the List of PdfDictionaries from the document. @@ -374,7 +396,7 @@ public abstract class BinarySignature /** * Builds a digest of the given data. - * + * * @param data * The data to be digested. * @param length @@ -393,7 +415,6 @@ public abstract class BinarySignature } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); throw new PDFDocumentException(202, "Digest algorithm not supported - NoSuchAlgorithmException", e); } @@ -406,7 +427,7 @@ public abstract class BinarySignature /** * Retrieves the signable text from the given document. - * + * * @param data * The data. * @param ods @@ -423,7 +444,7 @@ public abstract class BinarySignature /** * Fills the holes in the byte ranges with the SIGN_PLACEHOLDER. - * + * * @param data * The given byte ranged data. * @param byte_ranges @@ -697,7 +718,7 @@ public abstract class BinarySignature // throw new PresentableException(e); // } // } - + protected static int getLineBreakTolerance(IncrementalUpdateInformation iui) throws PDFDocumentException { SettingsReader settings; @@ -717,7 +738,7 @@ public abstract class BinarySignature } return lineBreakTolerance; } - + protected static int getCertificatePlaceholderLength(IncrementalUpdateInformation iui) throws SettingNotFoundException { SettingsReader settings; @@ -737,7 +758,7 @@ public abstract class BinarySignature } return certLen; } - + protected static int getTimestampPlaceholderLength(IncrementalUpdateInformation iui) throws SettingNotFoundException { SettingsReader settings; @@ -761,7 +782,7 @@ public abstract class BinarySignature /** * Signs a document with the given signature table using the Incremental * Update method. - * + * ** The table containing the signature text will be appended. As specified by * the parameters, the signature will be appended to the last page, or a plain @@ -777,7 +798,7 @@ public abstract class BinarySignature * information about the signature. Basically the size of the original * document and the reference of the signature table. *
- * + * * @param original_document * The original document. * @param pdf_table @@ -811,10 +832,7 @@ public abstract class BinarySignature // System.out.println("wprinz: STAMPING PDF"); // InputStream is = original_document.createInputStream(); - byte[] pdf_data = original_document.getAsByteArray(); - PdfReader reader = new PdfReader(pdf_data); - PDFASUtils.checkReaderPermissions(reader); - // is.close(); + PdfReader reader = PDFASUtils.createPdfReaderCheckingPermissions(original_document); OutputStream baos = written_pdf.createOutputStream("application/pdf"); // ByteArrayOutputStream baos = new ByteArrayOutputStream(); @@ -823,7 +841,7 @@ public abstract class BinarySignature // incremental updated // The stamper allows this by setting append = true boolean adobeSigField = AdobeSignatureHelper.isAdobeSignatureFieldEnabled(so.getSignatureTypeDefinition().getType()); - PdfStamper stamper = null; + PdfStamper stamper = null; if (adobeSigField) { stamper = PdfStamper.createSignature(reader, baos, '\0', null, true); } else { @@ -843,13 +861,13 @@ public abstract class BinarySignature { throw new PDFDocumentException(224, "The provided page (=" + pi.getPage() + ") is out of range."); } - + if (SignaturePlaceholderContext.isSignaturePlaceholderDataSet() && SignaturePlaceholderContext.getSignaturePlaceholderData().getPlaceholderName() != null) { replacePlaceholder(stamper, pi.getPage(), SignaturePlaceholderContext.getSignaturePlaceholderData().getPlaceholderName()); } - + PdfContentByte content = stamper.getOverContent(pi.getPage()); // content = StampContent einer PageStamp. @@ -857,12 +875,12 @@ public abstract class BinarySignature // table_height = " + pdf_table.getTotalHeight()); PdfTemplate table_template = content.createTemplate(pdf_table.getTotalWidth(), pdf_table.getTotalHeight()); - table_template.setCompress(Boolean.FALSE); // do not compress sigblock because we rewrite it afterwards for bin sig + table_template.setCompress(Boolean.FALSE); // do not compress sigblock because we rewrite it afterwards for bin sig // exthex StructContentHelper structHelper = new StructContentHelper(stamper, content, pi.getPage()); structHelper.prepareStructData(table_template); - + pdf_table.writeSelectedRows(0, -1, 0, pdf_table.getTotalHeight(), table_template); // table_template.moveTo(0, 0); @@ -876,13 +894,13 @@ public abstract class BinarySignature // pdf_table.writeSelectedRows(0, -1, SIGNATURE_BORDER / 2, // table_position, content); - + structHelper.beginSigBlockContent(); - + content.addTemplate(table_template, pi.getX(), pi.getY() - pdf_table.getTotalHeight()); - - structHelper.endSigBlockContent(); - + + structHelper.endSigBlockContent(); + ActualTablePos atp = new ActualTablePos(); atp.page = pi.getPage(); @@ -891,13 +909,13 @@ public abstract class BinarySignature atp.width = pdf_table.getTotalWidth(); atp.height = pdf_table.getTotalHeight(); iui.actualTablePos = atp; - + structHelper.buildFigureStructData(so, table_template); structHelper.buildSigBlockStructData(); structHelper.finishMainStructData(); - + structHelper.buildVerifyLinkStructData(table_template, atp); - + // For debugging print a 100x100 grid // { // Rectangle psize = reader.getPageSizeWithRotation(pos.page); @@ -940,7 +958,22 @@ public abstract class BinarySignature // PdfObject value = resources.get(key); // System.out.println(" " + key + " = " + value); // } - + + // added by dti: fixing PDF/A-1b + if (PDFASUtils.isPdfAEnabled(profile)) { + logger.debug("Adding sRGB IEC61966-2.1 color profile (output intent) in order to satisfy PDF/A-1b requirements."); + PdfWriter writer = stamper.getWriter(); + writer.setOutputIntents("Custom", "sRGB", "", "sRGB IEC61966-2.1", SRGB_PROFILE); + PdfArray a = writer.getExtraCatalog().getAsArray(PdfName.OUTPUTINTENTS); + if (a != null) { + PdfDictionary d = a.getAsDict(0); + if (d != null) { + // overwrite PDF/X entry with PDF/A entry + d.put(PdfName.S, PdfName.GTS_PDFA1); + } + } + } + // add the EGIZ dict: if (variable_field_definitions != null) { @@ -964,22 +997,20 @@ public abstract class BinarySignature } catch (IOException e) { - e.printStackTrace(); throw new PresentableException(ErrorCode.CANNOT_WRITE_PDF, e); } catch (DocumentException e) { - e.printStackTrace(); throw new PresentableException(ErrorCode.CANNOT_WRITE_PDF, e); } } - + private static void replacePlaceholder(PdfStamper stamper, int pageNr, String placeholderName) throws BadElementException, MalformedURLException, IOException, BadPdfFormatException, PresentableException { Image img = Image.getInstance(SignaturePlaceholderData.class.getResource("empty.jpg")); PdfImage pImg = new PdfImage(img, "Imwurscht", null); PdfStamperImp stamperImp = (PdfStamperImp)stamper.getWriter(); PdfIndirectObject ind = stamperImp.addToBody(pImg); - + PdfDictionary resources = stamper.getReader().getPageN(pageNr).getAsDict(PdfName.RESOURCES); if (ind != null && resources != null) { @@ -999,11 +1030,11 @@ public abstract class BinarySignature throw new PresentableException(ErrorCode.CANNOT_WRITE_PDF, new NullPointerException("Resource dictionary not found in document structure!")); } } - + /** * Creates the EGIZ Dictionary and adds it to the document. - * + * * @param stamper * The PdfStamper. * @param table_template @@ -1092,11 +1123,11 @@ public abstract class BinarySignature // /encodings replaces_array.add(new PdfName(new String(BREV_NIL, "US-ASCII"))); // the // /Cert - + if (iui.timeStamper != null) { encodings_array.add(new PdfName(new String(ENCODING_NIL))); // the /Timestamp replaces_array.add(new PdfName(new String(BREV_NIL, "US-ASCII"))); // the /timestamp - + } // hidden replaces @@ -1153,9 +1184,9 @@ public abstract class BinarySignature } PdfString cert_placeholder = new PdfString(cert_bytes); cert_array.add(cert_placeholder); - egiz_dict.put(EGIZ_CERTIFICATE_NAME, cert_array); - - // Timestamp + egiz_dict.put(EGIZ_CERTIFICATE_NAME, cert_array); + + // Timestamp if (iui.timeStamper != null) { // only if handler is available PdfArray timestamp_array = new PdfArray(); @@ -1167,10 +1198,10 @@ public abstract class BinarySignature } PdfString timestamp_placeholder = new PdfString(timestamp_bytes); timestamp_array.add(timestamp_placeholder); - egiz_dict.put(EGIZ_TIMESTAMP_NAME, timestamp_array); + egiz_dict.put(EGIZ_TIMESTAMP_NAME, timestamp_array); } - + // /Data array with hidden information if (has_hidden_variable_fields || invisibleKZString != null) { @@ -1221,7 +1252,7 @@ public abstract class BinarySignature /** * Converts a field name (type) to the corresponding BREV. - * + * * @param type * The field name (type). * @return Returns the corresponding BREV, or BREV_NIL if the type is not @@ -1261,12 +1292,12 @@ public abstract class BinarySignature /** * Updates the information in the egiz dictionary to reflect the real offsets * of the byte ranges. - * + * ** This replaces the "dummy numbers" in the egiz dictionary with the correct * values. *
- * + * * @param iui * The IncrementalUpdateInformation. * @throws PDFDocumentException @@ -1309,7 +1340,7 @@ public abstract class BinarySignature byte[] cert_bytes = cert_str.getBytes("US-ASCII"); int cert_index = ByteArrayUtils.indexOf(signed_pdf, obj_start, cert_bytes); int cert_start = cert_index + cert_bytes.length; - + //Timestamp int timestamp_index = 0; int timestamp_start = 0; @@ -1325,14 +1356,14 @@ public abstract class BinarySignature int cur_pos = array_start; int cur_br_start = 0; - + // write the /encodings byte range { int num_replaces = calcNumReps(iui.replaces); - int num_holes = num_replaces + 1 + 1; + int num_holes = num_replaces + 1 + 1; // +1 = the /encodings hole - // +1 = the /Cert + // +1 = the /Cert // +1 = the /Timestamp if (iui.timeStamper != null) { num_holes += 1; @@ -1376,7 +1407,7 @@ public abstract class BinarySignature iui.cert_start = cert_start; } - + // write the /Timestamp byte range if (iui.timeStamper != null) { StringInfo byte_range = new StringInfo(); @@ -1394,7 +1425,7 @@ public abstract class BinarySignature cur_br_start = timestamp_start + iui.timestamp_length; iui.timestamp_start = timestamp_start; - } + } // determine the /Data byte ranges if any List ifd = iui.invisible_field_definitions; @@ -1411,7 +1442,7 @@ public abstract class BinarySignature { StringInfo si = (StringInfo) iui.kz_list.get(0); si.string_start = hole_start; - + hole_start += si.string_length + 2; } @@ -1468,7 +1499,7 @@ public abstract class BinarySignature cur_pos += num_digits; cur_pos += 1; - + // update the Kennzeichnung byte ranges cur_pos = kz_start; for (int i = 0; i < iui.kz_list.size(); i++) @@ -1494,7 +1525,7 @@ public abstract class BinarySignature /** * Replaces the certificate placeholder with the certificate from the signed * Signature Object. - * + * * @param iui * The IncrementalUpdateInformation. * @throws PDFDocumentException @@ -1550,7 +1581,7 @@ public abstract class BinarySignature /** * Replaces the timestam placeholder with the timestamp from the signed * Signature Object. - * + * * @param iui * The IncrementalUpdateInformation. * @throws PDFDocumentException @@ -1558,27 +1589,27 @@ public abstract class BinarySignature public static void replaceTimestamp(IncrementalUpdateInformation iui) throws PDFDocumentException { String timestamp = iui.signed_signature_object.getSigTimeStamp(); - if (timestamp != null) { + if (timestamp != null) { byte[] escaped = Placeholder.escapePDFString(timestamp.getBytes()); if (escaped.length > iui.timestamp_length) { throw new PlaceholderException("timestamp", escaped.length - iui.timestamp_length); } - System.arraycopy(escaped, 0, iui.signed_pdf, iui.timestamp_start, escaped.length); + System.arraycopy(escaped, 0, iui.signed_pdf, iui.timestamp_start, escaped.length); } } - + /** * Replaces the placeholders with values from the signed SignatureObject. - * + * * @param iui * The IncrementalUpdateInformation. * @throws PDFDocumentException */ public static void replacePlaceholders(IncrementalUpdateInformation iui) throws PDFDocumentException { - final int lineBreakTolerance = getLineBreakTolerance(iui); - + final int lineBreakTolerance = getLineBreakTolerance(iui); + final byte[] signed_pdf = iui.signed_pdf; // int num_replaces = calcNumReps(iui.replaces); @@ -1661,7 +1692,7 @@ public abstract class BinarySignature * carried out. Accordingly to this number, entries in the dictionary are * created. * - * + * * @param replaces * The ReplaceInfo list. * @return Returns the number of string replaces. @@ -1681,12 +1712,12 @@ public abstract class BinarySignature /** * Determines the List of ReplaceInfo objects of replaces in the content * stream regarding the given field definitions. - * + * ** This method collects all variable String fields in a content stream and * orders them according to their start offset. *
- * + * * @param pdf * The PDF. * @param begin @@ -1760,7 +1791,7 @@ public abstract class BinarySignature /** * Determines the Kennzeichnug in the content stream. - * + * * @param pdf * The PDF. * @param begin @@ -1819,7 +1850,7 @@ public abstract class BinarySignature /** * Finds the index of the StringInfo within the StringInfo list that has the * given content (caption). - * + * * @param strings * The list of StringInfos. * @param caption @@ -1886,7 +1917,7 @@ public abstract class BinarySignature /** * Tells, if the given StringInfo contains only placeholder characters. - * + * * @param si * The StringInfo. * @param placeholder @@ -1935,7 +1966,7 @@ public abstract class BinarySignature /** * Finds the first string after and at the given index not being a placeholder * string. - * + * * @param strings * The list of StringInfos. * @param start @@ -1958,7 +1989,7 @@ public abstract class BinarySignature /** * Restores the given String to its placeholder. - * + * * @param pdf * The PDF. * @param si @@ -1978,7 +2009,7 @@ public abstract class BinarySignature /** * Reconstructs the replaces from the PDF and forms suitable value strings. - * + * * @param pdf * The PDF. * @param brevs @@ -2044,7 +2075,7 @@ public abstract class BinarySignature /** * Reads an unsigned integer number. - * + * * @param pdf * The PDF. * @param start_index @@ -2073,7 +2104,7 @@ public abstract class BinarySignature /** * Replaces a number by the new value. - * + * * @param pdf * The PDF. * @param start_index diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFPage.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFPage.java index 7de89d2..1a89b7b 100644 --- a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFPage.java +++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFPage.java @@ -25,15 +25,19 @@ */ package at.knowcenter.wag.egov.egiz.pdf; +import java.awt.Rectangle; +import java.awt.geom.GeneralPath; import java.io.IOException; import java.util.List; import java.util.Map; +import org.apache.commons.lang.math.NumberUtils; import org.apache.log4j.Logger; import org.pdfbox.cos.COSName; import org.pdfbox.cos.COSStream; import org.pdfbox.pdmodel.PDPage; import org.pdfbox.pdmodel.PDResources; +import org.pdfbox.pdmodel.common.PDRectangle; import org.pdfbox.pdmodel.common.PDStream; import org.pdfbox.pdmodel.graphics.xobject.PDXObject; import org.pdfbox.pdmodel.graphics.xobject.PDXObjectForm; @@ -44,6 +48,21 @@ import org.pdfbox.util.TextPosition; import org.pdfbox.util.operator.OperatorProcessor; import at.knowcenter.wag.egov.egiz.cfg.ConfigLogger; +import at.knowcenter.wag.egov.egiz.pdf.operator.path.construction.ClosePath; +import at.knowcenter.wag.egov.egiz.pdf.operator.path.construction.CurveTo; +import at.knowcenter.wag.egov.egiz.pdf.operator.path.construction.CurveToReplicateFinalPoint; +import at.knowcenter.wag.egov.egiz.pdf.operator.path.construction.CurveToReplicateInitialPoint; +import at.knowcenter.wag.egov.egiz.pdf.operator.path.construction.LineTo; +import at.knowcenter.wag.egov.egiz.pdf.operator.path.construction.MoveTo; +import at.knowcenter.wag.egov.egiz.pdf.operator.path.painting.CloseAndStrokePath; +import at.knowcenter.wag.egov.egiz.pdf.operator.path.painting.CloseFillEvenOddAndStrokePath; +import at.knowcenter.wag.egov.egiz.pdf.operator.path.painting.CloseFillNonZeroAndStrokePath; +import at.knowcenter.wag.egov.egiz.pdf.operator.path.painting.EndPath; +import at.knowcenter.wag.egov.egiz.pdf.operator.path.painting.FillEvenOddAndStrokePath; +import at.knowcenter.wag.egov.egiz.pdf.operator.path.painting.FillNonZeroAndStrokePath; +import at.knowcenter.wag.egov.egiz.pdf.operator.path.painting.FillPathEvenOddRule; +import at.knowcenter.wag.egov.egiz.pdf.operator.path.painting.FillPathNonZeroWindingNumberRule; +import at.knowcenter.wag.egov.egiz.pdf.operator.path.painting.StrokePath; /** * PDFPage is an inner class that is used to calculate the page length of a PDF @@ -52,7 +71,7 @@ import at.knowcenter.wag.egov.egiz.cfg.ConfigLogger; * This method is called when processing the FileStream. By calling the method * {@link org.pdfbox.util.PDFStreamEngine#processStream(org.pdfbox.pdmodel.PDPage, org.pdfbox.pdmodel.PDResources, org.pdfbox.cos.COSStream)} * the implemented method showCharacter is called. - * + * * @author wlackner * @see PDFTextStripper */ @@ -67,41 +86,167 @@ public class PDFPage extends PDFTextStripper * The maximum (lowest) y position of a character. */ protected float max_character_ypos = Float.NEGATIVE_INFINITY; - + /** * The maximum (lowest y position of an image. */ protected float max_image_ypos = Float.NEGATIVE_INFINITY; - + /** * The effective page height. */ protected float effectivePageHeight; - + + /** + * The path currently being constructed. + */ + private GeneralPath currentPath = new GeneralPath(); + + /** + * The lowest position of a drawn path (originating from top). + */ + private float maxPathRelatedYPositionFromTop = Float.NEGATIVE_INFINITY; + /** * Constructor. - * + * * @param effectivePageHeight The height of the page to be evaluated. PDF elements outside this height will not be considered. - * + * * @throws IOException */ public PDFPage(float effectivePageHeight) throws IOException { super(); - + this.effectivePageHeight = effectivePageHeight; - + OperatorProcessor newInvoke = new MyInvoke(); newInvoke.setContext(this); operators.put("Do", newInvoke); + + registerCustomPathOperators(); } + /** + * Registers operators responsible for path construction and painting in order to fix auto positioning on pages with + * path elements. + * + * @author Datentechnik Innovation GmbH + */ + @SuppressWarnings("unchecked") + private void registerCustomPathOperators() { + + // *** path construction + + operators.put("m", new MoveTo(this)); + operators.put("l", new LineTo(this)); + operators.put("c", new CurveTo(this)); + operators.put("y", new CurveToReplicateFinalPoint(this)); + operators.put("v", new CurveToReplicateInitialPoint(this)); + operators.put("h", new ClosePath(this)); + + // *** path painting + + // "S": stroke path + operators.put("S", new StrokePath(this)); + operators.put("s", new CloseAndStrokePath(this)); + operators.put("f", new FillPathNonZeroWindingNumberRule(this)); + operators.put("F", new FillPathNonZeroWindingNumberRule(this)); + operators.put("f*", new FillPathEvenOddRule(this)); + operators.put("b", new CloseFillNonZeroAndStrokePath(this)); + operators.put("B", new FillNonZeroAndStrokePath(this)); + operators.put("b*", new CloseFillEvenOddAndStrokePath(this)); + operators.put("B*", new FillEvenOddAndStrokePath(this)); + operators.put("n", new EndPath(this)); + + // Note: The graphic context (org.pdfbox.pdmodel.graphics.PDGraphicsState) of the underlying pdfbox library does + // not yet support clipping. This prevents feasible usage of clipping operators (W, W*). +// operators.put("W", new ...(this)); +// operators.put("W*", new ...(this)); + + } + + /** + * Returns the path currently being constructed. + * + * @return The path currently being constructed. + */ + public GeneralPath getCurrentPath() { + return currentPath; + } + + /** + * Sets the current path. + * @param currentPath The new current path. + */ + public void setCurrentPath(GeneralPath currentPath) { + this.currentPath = currentPath; + } + + /** + * Registers a rectangle that bounds the path currently being drawn. + * + * @param bounds + * A rectangle depicting the bounds (coordinates originating from bottom left). + * @author Datentechnik Innovation GmbH + */ + public void registerPathBounds(Rectangle bounds) { + if (!bounds.isEmpty()) { + logger_.trace("Registering path bounds: " + bounds); + + // vertical start of rectangle (counting from top of page) + float upperBoundYPositionFromTop; + + // vertical end of rectangle (counting from top of page) + // this depicts the current end of path-related page content + float lowerBoundYPositionFromTop; + + PDRectangle boundaryBox = page.findMediaBox(); + float pageHeight; + + switch (page.findRotation()) { + case 90: // CW + pageHeight = boundaryBox.getWidth(); + upperBoundYPositionFromTop = (float) bounds.getMinX(); + lowerBoundYPositionFromTop = (float) bounds.getMaxX(); + break; + case 180: + pageHeight = boundaryBox.getHeight(); + upperBoundYPositionFromTop = (float) bounds.getMinY(); + lowerBoundYPositionFromTop = (float) bounds.getMaxY(); + break; + case 270: // CCW + pageHeight = boundaryBox.getWidth(); + upperBoundYPositionFromTop = pageHeight - (float) bounds.getMaxX(); + lowerBoundYPositionFromTop = pageHeight - (float) bounds.getMinX(); + break; + default: + pageHeight = boundaryBox.getHeight(); + upperBoundYPositionFromTop = pageHeight - (float) bounds.getMaxY(); + lowerBoundYPositionFromTop = pageHeight - (float) bounds.getMinY(); + break; + } + + // new maximum ? + if (lowerBoundYPositionFromTop > maxPathRelatedYPositionFromTop) { + // Is the rectangle (at least partly) located above the footer line? + // (effective page height := page height - footer line) + if (upperBoundYPositionFromTop <= effectivePageHeight) { + // yes: update current end of path-related page content + maxPathRelatedYPositionFromTop = lowerBoundYPositionFromTop; + logger_.trace("New max path related y position (from top): " + maxPathRelatedYPositionFromTop); + } else { + // no: rectangle is fully located below the footer line -> ignore + logger_.trace("Ignoring path bound below the footer line."); + } + } + } + } protected void processOperator(PDFOperator operator, List arguments) throws IOException { - //logger_.debug("operator = " + operator); - - super.processOperator(operator, arguments); +// logger_.debug("operator = " + operator); + super.processOperator(operator, arguments); } // exthex @@ -111,7 +256,7 @@ public class PDFPage extends PDFTextStripper * is used to calculate the latest position of a text in the page. Sorry for * this missinterpretation of the method, but it is the only way to do this * (provided by PDFBox)!!! - * + * * @param text * the character to be displayed -> calculate there y position. */ @@ -119,7 +264,7 @@ public class PDFPage extends PDFTextStripper { float current_y = text.getY(); final String character = text.getCharacter(); - + int pageRotation = page.findRotation(); //logger_.debug("PageRotation = " + pageRotation); if (pageRotation == 0) @@ -146,7 +291,7 @@ public class PDFPage extends PDFTextStripper //logger_.debug("character is below footer_line. footer_line = " + this.footer_line + ", text.character=" + character + ", y=" + current_y); return; } - + // store ypos of the char if it is not empty if (!character.equals(" ") && current_y > this.max_character_ypos) { @@ -160,26 +305,18 @@ public class PDFPage extends PDFTextStripper // logger_.debug(new String(string)); // } - /** - * Returns the calculated page length. - * - * @return the max page length value - */ - public float getMaxPageLength() - { - float max_ypos = Float.NEGATIVE_INFINITY; - - if (this.max_character_ypos > this.max_image_ypos) - { - max_ypos = this.max_character_ypos; - } - else - { - max_ypos = this.max_image_ypos; - } - - return max_ypos; - } + /** + * Returns the calculated page length. + * + * @return the max page length value + */ + public float getMaxPageLength() { + if (logger_.isDebugEnabled()) { + logger_.debug("Determining page content length: text=" + max_character_ypos + ", image=" + max_image_ypos + + ", path=" + maxPathRelatedYPositionFromTop); + } + return NumberUtils.max(max_character_ypos, max_image_ypos, maxPathRelatedYPositionFromTop); + } public class MyInvoke extends OperatorProcessor { @@ -192,26 +329,26 @@ public class PDFPage extends PDFTextStripper Map xobjects = context.getXObjects(); PDXObject xobject = (PDXObject) xobjects.get(name.getName()); - + PDStream stream = xobject.getPDStream(); COSStream cos_stream = stream.getStream(); - + COSName subtype = (COSName) cos_stream.getDictionaryObject(COSName.SUBTYPE); if (subtype.equals(COSName.IMAGE)) { logger_.debug("XObject Image"); - + Matrix ctm = context.getGraphicsState().getCurrentTransformationMatrix(); logger_.debug("ctm = " + ctm); - + Pos [] coordinates = new Pos [] { new Pos(0, 0, 1), new Pos(1, 0, 1), new Pos(0, 1, 1), new Pos(1, 1, 1) }; - + Pos [] transformed_coordinates = transtormCoordinates(coordinates, ctm); - + /********************************************************** * pdf-as fix: * calculating min and max point of an image to look where @@ -219,10 +356,10 @@ public class PDFPage extends PDFTextStripper * fix solves problems with footer and images and * placement of the signature in an image only pdf document **********************************************************/ - + float actual_lowest_point = Float.NaN; float actual_starting_point = Float.NaN; - + int pageRotation = page.findRotation(); logger_.debug("PageRotation = " + pageRotation); if (pageRotation == 0) @@ -231,7 +368,7 @@ public class PDFPage extends PDFTextStripper logger_.debug("min_y = " + min_y); float page_height = page.findMediaBox().getHeight(); logger_.debug("page_height = " + page_height); - + actual_lowest_point = page_height - min_y; actual_starting_point = page_height - findMaxY(transformed_coordinates); } @@ -243,7 +380,7 @@ public class PDFPage extends PDFTextStripper logger_.debug("page_width = " + page_width); actual_lowest_point = max_x; - actual_starting_point = findMinX(transformed_coordinates); + actual_starting_point = findMinX(transformed_coordinates); } if (pageRotation == 180) { @@ -257,17 +394,17 @@ public class PDFPage extends PDFTextStripper { float min_x = findMinX(transformed_coordinates); logger_.debug("min_x = " + min_x); - + float page_width = page.findMediaBox().getWidth(); logger_.debug("page_width = " + page_width); - + actual_lowest_point = page_width - min_x; - actual_starting_point = page_width - findMaxX(transformed_coordinates); + actual_starting_point = page_width - findMaxX(transformed_coordinates); } - + logger_.debug("actual_lowest_point = " + actual_lowest_point); - + if (actual_lowest_point > PDFPage.this.effectivePageHeight && actual_starting_point > PDFPage.this.effectivePageHeight) { logger_.debug("image is below footer_line"); @@ -278,7 +415,7 @@ public class PDFPage extends PDFTextStripper { PDFPage.this.max_image_ypos = actual_lowest_point; } - + return; } @@ -297,7 +434,7 @@ public class PDFPage extends PDFTextStripper } } } - + public static Pos [] transtormCoordinates (Pos [] coordinates, Matrix m) { Pos [] transformed = new Pos [coordinates.length]; @@ -307,18 +444,18 @@ public class PDFPage extends PDFTextStripper } return transformed; } - + public static Pos transtormCoordinate (Pos pos, Matrix m) { Pos transformed = new Pos(); transformed.x = pos.x * m.getValue(0, 0) + pos.y * m.getValue(1, 0) + pos.z * m.getValue(2, 0); transformed.y = pos.x * m.getValue(0, 1) + pos.y * m.getValue(1, 1) + pos.z * m.getValue(2, 1); transformed.z = pos.x * m.getValue(0, 2) + pos.y * m.getValue(1, 2) + pos.z * m.getValue(2, 2); - + logger_.debug(" transformed " + pos + " --> " + transformed); return transformed; } - + public static float findMinY (Pos [] coordinates) { float min = Float.POSITIVE_INFINITY; @@ -331,7 +468,7 @@ public class PDFPage extends PDFTextStripper } return min; } - + public static float findMaxY(Pos[] coordinates) { float max = 0; for (int i = 0; i < coordinates.length; i++) { @@ -341,7 +478,7 @@ public class PDFPage extends PDFTextStripper } return max; } - + public static float findMaxX (Pos [] coordinates) { float max = Float.NEGATIVE_INFINITY; diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFSignatureObjectIText.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFSignatureObjectIText.java index a8a150e..3b9909f 100644 --- a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFSignatureObjectIText.java +++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFSignatureObjectIText.java @@ -35,6 +35,7 @@ import org.apache.log4j.Level; import org.apache.log4j.Logger; import at.gv.egiz.pdfas.exceptions.ErrorCode; +import at.gv.egiz.pdfas.utils.PDFASUtils; import at.knowcenter.wag.egov.egiz.cfg.ConfigLogger; import at.knowcenter.wag.egov.egiz.cfg.SettingsReader; import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException; @@ -59,7 +60,7 @@ import com.lowagie.text.pdf.SubsetLocal; * This class is the IText implementation of the PDFSignatureObject interface. * The class takes an abstract definition of a signature object and convert them * into a pdf table that is used to sign a pdf document. - * + * * @author wlackner * @see at.knowcenter.wag.egov.egiz.sig.SignatureObject * @see at.knowcenter.wag.egov.egiz.table.Table @@ -76,8 +77,6 @@ public class PDFSignatureObjectIText implements PDFSignatureObject // Also fixed a minor bug which prevented proper style inheritment (Bug Nr. #534). // 04.11.2010 changed by exthex - allow setting separate hAlign and vAlign for image cells analog to value cells. - private static final String SIG_PDFA1_B_VALID = "SIG_PDFA1B_VALID"; - /** * The default font definition */ @@ -116,7 +115,7 @@ public class PDFSignatureObjectIText implements PDFSignatureObject /** * The empty constructor. It loads the ui definitions from signature tables * and init the align map. - * + * * @throws PDFDocumentException */ public PDFSignatureObjectIText() throws PDFDocumentException @@ -127,7 +126,7 @@ public class PDFSignatureObjectIText implements PDFSignatureObject /** * load the class settings - * + * * @throws PDFDocumentException * @see SettingsReader */ @@ -174,7 +173,7 @@ public class PDFSignatureObjectIText implements PDFSignatureObject /** * Set the abstract signature definition. - * + * * @param signatorObject * the abstract signator object * @see at.knowcenter.wag.egov.egiz.pdf.PDFSignatureObject#setSignatorObject(at.knowcenter.wag.egov.egiz.sig.SignatureObject) @@ -186,7 +185,7 @@ public class PDFSignatureObjectIText implements PDFSignatureObject /** * This method maps the table cell definitions to the pdfCell element. - * + * * @param pdfCell * the pdf cell to be styled * @param cellStyle @@ -226,7 +225,7 @@ public class PDFSignatureObjectIText implements PDFSignatureObject align = ((Integer) alignMap_.get(cellStyle.getVAlign())).intValue(); if (align != -1) pdfCell.setVerticalAlignment(align); - + align = -1; if (type == Entry.TYPE_VALUE && cellStyle.getValueHAlign() != null) align = ((Integer) alignMap_.get(cellStyle.getValueHAlign())).intValue(); @@ -242,7 +241,7 @@ public class PDFSignatureObjectIText implements PDFSignatureObject /** * This method maps the cell font definition to the iText Font Object - * + * * @param fontString * @return the corresponding iText Font Object * @see com.lowagie.text.Font @@ -277,12 +276,12 @@ public class PDFSignatureObjectIText implements PDFSignatureObject int face = ((Integer) font_face).intValue(); float height = Float.parseFloat(font_arr[1]); int weight = ((Integer) font_weight).intValue(); - + font = new Font(face, height, weight); fontMap_.put(fontString, font); return font; } - + /** * Creates a custom * @param fontString @@ -305,15 +304,15 @@ public class PDFSignatureObjectIText implements PDFSignatureObject } } logger_.debug("TrueType Font detected:"+fontName +" ("+fontSize+")"); - + try { Font font = (Font) fontMap_.get(fontString); - + if (font == null) { logger_.debug("Font \"" + fontString + "\" not in cache. Instantiating font."); String fontPath = SettingsReader.RESOURCES_PATH + "fonts" + File.separator + fontName; logger_.debug("Instantiating \"" + fontPath + "\"."); - + font = new Font(BaseFont.createFont(fontPath, BaseFont.WINANSI, true), fontSize); fontMap_.put(fontString, font); } @@ -334,7 +333,7 @@ public class PDFSignatureObjectIText implements PDFSignatureObject ** PDFbox has serious problems with documents that use incremental updates or * XObject forms. Therefor use this to remove incremental updates and create a * streamlined document. *
- * + * ** Note that this has nothing to do with text normalization. It just unifies * the PDF documents that are fed into PDFbox for text extraction and page * length determination. *
- * + * * @param input_pdf * The input pdf to be normalized. * @return Returns the normalized pdf. * @throws IOException * @throws DocumentException - * @throws PDFDocumentException + * @throws PDFDocumentException */ public static byte[] normalizePDF(PdfDataSource pdfDataSource) throws IOException, DocumentException, PDFDocumentException { //iText - byte [] pdf_data = pdfDataSource.getAsByteArray(); - PdfReader reader = new PdfReader(pdf_data); - PDFASUtils.checkReaderPermissions(reader); - //input_pdf.close(); - + PdfReader reader = PDFASUtils.createPdfReaderCheckingPermissions(pdfDataSource); + // PERF: PDF Normalization needs byte array ByteArrayOutputStream baos = new ByteArrayOutputStream(); // For some reason the Reader -> ImportPage -> Writer mechanism produces diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/PathConstructionOperatorProcessor.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/PathConstructionOperatorProcessor.java new file mode 100644 index 0000000..143a6b6 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/PathConstructionOperatorProcessor.java @@ -0,0 +1,62 @@ +/** + *h S
.
+ *
+ * @see "PDF 1.7 specification, Section 8.5.3 'Path-Painting Operators'"
+ * @author PdfBox, modified by Datentechnik Innovation GmbH
+ */
+public class CloseAndStrokePath extends PathPaintingOperatorProcessor {
+
+ private Log log = LogFactory.getLog(getClass());
+
+ public CloseAndStrokePath(PDFPage context) {
+ super(context);
+ }
+
+ @Override
+ public void process(PDFOperator operator, List operands) throws IOException {
+ if (log.isTraceEnabled()) {
+ log.trace("Closing and stroking path.");
+ }
+ context.processOperator("h", operands);
+ context.processOperator("S", operands);
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/painting/CloseFillEvenOddAndStrokePath.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/painting/CloseFillEvenOddAndStrokePath.java
new file mode 100644
index 0000000..6a84cf4
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/painting/CloseFillEvenOddAndStrokePath.java
@@ -0,0 +1,60 @@
+/**
+ * h B*
.
+ *
+ * @see "PDF 1.7 specification, Section 8.5.3 'Path-Painting Operators'"
+ * @author PdfBox, modified by Datentechnik Innovation GmbH
+ */
+public class CloseFillEvenOddAndStrokePath extends PathPaintingOperatorProcessor {
+
+ private Log log = LogFactory.getLog(getClass());
+
+ public CloseFillEvenOddAndStrokePath(PDFPage context) {
+ super(context);
+ }
+
+ @Override
+ public void process(PDFOperator operator, List operands) throws IOException {
+ if (log.isTraceEnabled()) {
+ log.trace("Closing, filling (even odd rule) and stroking path.");
+ }
+ context.processOperator("h", operands);
+ context.processOperator("B*", operands);
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/painting/CloseFillNonZeroAndStrokePath.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/painting/CloseFillNonZeroAndStrokePath.java
new file mode 100644
index 0000000..f8db567
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/painting/CloseFillNonZeroAndStrokePath.java
@@ -0,0 +1,60 @@
+/**
+ * h B
.
+ *
+ * @see "PDF 1.7 specification, Section 8.5.3 'Path-Painting Operators'"
+ * @author PdfBox, modified by Datentechnik Innovation GmbH
+ */
+public class CloseFillNonZeroAndStrokePath extends PathPaintingOperatorProcessor {
+
+ private Log log = LogFactory.getLog(getClass());
+
+ public CloseFillNonZeroAndStrokePath(PDFPage context) {
+ super(context);
+ }
+
+ @Override
+ public void process(PDFOperator operator, List operands) throws IOException {
+ if (log.isTraceEnabled()) {
+ log.trace("Closing, filling (non zero rule) and stroking path.");
+ }
+ context.processOperator("h", operands);
+ context.processOperator("B", operands);
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/painting/EndPath.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/painting/EndPath.java
new file mode 100644
index 0000000..4448a1e
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/painting/EndPath.java
@@ -0,0 +1,68 @@
+/**
+ * B
, except that the path is filled as if with f*
instead of
+ * f
.
+ *
+ * @see "PDF 1.7 specification, Section 8.5.3 'Path-Painting Operators'"
+ * @author PdfBox, modified by Datentechnik Innovation GmbH
+ */
+public class FillEvenOddAndStrokePath extends PathPaintingOperatorProcessor {
+
+ private Log log = LogFactory.getLog(getClass());
+
+ public FillEvenOddAndStrokePath(PDFPage context) {
+ super(context);
+ }
+
+ @Override
+ public void process(PDFOperator operator, List operands) throws IOException {
+ try {
+ PDFPage pdfPage = (PDFPage) context;
+
+ if (log.isTraceEnabled()) {
+ log.trace("Filling (even odd rule) and stroking path.");
+ }
+
+ GeneralPath currentPath = (GeneralPath) pdfPage.getCurrentPath().clone();
+ context.processOperator("f*", operands);
+ pdfPage.setCurrentPath(currentPath);
+ context.processOperator("S", operands);
+
+ } catch (Exception e) {
+ log.warn("Error processing operator 'B*'.", e);
+ }
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/painting/FillNonZeroAndStrokePath.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/painting/FillNonZeroAndStrokePath.java
new file mode 100644
index 0000000..96025ed
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/painting/FillNonZeroAndStrokePath.java
@@ -0,0 +1,72 @@
+/**
+ * f
and
+ * the second with S
.
+ *
+ * @see "PDF 1.7 specification, Section 8.5.3 'Path-Painting Operators'"
+ * @author PdfBox, modified by Datentechnik Innovation GmbH
+ */
+public class FillNonZeroAndStrokePath extends PathPaintingOperatorProcessor {
+
+ private Log log = LogFactory.getLog(getClass());
+
+ public FillNonZeroAndStrokePath(PDFPage context) {
+ super(context);
+ }
+
+ @Override
+ public void process(PDFOperator operator, List operands) throws IOException {
+ try {
+ PDFPage pdfPage = (PDFPage) context;
+
+ if (log.isTraceEnabled()) {
+ log.trace("Filling (non zero rule) and stroking path.");
+ }
+
+ GeneralPath currentPath = (GeneralPath) pdfPage.getCurrentPath().clone();
+ context.processOperator("f", operands);
+ pdfPage.setCurrentPath(currentPath);
+ context.processOperator("S", operands);
+
+ } catch (Exception e) {
+ log.warn("Error processing operator 'B'.", e);
+ }
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/painting/FillPathEvenOddRule.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/painting/FillPathEvenOddRule.java
new file mode 100644
index 0000000..c6417ea
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/painting/FillPathEvenOddRule.java
@@ -0,0 +1,71 @@
+/**
+ *
* This is set by the Connector so that signing Applications can use the
* returned XML values.
@@ -222,7 +222,7 @@ public class SignatureObject implements Serializable
/**
* The empty constructor. It initilize the normlizer, load the settings and
* set the default styles.
- *
+ *
* @throws SignatureException
* ErrorCode:101, 400
*/
@@ -235,7 +235,7 @@ public class SignatureObject implements Serializable
/**
* This method initialize the normalizer
- *
+ *
* @throws SignatureException
* ErrorCode:400
*/
@@ -254,7 +254,7 @@ public class SignatureObject implements Serializable
/**
* This method load the signature definitions
- *
+ *
* @throws SignatureException
* ErrorCode:101
*/
@@ -296,7 +296,7 @@ public class SignatureObject implements Serializable
/**
* Dummy getter Method for debugging only
- *
+ *
* @return response string
*/
public String getSigResponse()
@@ -306,7 +306,7 @@ public class SignatureObject implements Serializable
/**
* Dummy setter Method for debugging only
- *
+ *
* @param sigRespone
* store the response string
*/
@@ -317,7 +317,7 @@ public class SignatureObject implements Serializable
/**
* This method set the signature type.
- *
+ *
* @param sigType
* the signature type to be set
* @throws SignatureTypesException
@@ -331,7 +331,7 @@ public class SignatureObject implements Serializable
/**
* Returns the default signation type
- *
+ *
* @return the key for the default signature definition, if the key is not
* found it returns null
*/
@@ -343,7 +343,7 @@ public class SignatureObject implements Serializable
/**
* This method checks if a given signature key is realy a defined signature
* key.
- *
+ *
* @param sigKey
* the key to check
* @return true if the key is correct, false if the given key is not defined
@@ -360,7 +360,7 @@ public class SignatureObject implements Serializable
* The value that has to be set would be normalized!
* If the key equals to SIG_VALUE
all whitespaces are
* removed!
- *
+ *
* @param key
* the key to be set
* @param value
@@ -371,7 +371,7 @@ public class SignatureObject implements Serializable
public boolean setSigValue(String key, String value) {
return setSigValue(key, value, false);
}
-
+
public boolean setSigValue(String key, String value, boolean placeholder)
{
SignatureEntry sig_entry = null;
@@ -416,7 +416,7 @@ public class SignatureObject implements Serializable
/**
* Set the value and the caption to given key.
- *
+ *
* @param key
* the key of the signature object
* @param value
@@ -435,14 +435,14 @@ public class SignatureObject implements Serializable
* This method returns a value for a given signature key. If the key equals to
* SIG_NORM
and the value is null
the version
* string of the current normalizer is returned!
- *
+ *
* @param key
* the key to get the value for
* @return a value for the given key
*/
public String getSigValue(String key)
{
-
+
String value = null;
SignatureEntry sigEntry = null;
if (sigEntries_.containsKey(key))
@@ -462,13 +462,13 @@ public class SignatureObject implements Serializable
logger_.debug("Using override property for key '" + key + "' = " + value);
}
}
-
+
return value;
}
/**
* Sets the "Kennzeichnung".
- *
+ *
* @param kz
* The "Kennzeichnung" to be set.
*/
@@ -479,7 +479,7 @@ public class SignatureObject implements Serializable
/**
* Returns the "Kennzeichnung" of this signature.
- *
+ *
* @return Returns the "Kennzeichnung" of this signature. Returns null if
* there is no "Kennzeichnung" or it is not recognized by this
* application.
@@ -508,14 +508,14 @@ public class SignatureObject implements Serializable
* and the coresponding value is null
the key itself is
* returned as caption! If the key does not exist the method returns
* null
.
- *
+ *
* @param key
* the key to get the caption for
* @return a caption for the given key
*/
private String getSigCaption(String key)
{
-
+
String caption = null;
if (sigEntries_.containsKey(key))
{
@@ -667,15 +667,15 @@ public class SignatureObject implements Serializable
if (StringUtils.equals(nameFromText, nameFromCertificate)) {
return nameFromText;
}
-
+
logger_.debug("Checking RFC2253 name.");
-
+
// if we do not have a name from certificate just return the name from text
if (nameFromCertificate == null) {
logger_.debug("No certificate RFC2253 name provided. Applying less sophisticated workaround (does not cover all cases) without certificate usage.");
return prepareRFC2253Name(nameFromText);
}
-
+
// no name from text extraction available, just return name from certificate
if (nameFromText == null) {
logger_.debug("No extracted/reconstructed name available. Just returning the name from certificate: \"" + nameFromCertificate + "\".");
@@ -762,13 +762,13 @@ public class SignatureObject implements Serializable
result.append(rdnVP.getValue());
} else {
// no BER encoding -> take value from certificate
- // also take RDN from certificate if possible
+ // also take RDN from certificate if possible
String certValue = values[values.length - 1 - i].getAVA()
.getValueAsString();
String rdn = resolveRDN(nameFromCertificate, certValue, rdnVP.getRdn());
result.append(rdn + "=").append(certValue);
}
-
+
}
String merged = result.toString();
if (logger_.isDebugEnabled()) {
@@ -785,15 +785,15 @@ public class SignatureObject implements Serializable
}
return merged;
}
-
+
/**
* This method tries to resolve the RDN corresponding to a given value from the certificate String.
- * As values might occur multiple times for different RDNs, an unambiguous resolving cannot be assured.
+ * As values might occur multiple times for different RDNs, an unambiguous resolving cannot be assured.
* In case of ambiguity, the RDN extracted from text is returned by default.
- *
+ *
* This method is a bug fix for a problem that caused the verification of ZID documents to fail as the RDN
* from the extracted text ("EMAILADDRESS") was different to the RDN in the certificate ("EMAIL")
- *
+ *
* @param certString
* The String obtained from the certificate
* @param value
@@ -804,42 +804,42 @@ public class SignatureObject implements Serializable
* The resolved RDN from the certificate, or the RDN from text extraction
*/
private static String resolveRDN(String certString, String value, String extractedRDN) {
-
+
if (!certString.contains(value)) {
-
+
// given value cannot be found in certificate string
return extractedRDN;
}
-
+
if (certString.indexOf(value) != certString.lastIndexOf(value)) {
-
+
// given value is ambiguous - cannot resolve RDN from certificate string
return extractedRDN;
}
-
+
String[] parts = certString.split(",|;");
String val = value.trim();
-
+
for (int i = 0; i < parts.length; i++) {
-
+
String part = parts[i].trim();
-
+
if (part.endsWith(val)) {
-
+
// found entry - extract RDN
- String[] components = part.split("=");
+ String[] components = part.split("=");
if (components.length != 2) {
// unexpected format - return default
- return extractedRDN;
- }
+ return extractedRDN;
+ }
String rdn = components[0].trim();
- return rdn;
- }
- }
+ return rdn;
+ }
+ }
// default
return extractedRDN;
}
-
+
/**
* @return Returns the SignationIssuer.
*/
@@ -920,10 +920,10 @@ public class SignatureObject implements Serializable
}
// dferbas baik
-
+
/**
* signature algorithm if embedded
- * @param sigAlg
+ * @param sigAlg
*/
public void setSigAlg(String sigAlg)
{
@@ -937,7 +937,7 @@ public class SignatureObject implements Serializable
public String getSigAlg()
{
return getSigValue(SignatureTypes.SIG_ALG);
- }
+ }
/**
* @param certDigest
@@ -1016,7 +1016,7 @@ public class SignatureObject implements Serializable
setSigValue(SIG_CER, x509Certificate);
storeCertificate(getSignationSerialNumber(), getSignationIssuer(), x509Certificate);
}
-
+
public void setX509Certificate(X509Certificate cert)
{
try
@@ -1037,7 +1037,7 @@ public class SignatureObject implements Serializable
/**
* return the 509v3 certificate of the given serialNumber and the given issuer
* string
- *
+ *
* @param serialNumber
* the serialNumber which the certificates should load
* @param issuer
@@ -1070,7 +1070,7 @@ public class SignatureObject implements Serializable
/**
* Set the signation id's build by a BKU signated SignatureObject.
- *
+ *
* @param sigIds
* the string to store.
*/
@@ -1152,7 +1152,7 @@ public class SignatureObject implements Serializable
String productVersion = response_properties.getProperty("productVersion");
logger_.debug("productVersion = " + productVersion);
- boolean new_etsi = decideNewEtsiByBKUVersion(productVersion);
+ boolean new_etsi = decideNewEtsiByBKUVersion(productVersion);
logger_.debug("verwende neue etsi properties = " + new_etsi);
String etsi_prefix = "";
@@ -1183,7 +1183,7 @@ public class SignatureObject implements Serializable
/**
* Checks if the current SignatureObject is siganted by MOA. It checks if the
* current SignatureObject has a signation id value.
- *
+ *
* @return true if no signation id value is found, false otherwise
*/
public boolean isMOASigned()
@@ -1204,7 +1204,7 @@ public class SignatureObject implements Serializable
/**
* Tells if this SignatureObject is textual.
- *
+ *
* @return Returns true, if it is textual.
*/
public boolean isTextual()
@@ -1223,7 +1223,7 @@ public class SignatureObject implements Serializable
/**
* Tells, if this SignatureObject is binary.
- *
+ *
* @return Returns true, if it is binary.
*/
public boolean isBinary()
@@ -1237,14 +1237,14 @@ public class SignatureObject implements Serializable
{
logger_.error(e.getMessage(), e);
}
-
+
return SigKZIDHelper.isBinary(kz);
}
/**
* Takes the signation id value of the current SignatureObject and split them
* into the corresponding id array added with the id-base.
- *
+ *
* @return the id array
*/
// TODO hotifx
@@ -1328,7 +1328,7 @@ public class SignatureObject implements Serializable
real_ids[3] = "0-" + base + "-" + ids[3];
real_ids[4] = "0-" + base + "-" + ids[4];
real_ids[5] = etsi_string;
-
+
if (logger_.isDebugEnabled())
{
for (int id_idx = 0; id_idx < real_ids.length; id_idx++)
@@ -1345,7 +1345,7 @@ public class SignatureObject implements Serializable
* for equition. Used to store and find corresponting certificates.
* Normalzing: normalizing the string using the normalizer, remove all white
* spaces, encode as base64 and replace all "/" chars with "_".
- *
+ *
* @param issuer
* the issuer string to normalize
* @return the normalized issuer string
@@ -1357,7 +1357,7 @@ public class SignatureObject implements Serializable
{
if (issuer != null)
{
- // use explicit method for normalization
+ // use explicit method for normalization
issuer = normalizeIssuer(issuer);
/* this block may be used to enhance normalization (tknall)
try {
@@ -1375,7 +1375,6 @@ public class SignatureObject implements Serializable
}
catch (UnsupportedEncodingException e)
{
- e.printStackTrace();
throw new RuntimeException(e);
}
}
@@ -1443,7 +1442,7 @@ public class SignatureObject implements Serializable
}
}
}
-
+
private X509Cert loadCertificateFromCertstore(String serialNumber, String issuer) {
String iss_hash = getIssuerFileHash(issuer);
String cert_store_path = certPath_ + iss_hash;
@@ -1476,10 +1475,10 @@ public class SignatureObject implements Serializable
*
.txt
extension to get the meta information of
* the certificate@
char.
- *
+ *
* @param serialNumber
* the file name of the certificate .der|.txt
* @param issuer
@@ -1541,7 +1540,7 @@ public class SignatureObject implements Serializable
/**
* Writes the certificate data to a file and stores the file in the local
* certificate store.
- *
+ *
* @param cert_data
* The binary certificate data.
*/
@@ -1580,17 +1579,17 @@ public class SignatureObject implements Serializable
/**
* Connects to the LDAP server to look for the certificate.
- *
+ *
* @param serialNumber
* The serial number String of the certificate being sought. E.g.
* "123455676744123432".
* @param issuer
* The issuer String of the certificate being sought.
- *
+ *
* @return Returns the DER certificate file as can be stored in the local
* repository. Returns null, if the document wasn't found on the
* server.
- * @throws ClassNotFoundException
+ * @throws ClassNotFoundException
*/
protected byte[] loadCertificateFromLDAP(String serialNumber, String issuer) {
// START modification by TK
@@ -1629,10 +1628,10 @@ public class SignatureObject implements Serializable
* .txt
extension to get the meta information of
* the certificate@
char.
- *
+ *
* @param serialNumber
* the file name of the certificate .der|.txt
* @param issuer
@@ -1650,7 +1649,7 @@ public class SignatureObject implements Serializable
{
return storeCertificate(serialNumber, issuer, x509Certificate);
}
-
+
/**
* This method stores a X509v3 certificate to the filesystem. The reference to
* the stored certificate is build by the serialNumber and the issuer string.
@@ -1673,10 +1672,10 @@ public class SignatureObject implements Serializable
* .txt
extension to get the meta information of
* the certificate@
char.
- *
+ *
* @param serialNumber
* the file name of the certificate .der|.txt
* @param issuer
@@ -1723,7 +1722,7 @@ public class SignatureObject implements Serializable
}
return store_complete;
}
-
+
/**
* @return Returns the AbstractTable.
* @see at.knowcenter.wag.egov.egiz.table.Table
@@ -1739,7 +1738,7 @@ public class SignatureObject implements Serializable
/**
* This method read the style definitions from the settings file.
- *
+ *
* @param styleKey
* the key to read the style definitions
* @return the defined style informations
@@ -1762,7 +1761,7 @@ public class SignatureObject implements Serializable
* This method creates an abstract signature table object. It takes all keys
* and values set by the signature object to create the corresponding abstract
* table object. The table definition is read from the settings file.
- *
+ *
* @param tableKey
* is the name of the table definition in the settings file
* @return a new abstract signature table
@@ -1964,7 +1963,7 @@ public class SignatureObject implements Serializable
/**
* This method returns a signature entry object.
- *
+ *
* @param key
* the corresponding key
* @return the signature entry object of the given key, null if the key does
@@ -1977,7 +1976,7 @@ public class SignatureObject implements Serializable
/**
* This method is a helper function to remove all white spaces from a text.
- *
+ *
* @param text
* the white spaces should remove from
* @return a text without white spaces
@@ -1993,7 +1992,7 @@ public class SignatureObject implements Serializable
}
/**
- *
+ *
* @param placeholder
* @return Returns the list of SignatureFieldDefinitions that's values in the
* SignatureObject have been filled out with placeholders.
@@ -2015,7 +2014,7 @@ public class SignatureObject implements Serializable
setValueBruteForce(SignatureTypes.SIG_ID, null);
continue;
}
-
+
if (sfd.field_name.equals(SignatureTypes.SIG_ALG) && !baikEnabled) {
setValueBruteForce(SignatureTypes.SIG_ID, null);
continue;
@@ -2040,7 +2039,7 @@ public class SignatureObject implements Serializable
/**
* Returns the raw signature response XML string as set by the signing
* Connector.
- *
+ *
* @return Returns the XML response String.
*/
public String getRawSignatureResponse()
@@ -2050,12 +2049,12 @@ public class SignatureObject implements Serializable
/**
* Sets the raw signature response XML string.
- *
+ *
* * This should be used by the Connector to pass the response String to the * signer. *
- * + * * @param raw_response_string * The new raw signature response string. */ @@ -2063,8 +2062,8 @@ public class SignatureObject implements Serializable { this.raw_signature_response = raw_response_string; } - - + + /** * get timestamp if available diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureTypes.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureTypes.java index 783512c..a4d71fd 100644 --- a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureTypes.java +++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureTypes.java @@ -26,7 +26,9 @@ package at.knowcenter.wag.egov.egiz.sig; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -45,6 +47,118 @@ import at.knowcenter.wag.exactparser.ByteArrayUtils; public class SignatureTypes { + /** + * Defines all supported states for {@link SignatureTypes} (signature profiles). Signature types can be enabled + * ("on"), can be set to support signature only ("sign_only"), to verification only ("verify_only") or can be + * disabled ("off" or any other value not covered by other enum values). + * + * @author Datentechnik Innovation GmbH + */ + public enum State { + + /** + * Enables a signature profile. + */ + ON ("on", "yes", "true", "enabled"), + + /** + * Disables a signature profile. + */ + OFF (), + + /** + * Restricts the signature profile so that is can only be used for verification purposes and not for signature. + */ + VERIFY_ONLY ("verify_only", "verify-only", "verifyonly", "verify only", "verify"), + + /** + * Allows the signature profile to be used for signature but not for verification. + */ + SIGN_ONLY ("sign_only", "sign-only", "signonly", "sign only", "sign"); + + /** + * Sets the default state when no valid value was provided. + */ + private static final State DEFAULT = OFF; + + /** + * States that allow signatures. + */ + private static final State[] CAN_SIGN = { ON, SIGN_ONLY }; + + /** + * States that allow verification. + */ + private static final State[] CAN_VERIFY = { ON, VERIFY_ONLY }; + + private String[] keyWords; + + private State(String... keyWords) { + this.keyWords = keyWords; + } + + /** + * Returns a valid State from a given {@code keyWord}. If the {@code keyWord} cannot be matched to a certain + * state, the default State {@link #OFF} is returned. + * + * @param keyWord + * A valid keyword like "on", "sign_only"... + * @return The enum State. + */ + public static State fromString(String keyWord) { + if (keyWord == null) { + return DEFAULT; + } + try { + return valueOf(keyWord.toUpperCase()); + } catch (IllegalArgumentException e) { + for (State candidate : values()) { + for (String candidateKeyWord : candidate.keyWords) { + if (keyWord.equalsIgnoreCase(candidateKeyWord)) { + return candidate; + } + } + } + return DEFAULT; + } + } + + /** + * Returns {@code true} when the current state is one of the given candidate {@code states}. + * + * @param states + * The candidate states. + * @return {@code true} when the current state is one of the given candidate states, {@code false} if not. + */ + public boolean in(State... states) { + if (states != null) { + for (State state : states) { + if (this == state) { + return true; + } + } + } + return false; + } + + /** + * Returns if the respective state allows signatures. + * @return {@code true} if signatures are allowed, {@code false} if not. + */ + public boolean canSign() { + return in(CAN_SIGN); + } + + /** + * Returns if the respective state allows verification. + * @return {@code true} if verification is allowed, {@code false} if not. + */ + public boolean canVerify() { + return in(CAN_VERIFY); + } + + } + // 03.11.2010 changed by exthex - commented unneeded setDefaultStyles method to reduce confusion /** @@ -70,8 +184,8 @@ public class SignatureTypes /** * The state value activating an signature definition */ - private static final String STATE_ON = "on"; - +// public static final String STATE_ON = "on"; + // /** // * The state value de activating an signature definition // */ @@ -403,10 +517,12 @@ public class SignatureTypes if (settings_ != null) { ArrayList types = settings_.getKeys(TYPES); - for (int type_idx = 0; type_idx < types.size(); type_idx++) - { - String type = (String) types.get(type_idx); - addSignatureType(type); + if (types != null) { + for (int type_idx = 0; type_idx < types.size(); type_idx++) + { + String type = (String) types.get(type_idx); + addSignatureType(type); + } } } } @@ -420,8 +536,9 @@ public class SignatureTypes * @param typeName */ public void addSignatureType(String typeName) { - - if (STATE_ON.equals(settings_.getSetting(TYPES + "." + typeName, null))) + +// if (STATE_ON.equals(settings_.getSetting(TYPES + "." + typeName, null))) + if (State.fromString(settings_.getSetting(TYPES + "." + typeName, null)) != State.OFF) { SignatureTypeDefinition sig_type_def; try @@ -446,6 +563,23 @@ public class SignatureTypes return this.typeDefMap_.keySet(); } + /** + * Returns a set of identifiers for profiles than can be used for signature, i.e. profiles that are either enabled + * ("on") or set to "sign_only"). + * + * @return A set of signature profile/type identifiers. + */ + @SuppressWarnings("unchecked") + public Set* All settings keys will be prefixed by this type. So to reuse the BKU * connector, a deriving class has to implement this method specifying an own * type. *
- * + * * @return Returns the type of this BKU-like connector. */ protected String getType() diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/MOAConnector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/MOAConnector.java index ef355a0..d413a29 100644 --- a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/MOAConnector.java +++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/MOAConnector.java @@ -63,7 +63,7 @@ import at.knowcenter.wag.egov.egiz.tools.CodingHelper; /** * Connector to access the MOA service. - * + * * @deprecated * @author wlackner * @author wprinz @@ -72,7 +72,7 @@ public class MOAConnector implements Connector { /** * ConnectorInformation that identifies this Connector to the system. - * + * * @see at.knowcenter.wag.egov.egiz.sig.ConnectorFactory * @see ConnectorInformation */ @@ -80,7 +80,7 @@ public class MOAConnector implements Connector /** * The class type value. - * + * ** Just for convenience. *
@@ -122,7 +122,7 @@ public class MOAConnector implements Connector /** * load the inital signature settings - * + * * @see SettingsReader */ private void loadSettings() throws SignatureException @@ -148,7 +148,7 @@ public class MOAConnector implements Connector * SignatureObject is filled out by the parsed MOA-Response.* The data is Base64 encoded. If the mime-type suggests that the data is * binary, it is Base64 encoded for a second time. *
- * + * * @param data * The data to be converted to a valid Base64 content. * @return Returns the Base64 content. */ public static String prepareBase64Content(SignatureData data) { - // PERF: base64 encoding needs byte array + // PERF: base64 encoding needs byte array byte [] d = DataSourceHelper.convertDataSourceToByteArray(data.getDataSource()); - + String base64 = CodingHelper.encodeBase64(d); if (data.getMimeType().equals("application/pdf")) //$NON-NLS-1$ { @@ -105,7 +105,7 @@ public final class BKUHelper ** This is useful for building the hash. *
- * + * * @param data * The data to be prepared. * @return Returns the prepared data. @@ -114,7 +114,7 @@ public final class BKUHelper { // PERF: prepareEnvelopingData needs byte array byte[] enc = DataSourceHelper.convertDataSourceToByteArray(data.getDataSource()); - + if (data.getMimeType().equals("application/pdf")) //$NON-NLS-1$ { log.debug("The data is application/pdf - so the binary data is Base64 encoded."); //$NON-NLS-1$ @@ -125,7 +125,6 @@ public final class BKUHelper } catch (UnsupportedEncodingException e) { - e.printStackTrace(); throw new RuntimeException("Very Strange: US-ASCII encoding not supported???", e); //$NON-NLS-1$ } } @@ -135,7 +134,7 @@ public final class BKUHelper /** * Checks the response xml for an error description and if found throws an * appropriate exception. - * + * * @param response_string * The response xml. * @throws ConnectorException @@ -169,29 +168,29 @@ public final class BKUHelper throw new ExternalErrorException(error_code, error_mess); } log.debug("No error found. Assuring that CreateXMLSignatureResponse or VerifyXMLSignatureResponse elements are available."); - + // assure that a CreateXMLSignatureResponse or a VerifyXMLSignatureResponse is available Matcher slMatcher = ALLOWED_SL_RESPONSE_PATTERN.matcher(response_string); if (!slMatcher.matches()) { throw new ConnectorException(ErrorCode.UNABLE_TO_RECEIVE_SUITABLE_RESPONSE, "No suitable response received: " + response_string); } - + } /** * This method parses the BKU-Response string. - * + * ** It separates the SignatureValue, X509IssuerName, SigningTime, * X509SerialNumber, X509Certificate, CertDigest, DigestValue and the * signation id-s. If the X509Certificate is extracted it would be stored in * the certificates directory. *
- * + * * @param xmlResponse * The response string. * @return Returns the parsed signature object holding the data. - * + * * @throws ConnectorException * ErrorCode (303, 304) * @see SignatureObject @@ -355,7 +354,7 @@ public final class BKUHelper ids[2] = extractId(xmlResponse, "signed-data-object-"); //$NON-NLS-1$ ids[3] = extractId(xmlResponse, "etsi-data-reference-"); //$NON-NLS-1$ ids[4] = extractId(xmlResponse, "etsi-data-object-"); //$NON-NLS-1$ - + String algs = AlgorithmSuiteUtil.extractAlgorithmSuiteString(xmlResponse); SignSignatureObject so = new SignSignatureObject(); @@ -363,26 +362,26 @@ public final class BKUHelper so.issuer = iss_nam; so.signatureValue = sig_val; so.x509Certificate = cert; - + AlgorithmSuiteObject suite = new AlgorithmSuiteObject(algs, false); so.sigAlgorithm = AlgorithmMapper.getUri(suite.getSignatureMethod()); - + String defaultCertAlg = environment.getDefaultAlgForCert(cert); if (AlgorithmSuiteUtil.isDefaultCertAlg(algs, defaultCertAlg)) { // do not embed default alg algs = null; - } + } String final_ids = id_formatter.formatIds(ids, algs); so.id = final_ids; - + return so; } /** * Removes all whitespaces ("\\s") from the String. - * + * * @param str * The String. * @return The String with all whitespaces removed. @@ -394,7 +393,7 @@ public final class BKUHelper /** * This emthod extracts id-values from a text. The id is given by the name. - * + * * @param text * the id-value that should extract from * @param name @@ -411,7 +410,7 @@ public final class BKUHelper return ""; } // stop - + int start_idx = startOfName + name.length(); int end_idx = text.indexOf("\"", start_idx); //$NON-NLS-1$ @@ -430,7 +429,7 @@ public final class BKUHelper * This method parses the verify response string and return a * SignatureResponse object. The SignatureResponse object is filled out by the * response values from the BKU-response. - * + * * @param xmlResponse * the response values from the BKU-verify request * @return SignatureResponse object @@ -521,14 +520,14 @@ public final class BKUHelper if (hash_data_m_s.find() && hash_data_m_e.find()) { String hashInputData = xmlResponse.substring(hash_data_m_s.end(), hash_data_m_e.start()); - + Pattern b64_p_s = Pattern.compile("* This feature is available since BKU version 2.7.4. *
- * + * * @author wprinz */ public class DetachedBKUConnector implements Connector, LocalConnector @@ -85,12 +85,12 @@ public class DetachedBKUConnector implements Connector, LocalConnector /** * Constructor that builds the configuration environment for this connector * according to the given profile. - * + * ** If confuguration parameters are not defined on that profile, the default * parameters defined in the configuration are used. *
- * + * * @param connectorParameters * The connectot parameters. * @throws ConnectorException @@ -101,10 +101,10 @@ public class DetachedBKUConnector implements Connector, LocalConnector this.params = connectorParameters; this.environment = new Environment(this.params.getProfileId(), loc_ref_content); } - + /** * Prepares the sign request xml to be sent using the sign request template. - * + * * @param data * The SignatureData. * @return Returns the sign request xml to be sent. @@ -120,7 +120,7 @@ public class DetachedBKUConnector implements Connector, LocalConnector String sign_keybox_identifier = this.environment.getSignKeyboxIdentifier(); String mime_type = data.getMimeType(); String loc_ref_content = this.environment.getLocRefContent(); - + if (log.isDebugEnabled()) { log.debug("sign keybox identifier = " + sign_keybox_identifier); //$NON-NLS-1$ @@ -139,7 +139,7 @@ public class DetachedBKUConnector implements Connector, LocalConnector /** * Analyzes the sign response xml and extracts the signature data. - * + * * @param response_properties * The response properties containing the response String and * transport related information. @@ -155,14 +155,14 @@ public class DetachedBKUConnector implements Connector, LocalConnector String bkuIdentifier = BKUHelper.getBKUIdentifier(response_properties); log.debug("BKU identifier: " + (bkuIdentifier != null ? ("\"" + bkuIdentifier + "\"") : "n/a")); - + SignatureLayoutHandler sigLayout; try { sigLayout = SignatureLayoutHandlerFactory.getSignatureLayoutHandlerInstance(bkuIdentifier); } catch (SettingsException e) { throw new ConnectorException(e.getErrorCode(), e.getMessage()); } - + BKUHelper.checkResponseForError(response_string); SignSignatureObject so = sigLayout.parseCreateXMLSignatureResponse(response_string, this.environment); @@ -225,15 +225,15 @@ public class DetachedBKUConnector implements Connector, LocalConnector /** * Sends the request and data to the given URL. - * + * ** This method mainly handles communication exceptions. The actual send work * is done by doPostRequestMultipart. *
- * + * * @see BKUPostConnection#doPostRequestMultipart(String, String, * SignatureData) - * + * * @param url * The URL to send the request to. * @param request_string @@ -262,7 +262,7 @@ public class DetachedBKUConnector implements Connector, LocalConnector /** * Performs a sign. - * + * * @param data * The data to be signed. * @return Returns the signature object containing the signature data. @@ -289,7 +289,7 @@ public class DetachedBKUConnector implements Connector, LocalConnector /** * Performs a verification. - * + * * @param data * The data to be verified. * @param so @@ -331,7 +331,7 @@ public class DetachedBKUConnector implements Connector, LocalConnector /** * Prepares the verify request xml to be sent using the verify request * template. - * + * * @param data * The SignatureData. * @param so @@ -345,7 +345,7 @@ public class DetachedBKUConnector implements Connector, LocalConnector String verify_request_template = this.environment.getVerifyRequestTemplate(); String xml_content = null; - + if (dsigData != null && dsigData.getXmlDsig() != null) { xml_content = dsigData.getXmlDsig(); @@ -355,16 +355,18 @@ public class DetachedBKUConnector implements Connector, LocalConnector xml_content = chooseAndCreateXMLDsig(data, so); } - - - String verify_request_xml = verify_request_template.replaceFirst(TemplateReplaces.XML_CONTENT_REPLACE, xml_content); + // fixed by dti: Issuer names may contain escapted commas ("\,"). As far as replaceFirst (and replaceAll) + // methods are regarded, backslashes in the replacement string may cause the results to be different than + // if it were being treated as a literal replacement string. +// String verify_request_xml = verify_request_template.replaceFirst(TemplateReplaces.XML_CONTENT_REPLACE, xml_content); + String verify_request_xml = verify_request_template.replace(TemplateReplaces.XML_CONTENT_REPLACE, xml_content); verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.LOC_REF_CONTENT_REPLACE, this.environment.getLocRefContent()); verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.DATE_TIME_REPLACE, BKUHelper.formDateTimeElement(this.params.getVerificationTime(), "sl")); return verify_request_xml; } - - private String chooseAndCreateXMLDsig(SignatureData data, SignSignatureObject so) throws ConnectorException { + + private String chooseAndCreateXMLDsig(SignatureData data, SignSignatureObject so) throws ConnectorException { // MOA if (SigKZIDHelper.isMOASigned(so)) { @@ -379,7 +381,7 @@ public class DetachedBKUConnector implements Connector, LocalConnector log.debug("Algorithm = " + algorithmId); LocRefDetachedMOCCAConnector mocca_connector = new LocRefDetachedMOCCAConnector(this.params, "not needed here", algorithmId); return mocca_connector.prepareXMLContent(data, so); - + // ATRUST } else if (SigKZIDHelper.isATrustSigned(so)) { log.debug("ATrust signature detected"); @@ -391,20 +393,20 @@ public class DetachedBKUConnector implements Connector, LocalConnector else if (SigKZIDHelper.isBKUSigned(so)) { log.debug("TD signature signature detected."); return prepareXMLContent(data, so); - } + } // unknown else { throw new ConnectorException(ErrorCode.UNSUPPORTED_SIGNATURE, "Unsupported signature (" + so.id + ", " +so.kz + "). Please get a new version of PDF-AS. Your version is: " + PdfAS.PDFAS_VERSION); } - } + } /** * Prepares the XML content the holds the actual signature data. - * + * ** This strongly rebuilds the XML content as retuned from a sign request. *
- * + * * @param data * The data. * @param so @@ -421,13 +423,13 @@ public class DetachedBKUConnector implements Connector, LocalConnector String ids_string = so.getSigID(); String[] ids = SignatureObject.parseSigIds(ids_string); - + X509Certificate cert = so.getX509Certificate(); - + // dferbas AlgorithmSuiteObject algSuite = new AlgorithmSuiteObject(); String verify_xml = AlgorithmSuiteUtil.evaluateReplaceAlgs(algSuite, this.environment, so); - + // data digest replace { // byte[] data_value = data.getData(); @@ -457,7 +459,11 @@ public class DetachedBKUConnector implements Connector, LocalConnector verify_xml = verify_xml.replaceAll(TemplateReplaces.SIG_ID_REPLACE, ids[0]); verify_xml = verify_xml.replaceFirst(TemplateReplaces.SIGNING_TIME_REPLACE, so.getDate()); verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_CERTIFICATE_REPLACE, certDigest); - verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_ISSUER_NAME_REPLACE, so.getIssuer()); + // fixed by dti: Issuer names may contain escapted commas ("\,"). As far as replaceFirst (and replaceAll) + // methods are regarded, backslashes in the replacement string may cause the results to be different than + // if it were being treated as a literal replacement string. +// verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_ISSUER_NAME_REPLACE, so.getIssuer()); + verify_xml = verify_xml.replace(TemplateReplaces.X509_ISSUER_NAME_REPLACE, so.getIssuer()); verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_SERIAL_NUMBER_REPLACE, so.getSerialNumber()); // SigDataRefReplace already done above verify_xml = verify_xml.replaceFirst(TemplateReplaces.MIME_TYPE_REPLACE, data.getMimeType()); @@ -495,7 +501,7 @@ public class DetachedBKUConnector implements Connector, LocalConnector /** * Analyzes the verify response string. - * + * * @param response_properties * The response properties containing the response XML. * @return Returns the SignatureResponse containing the verification result. @@ -518,7 +524,7 @@ public class DetachedBKUConnector implements Connector, LocalConnector /** * Holds environment configuration information like templates. - * + * * @author wprinz */ public static class Environment extends ConnectorEnvironment @@ -537,27 +543,27 @@ public class DetachedBKUConnector implements Connector, LocalConnector * The configuration key of the sign URL. */ protected static final String SIGN_URL_KEY = "bku.sign.url"; //$NON-NLS-1$ - + /** * BKU template file prefix */ protected static final String TEMPLATE_FILE_PREFIX = "/templates/bku."; - + /** * signing file template sufix */ protected static final String SIGN_TEMPLATE_FILE_SUFIX = ".sign.xml"; - + /** * verifing template file sufix */ - protected static final String VERIFY_REQUEST_TEMPLATE_FILE_SUFIX = ".verify.request.xml"; + protected static final String VERIFY_REQUEST_TEMPLATE_FILE_SUFIX = ".verify.request.xml"; /** * verifing file template key sufix */ protected static final String VERIFY_TEMPLATE_SUFIX = ".verify.template.xml"; - + /** * The configuration key of the verify request template. */ @@ -605,7 +611,7 @@ public class DetachedBKUConnector implements Connector, LocalConnector /** * Initializes the environment with a given profile. - * + * * @param profile * The configuration profile. * @throws ConnectorException @@ -614,7 +620,7 @@ public class DetachedBKUConnector implements Connector, LocalConnector public Environment(String profile, String loc_ref_content) throws ConnectorException { this.profile = profile; - + this.loc_ref_content = loc_ref_content; SettingsReader settings = null; @@ -626,7 +632,7 @@ public class DetachedBKUConnector implements Connector, LocalConnector { throw new ConnectorException(300, e); } - + this.sign_keybox_identifier = getConnectorValueFromProfile(settings, profile, SIGN_KEYBOX_IDENTIFIER_KEY); String sign_request_filename = TEMPLATE_FILE_PREFIX + settings.getValueFromKey("default.bku.algorithm.id") + SIGN_TEMPLATE_FILE_SUFIX; @@ -634,7 +640,7 @@ public class DetachedBKUConnector implements Connector, LocalConnector // try to load template from file //this.sign_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename)); this.sign_request_template = settings.readInternalResourceAsString(sign_request_filename); - + // when first load failed (the template file does'nt exist), load it from default template file if(this.sign_request_template == null) { @@ -642,7 +648,7 @@ public class DetachedBKUConnector implements Connector, LocalConnector //this.sign_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename)); this.sign_request_template = settings.readInternalResourceAsString(sign_request_filename); } - + if (this.sign_request_template == null) { throw new ConnectorException(300, "Can not read the create xml request template"); //$NON-NLS-1$ @@ -651,20 +657,20 @@ public class DetachedBKUConnector implements Connector, LocalConnector this.sign_url = getConnectorValueFromProfile(settings, profile, SIGN_URL_KEY); // verify - + String verify_request_filename = TEMPLATE_FILE_PREFIX + settings.getValueFromKey("default.bku.algorithm.id") + VERIFY_REQUEST_TEMPLATE_FILE_SUFIX; - + // try to load template file for verifing //this.verify_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_request_filename)); this.verify_request_template = settings.readInternalResourceAsString(verify_request_filename); - + if(this.verify_request_template == null) { verify_request_filename = getConnectorValueFromProfile(settings, profile, VERIFY_REQUEST_TEMPLATE_KEY); //this.verify_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_request_filename)); this.verify_request_template = settings.readInternalResourceAsString(verify_request_filename); } - + if (this.verify_request_template == null) { throw new ConnectorException(ErrorCode.SETTING_NOT_FOUND, "Can not read the verify xml request template"); //$NON-NLS-1$ @@ -674,7 +680,7 @@ public class DetachedBKUConnector implements Connector, LocalConnector String verify_filename = TEMPLATE_FILE_PREFIX + settings.getValueFromKey("default.bku.algorithm.id") + VERIFY_TEMPLATE_SUFIX; //this.verify_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_filename)); this.verify_template = settings.readInternalResourceAsString(verify_filename); - + if(this.verify_template == null) { verify_filename = getConnectorValueFromProfile(settings, profile, VERIFY_TEMPLATE_KEY); @@ -702,7 +708,7 @@ public class DetachedBKUConnector implements Connector, LocalConnector /** * Returns the LocRef content. - * + * * @return Returns the LocRef content. */ public String getLocRefContent() @@ -712,7 +718,7 @@ public class DetachedBKUConnector implements Connector, LocalConnector /** * Returns the sign keybox identifier. - * + * * @return Returns the sign keybox identifier. */ public String getSignKeyboxIdentifier() @@ -722,7 +728,7 @@ public class DetachedBKUConnector implements Connector, LocalConnector /** * Returns the sign request template. - * + * * @return Returns the sign request template. */ public String getSignRequestTemplate() @@ -732,7 +738,7 @@ public class DetachedBKUConnector implements Connector, LocalConnector /** * Returns the sign URL. - * + * * @return Returns the sign URL. */ public String getSignURL() @@ -742,7 +748,7 @@ public class DetachedBKUConnector implements Connector, LocalConnector /** * Returns the verify request template. - * + * * @return Returns the verify request template. */ public String getVerifyRequestTemplate() @@ -752,7 +758,7 @@ public class DetachedBKUConnector implements Connector, LocalConnector /** * Returns the verify template. - * + * * @return Returns the verify template. */ public String getVerifyTemplate() @@ -762,7 +768,7 @@ public class DetachedBKUConnector implements Connector, LocalConnector /** * Returns the verify URL. - * + * * @return Returns the verify URL. */ public String getVerifyURL() @@ -772,7 +778,7 @@ public class DetachedBKUConnector implements Connector, LocalConnector /** * Returns the ecdsa cert alg property. - * + * * @return Returns the ecdsa cert alg property. */ public String getCertAlgEcdsa() @@ -782,7 +788,7 @@ public class DetachedBKUConnector implements Connector, LocalConnector /** * Returns the rsa cert alg property. - * + * * @return Returns the rsa cert alg property. */ public String getCertAlgRsa() @@ -793,7 +799,7 @@ public class DetachedBKUConnector implements Connector, LocalConnector /** * Reads the configuration entry given by the key, first from the given * profile, if not found from the defaults. - * + * * @param settings * The settings. * @param profile diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/EnvelopedBase64BKUConnector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/EnvelopedBase64BKUConnector.java index 170cc45..22318a2 100644 --- a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/EnvelopedBase64BKUConnector.java +++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/EnvelopedBase64BKUConnector.java @@ -52,7 +52,7 @@ import at.knowcenter.wag.egov.egiz.tools.CodingHelper; /** * @author wprinz - * + * */ public class EnvelopedBase64BKUConnector implements Connector, LocalConnector { @@ -72,16 +72,16 @@ public class EnvelopedBase64BKUConnector implements Connector, LocalConnector /** * Constructor that builds the configuration environment for this connector * according to the given profile. - * + * ** If confuguration parameters are not defined on that profile, the default * parameters defined in the configuration are used. *
- * + * ** This is the new "hotfix" base64 connector. *
- * + * * @param profile * The profile from which the Environment should be assembled. * @throws ConnectorException @@ -137,7 +137,7 @@ public class EnvelopedBase64BKUConnector implements Connector, LocalConnector // /** // * This emthod extracts id-values from a text. The id is given by the name. -// * +// * // * @param text // * the id-value that should extract from // * @param name @@ -166,11 +166,11 @@ public class EnvelopedBase64BKUConnector implements Connector, LocalConnector /** * Prepares the XML content the holds the actual signature data. - * + * ** This strongly rebuilds the XML content as retuned from a sign request. *
- * + * * @param data * The data. * @param so @@ -186,13 +186,13 @@ public class EnvelopedBase64BKUConnector implements Connector, LocalConnector { String ids_string = so.getSigID(); String[] ids = SignatureObject.parseSigIds(ids_string); - + X509Certificate cert = so.getX509Certificate(); - + // dferbas AlgorithmSuiteObject algSuite = new AlgorithmSuiteObject(); String verify_xml = AlgorithmSuiteUtil.evaluateReplaceAlgs(algSuite, this.environment, so); - + // data digest replace byte[] data_value = BKUHelper.prepareEnvelopingData(data); { @@ -225,7 +225,11 @@ public class EnvelopedBase64BKUConnector implements Connector, LocalConnector verify_xml = verify_xml.replaceAll(TemplateReplaces.SIG_ID_REPLACE, ids[0]); verify_xml = verify_xml.replaceFirst(TemplateReplaces.SIGNING_TIME_REPLACE, so.getDate()); verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_CERTIFICATE_REPLACE, certDigest); - verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_ISSUER_NAME_REPLACE, so.getIssuer()); + // fixed by dti: Issuer names may contain escapted commas ("\,"). As far as replaceFirst (and replaceAll) + // methods are regarded, backslashes in the replacement string may cause the results to be different than + // if it were being treated as a literal replacement string. +// verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_ISSUER_NAME_REPLACE, so.getIssuer()); + verify_xml = verify_xml.replace(TemplateReplaces.X509_ISSUER_NAME_REPLACE, so.getIssuer()); verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_SERIAL_NUMBER_REPLACE, so.getSerialNumber()); // SigDataRefReplace already done above @@ -276,7 +280,7 @@ public class EnvelopedBase64BKUConnector implements Connector, LocalConnector /** * Prepares the sign request xml to be sent using the sign request template. - * + * * @param data * The SignatureData. * @return Returns the sign request xml to be sent. @@ -302,7 +306,7 @@ public class EnvelopedBase64BKUConnector implements Connector, LocalConnector /** * Prepares the verify request xml to be sent using the verify request * template. - * + * * @param data * The SignatureData. * @param so @@ -325,7 +329,11 @@ public class EnvelopedBase64BKUConnector implements Connector, LocalConnector xml_content = chooseAndCreateXMLDsig(data, so); } - String verify_request_xml = verify_request_template.replaceFirst(TemplateReplaces.XML_CONTENT_REPLACE, xml_content); + // fixed by dti: Issuer names may contain escapted commas ("\,"). As far as replaceFirst (and replaceAll) + // methods are regarded, backslashes in the replacement string may cause the results to be different than + // if it were being treated as a literal replacement string. +// String verify_request_xml = verify_request_template.replaceFirst(TemplateReplaces.XML_CONTENT_REPLACE, xml_content); + String verify_request_xml = verify_request_template.replace(TemplateReplaces.XML_CONTENT_REPLACE, xml_content); // log.debug("\r\n\r\n" + verify_request_xml + "\r\n\r\n"); @@ -349,7 +357,7 @@ public class EnvelopedBase64BKUConnector implements Connector, LocalConnector /** * Sends the request to the given URL. - * + * * @param url * The URL. * @param request_string @@ -373,7 +381,7 @@ public class EnvelopedBase64BKUConnector implements Connector, LocalConnector /** * Analyzes the sign response xml and extracts the signature data. - * + * * @param response_properties * The response properties containing the response String and * transport related information. @@ -391,7 +399,7 @@ public class EnvelopedBase64BKUConnector implements Connector, LocalConnector String bkuIdentifier = BKUHelper.getBKUIdentifier(response_properties); log.debug("BKU identifier: \"" + bkuIdentifier + "\""); - + SignSignatureObject so = BKUHelper.parseCreateXMLResponse(response_string, new HotfixIdFormatter(), this.environment); log.debug("analyzeSignResponse finished."); //$NON-NLS-1$ @@ -400,7 +408,7 @@ public class EnvelopedBase64BKUConnector implements Connector, LocalConnector /** * Analyzes the verify response string. - * + * * @param response_properties * The response properties containing the response XML. * @return Returns the SignatureResponse containing the verification result. @@ -423,7 +431,7 @@ public class EnvelopedBase64BKUConnector implements Connector, LocalConnector /** * Holds environment configuration information like templates. - * + * * @author wprinz */ public static class Environment extends ConnectorEnvironment @@ -488,7 +496,7 @@ public class EnvelopedBase64BKUConnector implements Connector, LocalConnector /** * Initializes the environment with a given profile. - * + * * @param profile * The configuration profile. * @throws ConnectorException @@ -524,7 +532,7 @@ public class EnvelopedBase64BKUConnector implements Connector, LocalConnector //this.verify_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_request_filename)); this.verify_request_template = settings.readInternalResourceAsString(verify_request_filename); log.debug("Verify request template filename = " + verify_request_filename); - + if (this.verify_request_template == null) { throw new ConnectorException(ErrorCode.SETTING_NOT_FOUND, "Can not read the verify xml request template"); //$NON-NLS-1$ @@ -555,7 +563,7 @@ public class EnvelopedBase64BKUConnector implements Connector, LocalConnector /** * Returns the sign keybox identifier. - * + * * @return Returns the sign keybox identifier. */ public String getSignKeyboxIdentifier() @@ -565,7 +573,7 @@ public class EnvelopedBase64BKUConnector implements Connector, LocalConnector /** * Returns the sign request template. - * + * * @return Returns the sign request template. */ public String getSignRequestTemplate() @@ -575,7 +583,7 @@ public class EnvelopedBase64BKUConnector implements Connector, LocalConnector /** * Returns the sign URL. - * + * * @return Returns the sign URL. */ public String getSignURL() @@ -585,7 +593,7 @@ public class EnvelopedBase64BKUConnector implements Connector, LocalConnector /** * Returns the verify request template. - * + * * @return Returns the verify request template. */ public String getVerifyRequestTemplate() @@ -595,7 +603,7 @@ public class EnvelopedBase64BKUConnector implements Connector, LocalConnector /** * Returns the verify template. - * + * * @return Returns the verify template. */ public String getVerifyTemplate() @@ -605,7 +613,7 @@ public class EnvelopedBase64BKUConnector implements Connector, LocalConnector /** * Returns the verify URL. - * + * * @return Returns the verify URL. */ public String getVerifyURL() @@ -615,7 +623,7 @@ public class EnvelopedBase64BKUConnector implements Connector, LocalConnector /** * Returns the ecdsa cert alg property. - * + * * @return Returns the ecdsa cert alg property. */ public String getCertAlgEcdsa() @@ -625,7 +633,7 @@ public class EnvelopedBase64BKUConnector implements Connector, LocalConnector /** * Returns the rsa cert alg property. - * + * * @return Returns the rsa cert alg property. */ public String getCertAlgRsa() @@ -636,7 +644,7 @@ public class EnvelopedBase64BKUConnector implements Connector, LocalConnector /** * Reads the configuration entry given by the key, first from the given * profile, if not found from the defaults. - * + * * @param settings * The settings. * @param profile diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/DetachedLocRefMOAConnector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/DetachedLocRefMOAConnector.java index ea90841..07e9ccd 100644 --- a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/DetachedLocRefMOAConnector.java +++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/DetachedLocRefMOAConnector.java @@ -55,7 +55,7 @@ import at.knowcenter.wag.egov.egiz.tools.FileHelper; /** * Connects to MOA providing the Data detached as LocRef on a local resource. - * + * * @author wprinz */ public class DetachedLocRefMOAConnector implements Connector @@ -79,12 +79,12 @@ public class DetachedLocRefMOAConnector implements Connector /** * Constructor that builds the configuration environment for this connector * according to the given profile. - * + * ** If confuguration parameters are not defined on that profile, the default * parameters defined in the configuration are used. *
- * + * * @param profile * The profile from which the Environment should be assembled. * @throws SettingsException @@ -183,7 +183,7 @@ public class DetachedLocRefMOAConnector implements Connector /** * Prepares the verify request xml to be sent using the verify request * template. - * + * * @param data * The SignatureData. * @param so @@ -206,7 +206,11 @@ public class DetachedLocRefMOAConnector implements Connector xml_content = chooseAndCreateXMLDsig(data, so); } - String verify_request_xml = verify_request_template.replaceFirst(TemplateReplaces.XML_CONTENT_REPLACE, xml_content); + // fixed by dti: Issuer names may contain escapted commas ("\,"). As far as replaceFirst (and replaceAll) + // methods are regarded, backslashes in the replacement string may cause the results to be different than + // if it were being treated as a literal replacement string. +// String verify_request_xml = verify_request_template.replaceFirst(TemplateReplaces.XML_CONTENT_REPLACE, xml_content); + String verify_request_xml = verify_request_template.replace(TemplateReplaces.XML_CONTENT_REPLACE, xml_content); verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.TRUST_PROFILE_ID_REPLACE, this.environment.getVerifyTrustProfileId()); verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.LOC_REF_CONTENT_REPLACE, this.environment.getSignatureDataUrl()); @@ -217,7 +221,7 @@ public class DetachedLocRefMOAConnector implements Connector /** * Analyzes the verify response string. - * + * * @param response_properties * The response properties containing the response XML. * @return Returns the SignatureResponse containing the verification result. @@ -272,7 +276,11 @@ public class DetachedLocRefMOAConnector implements Connector // Qualified Properties replaces verify_xml = verify_xml.replaceFirst(TemplateReplaces.SIGNING_TIME_REPLACE, so.getDate()); verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_CERTIFICATE_REPLACE, certDigest); - verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_ISSUER_NAME_REPLACE, so.getIssuer()); + // fixed by dti: Issuer names may contain escapted commas ("\,"). As far as replaceFirst (and replaceAll) + // methods are regarded, backslashes in the replacement string may cause the results to be different than + // if it were being treated as a literal replacement string. +// verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_ISSUER_NAME_REPLACE, so.getIssuer()); + verify_xml = verify_xml.replace(TemplateReplaces.X509_ISSUER_NAME_REPLACE, so.getIssuer()); verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_SERIAL_NUMBER_REPLACE, so.getSerialNumber()); // SigDataRefReplace already done above verify_xml = verify_xml.replaceFirst(TemplateReplaces.MIME_TYPE_REPLACE, data.getMimeType()); @@ -323,7 +331,7 @@ public class DetachedLocRefMOAConnector implements Connector /** * Holds environment configuration information like templates. - * + * * @author wprinz */ public static class Environment extends ConnectorEnvironment @@ -417,7 +425,7 @@ public class DetachedLocRefMOAConnector implements Connector /** * Initializes the environment with a given profile. - * + * * @param profile * The configuration profile. * @throws SettingsException @@ -516,7 +524,7 @@ public class DetachedLocRefMOAConnector implements Connector /** * Returns the URL where to load the detached data from. - * + * * @return Returns the URL where to load the detached data from. */ public String getSignatureDataUrl() @@ -526,7 +534,7 @@ public class DetachedLocRefMOAConnector implements Connector /** * Returns the sign key identifier. - * + * * @return Returns the sign key identifier. */ public String getSignKeyIdentifier() @@ -536,7 +544,7 @@ public class DetachedLocRefMOAConnector implements Connector /** * Returns the sign request template. - * + * * @return Returns the sign request template. */ public String getSignRequestTemplate() @@ -546,7 +554,7 @@ public class DetachedLocRefMOAConnector implements Connector /** * Returns the sign URL. - * + * * @return Returns the sign URL. */ public String getSignURL() @@ -556,7 +564,7 @@ public class DetachedLocRefMOAConnector implements Connector /** * Returns the verify request template. - * + * * @return Returns the verify request template. */ public String getVerifyRequestTemplate() @@ -566,7 +574,7 @@ public class DetachedLocRefMOAConnector implements Connector /** * Returns the verify template. - * + * * @return Returns the verify template. */ public String getVerifyTemplate() @@ -576,7 +584,7 @@ public class DetachedLocRefMOAConnector implements Connector /** * Returns the verify URL. - * + * * @return Returns the verify URL. */ public String getVerifyURL() @@ -586,7 +594,7 @@ public class DetachedLocRefMOAConnector implements Connector /** * Returns the verify trust profile id. - * + * * @return Returns the verify trust profile id. */ public String getVerifyTrustProfileId() @@ -596,7 +604,7 @@ public class DetachedLocRefMOAConnector implements Connector /** * Returns the ecdsa cert alg property. - * + * * @return Returns the ecdsa cert alg property. */ public String getCertAlgEcdsa() @@ -606,7 +614,7 @@ public class DetachedLocRefMOAConnector implements Connector /** * Returns the rsa cert alg property. - * + * * @return Returns the rsa cert alg property. */ public String getCertAlgRsa() @@ -617,7 +625,7 @@ public class DetachedLocRefMOAConnector implements Connector /** * Reads the configuration entry given by the key, first from the given * profile, if not found from the defaults. - * + * * @param settings * The settings. * @param profile diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/EnvelopingBase64MOAConnector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/EnvelopingBase64MOAConnector.java index 6f2d171..4a33fc8 100644 --- a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/EnvelopingBase64MOAConnector.java +++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/EnvelopingBase64MOAConnector.java @@ -54,7 +54,7 @@ import at.knowcenter.wag.egov.egiz.tools.FileHelper; /** * @author wprinz - * + * */ public class EnvelopingBase64MOAConnector implements Connector { @@ -69,18 +69,18 @@ public class EnvelopingBase64MOAConnector implements Connector * other configurable elements. */ protected Environment environment = null; - + protected ConnectorParameters params = null; /** * Constructor that builds the configuration environment for this connector * according to the given profile. - * + * ** If confuguration parameters are not defined on that profile, the default * parameters defined in the configuration are used. *
- * + * * @param profile * The profile from which the Environment should be assembled. * @throws ConnectorException @@ -150,7 +150,7 @@ public class EnvelopingBase64MOAConnector implements Connector /** * Prepares the sign request xml to be sent using the sign request template. - * + * * @param data * The SignatureData. * @return Returns the sign request xml to be sent. @@ -176,7 +176,7 @@ public class EnvelopingBase64MOAConnector implements Connector /** * Prepares the verify request xml to be sent using the verify request * template. - * + * * @param data * The SignatureData. * @param so @@ -199,7 +199,11 @@ public class EnvelopingBase64MOAConnector implements Connector xml_content = chooseAndCreateXMLDsig(data, so); } - String verify_request_xml = verify_request_template.replaceFirst(TemplateReplaces.XML_CONTENT_REPLACE, xml_content); + // fixed by dti: Issuer names may contain escapted commas ("\,"). As far as replaceFirst (and replaceAll) + // methods are regarded, backslashes in the replacement string may cause the results to be different than + // if it were being treated as a literal replacement string. +// String verify_request_xml = verify_request_template.replaceFirst(TemplateReplaces.XML_CONTENT_REPLACE, xml_content); + String verify_request_xml = verify_request_template.replace(TemplateReplaces.XML_CONTENT_REPLACE, xml_content); verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.TRUST_PROFILE_ID_REPLACE, this.environment.getVerifyTrustProfileId()); String returnHashInputDataElement = ""; @@ -208,10 +212,10 @@ public class EnvelopingBase64MOAConnector implements Connector returnHashInputDataElement = MOASoapWithAttachmentConnector.RETURN_HASH_INPUT_DATA; } verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.RETURN_HASH_INPUT_DATA_REPLACE, returnHashInputDataElement); - + verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.DATE_TIME_REPLACE, BKUHelper.formDateTimeElement(this.params.getVerificationTime())); - + log.debug("\r\n\r\n" + verify_request_xml + "\r\n\r\n"); return verify_request_xml; @@ -219,7 +223,7 @@ public class EnvelopingBase64MOAConnector implements Connector /** * Analyzes the sign response xml and extracts the signature data. - * + * * @param response_properties * The response properties containing the response String and * transport related information. @@ -243,7 +247,7 @@ public class EnvelopingBase64MOAConnector implements Connector /** * Analyzes the verify response string. - * + * * @param response_properties * The response properties containing the response XML. * @return Returns the SignatureResponse containing the verification result. @@ -266,11 +270,11 @@ public class EnvelopingBase64MOAConnector implements Connector /** * Prepares the XML content the holds the actual signature data. - * + * ** This strongly rebuilds the XML content as retuned from a sign request. *
- * + * * @param data * The data. * @param so @@ -285,7 +289,7 @@ public class EnvelopingBase64MOAConnector implements Connector try { X509Certificate cert = so.getX509Certificate(); - + // dferbas AlgorithmSuiteObject algSuite = new AlgorithmSuiteObject(); String verify_xml = AlgorithmSuiteUtil.evaluateReplaceAlgs(algSuite, this.environment, so); @@ -311,7 +315,11 @@ public class EnvelopingBase64MOAConnector implements Connector // Qualified Properties replaces verify_xml = verify_xml.replaceFirst(TemplateReplaces.SIGNING_TIME_REPLACE, so.getDate()); verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_CERTIFICATE_REPLACE, certDigest); - verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_ISSUER_NAME_REPLACE, so.getIssuer()); + // fixed by dti: Issuer names may contain escapted commas ("\,"). As far as replaceFirst (and replaceAll) + // methods are regarded, backslashes in the replacement string may cause the results to be different than + // if it were being treated as a literal replacement string. +// verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_ISSUER_NAME_REPLACE, so.getIssuer()); + verify_xml = verify_xml.replace(TemplateReplaces.X509_ISSUER_NAME_REPLACE, so.getIssuer()); verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_SERIAL_NUMBER_REPLACE, so.getSerialNumber()); // SigDataRefReplace already done above @@ -339,7 +347,7 @@ public class EnvelopingBase64MOAConnector implements Connector // Base64 content replace -> do this at last for performance String base64 = CodingHelper.encodeBase64(data_value); verify_xml = verify_xml.replaceFirst(TemplateReplaces.BASE64_CONTENT_REPLACE, base64); - + log.debug("prepareXMLContent finished."); //$NON-NLS-1$ return verify_xml; } @@ -352,7 +360,7 @@ public class EnvelopingBase64MOAConnector implements Connector /** * Holds environment configuration information like templates. - * + * * @author wprinz */ public static class Environment extends ConnectorEnvironment @@ -401,7 +409,7 @@ public class EnvelopingBase64MOAConnector implements Connector * The configuration key for the RSA cert alg property. */ protected static final String RSA_CERT_ALG_KEY = "cert.alg.rsa"; //$NON-NLS-1$ - + protected String profile = null; protected String sign_key_identifier = null; @@ -424,7 +432,7 @@ public class EnvelopingBase64MOAConnector implements Connector /** * Initializes the environment with a given profile. - * + * * @param profile * The configuration profile. * @throws ConnectorException @@ -433,7 +441,7 @@ public class EnvelopingBase64MOAConnector implements Connector public Environment(String profile, String signKeyIdentifier) throws ConnectorException { this.profile = profile; - + SettingsReader settings = null; try { @@ -449,7 +457,7 @@ public class EnvelopingBase64MOAConnector implements Connector this.sign_key_identifier = signKeyIdentifier; } else - { + { this.sign_key_identifier = getConnectorValueFromProfile(settings, profile, SIGN_KEY_IDENTIFIER_KEY); } @@ -488,7 +496,7 @@ public class EnvelopingBase64MOAConnector implements Connector this.cert_alg_rsa = settings.getValueFromKey(RSA_CERT_ALG_KEY); } - + public String getProfile() { return this.profile; @@ -496,7 +504,7 @@ public class EnvelopingBase64MOAConnector implements Connector /** * Returns the sign key identifier. - * + * * @return Returns the sign key identifier. */ public String getSignKeyIdentifier() @@ -506,7 +514,7 @@ public class EnvelopingBase64MOAConnector implements Connector /** * Returns the sign request template. - * + * * @return Returns the sign request template. */ public String getSignRequestTemplate() @@ -516,7 +524,7 @@ public class EnvelopingBase64MOAConnector implements Connector /** * Returns the sign URL. - * + * * @return Returns the sign URL. */ public String getSignURL() @@ -526,7 +534,7 @@ public class EnvelopingBase64MOAConnector implements Connector /** * Returns the verify request template. - * + * * @return Returns the verify request template. */ public String getVerifyRequestTemplate() @@ -536,7 +544,7 @@ public class EnvelopingBase64MOAConnector implements Connector /** * Returns the verify template. - * + * * @return Returns the verify template. */ public String getVerifyTemplate() @@ -546,7 +554,7 @@ public class EnvelopingBase64MOAConnector implements Connector /** * Returns the verify URL. - * + * * @return Returns the verify URL. */ public String getVerifyURL() @@ -556,7 +564,7 @@ public class EnvelopingBase64MOAConnector implements Connector /** * Returns the verify trust profile id. - * + * * @return Returns the verify trust profile id. */ public String getVerifyTrustProfileId() @@ -566,7 +574,7 @@ public class EnvelopingBase64MOAConnector implements Connector /** * Returns the ecdsa cert alg property. - * + * * @return Returns the ecdsa cert alg property. */ public String getCertAlgEcdsa() @@ -576,7 +584,7 @@ public class EnvelopingBase64MOAConnector implements Connector /** * Returns the rsa cert alg property. - * + * * @return Returns the rsa cert alg property. */ public String getCertAlgRsa() @@ -587,7 +595,7 @@ public class EnvelopingBase64MOAConnector implements Connector /** * Reads the configuration entry given by the key, first from the given * profile, if not found from the defaults. - * + * * @param settings * The settings. * @param profile diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapWithAttachmentConnector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapWithAttachmentConnector.java index db0a04f..401921b 100644 --- a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapWithAttachmentConnector.java +++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapWithAttachmentConnector.java @@ -54,7 +54,7 @@ import at.knowcenter.wag.egov.egiz.tools.CodingHelper; /** * Connects to MOA providing the Data detached as LocRef on a local resource. - * + * * @author wprinz */ public class MOASoapWithAttachmentConnector implements Connector @@ -72,9 +72,9 @@ public class MOASoapWithAttachmentConnector implements Connector private static Log log = LogFactory.getLog(MOASoapWithAttachmentConnector.class); protected static final String MULTIPART_LOC_REF_CONTENT = "formdata:fileupload"; //$NON-NLS-1$ - + protected static final String RETURN_HASH_INPUT_DATA = "* If confuguration parameters are not defined on that profile, the default * parameters defined in the configuration are used. *
- * + * * @param connectorParameters * The parameters for this connector. * @throws ConnectorException @@ -193,7 +193,7 @@ public class MOASoapWithAttachmentConnector implements Connector /** * Prepares the verify request xml to be sent using the verify request * template. - * + * * @param data * The SignatureData. * @param so @@ -216,32 +216,36 @@ public class MOASoapWithAttachmentConnector implements Connector xml_content = chooseAndCreateXMLDsig(data, so); } - String verify_request_xml = verify_request_template.replaceFirst(TemplateReplaces.XML_CONTENT_REPLACE, xml_content); + // fixed by dti: Issuer names may contain escapted commas ("\,"). As far as replaceFirst (and replaceAll) + // methods are regarded, backslashes in the replacement string may cause the results to be different than + // if it were being treated as a literal replacement string. +// String verify_request_xml = verify_request_template.replaceFirst(TemplateReplaces.XML_CONTENT_REPLACE, xml_content); + String verify_request_xml = verify_request_template.replace(TemplateReplaces.XML_CONTENT_REPLACE, xml_content); verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.TRUST_PROFILE_ID_REPLACE, this.environment.getVerifyTrustProfileId()); verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.LOC_REF_CONTENT_REPLACE, this.environment.getSignatureDataUrl()); - + String returnHashInputDataElement = ""; if (this.params.isReturnHashInputData()) { returnHashInputDataElement = RETURN_HASH_INPUT_DATA; } verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.RETURN_HASH_INPUT_DATA_REPLACE, returnHashInputDataElement); - + verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.DATE_TIME_REPLACE, BKUHelper.formDateTimeElement(this.params.getVerificationTime())); - + log.debug("\r\n\r\n" + verify_request_xml + "\r\n\r\n"); return verify_request_xml; } - + private String chooseAndCreateXMLDsig(SignatureData data, SignSignatureObject so) throws ConnectorException { - + // MOA if (SigKZIDHelper.isMOASigned(so)) { log.debug("MOA signature detected."); return prepareXMLContent(data, so); - + // MOCCA } else if (SigKZIDHelper.isMOCCASigned(so)) { log.debug("MOCCA signature detected."); @@ -255,7 +259,7 @@ public class MOASoapWithAttachmentConnector implements Connector log.debug("A-Trust signature detected."); this.environment.reInitVerifyTemplate(ATRUST_VERIFY_TEMPLATE_KEY); return prepareXMLContent(data, so); - + // TD bku } else if (SigKZIDHelper.isBKUSigned(so)) { log.debug("TD bku signature detected."); @@ -263,13 +267,13 @@ public class MOASoapWithAttachmentConnector implements Connector return bku_connector.prepareXMLContent(data, so); } else { throw new ConnectorException(ErrorCode.UNSUPPORTED_SIGNATURE, "Unsupported signature (" + so.id + ", " +so.kz + "). Please get a new version of PDF-AS. Your version is: " + PdfAS.PDFAS_VERSION); - + } } - + /** * Analyzes the verify response string. - * + * * @param response_properties * The response properties containing the response XML. * @return Returns the SignatureResponse containing the verification result. @@ -298,7 +302,7 @@ public class MOASoapWithAttachmentConnector implements Connector String verify_xml = null; X509Certificate cert = so.getX509Certificate(); - + // dferbas AlgorithmSuiteObject algSuite = new AlgorithmSuiteObject(); verify_xml = AlgorithmSuiteUtil.evaluateReplaceAlgs(algSuite, this.environment, so); @@ -326,7 +330,11 @@ public class MOASoapWithAttachmentConnector implements Connector // Qualified Properties replaces verify_xml = verify_xml.replaceFirst(TemplateReplaces.SIGNING_TIME_REPLACE, so.getDate()); verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_CERTIFICATE_REPLACE, certDigest); - verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_ISSUER_NAME_REPLACE, so.getIssuer()); + // fixed by dti: Issuer names may contain escapted commas ("\,"). As far as replaceFirst (and replaceAll) + // methods are regarded, backslashes in the replacement string may cause the results to be different than + // if it were being treated as a literal replacement string. +// verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_ISSUER_NAME_REPLACE, so.getIssuer()); + verify_xml = verify_xml.replace(TemplateReplaces.X509_ISSUER_NAME_REPLACE, so.getIssuer()); verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_SERIAL_NUMBER_REPLACE, so.getSerialNumber()); // SigDataRefReplace already done above verify_xml = verify_xml.replaceFirst(TemplateReplaces.MIME_TYPE_REPLACE, data.getMimeType()); @@ -367,23 +375,11 @@ public class MOASoapWithAttachmentConnector implements Connector { try { - // for performance measurement -// long startTime = 0; -// if (log.isInfoEnabled()) { -// startTime = System.currentTimeMillis(); -// } - + // Properties response_properties = MOASoapConnection.connectMOA(request_string, MOASoapConnection.SERVICE_SIGN, url); log.debug("Connecting to " + url); Properties response_properties = MOASoapConnection.doPostRequestMultipart(url,mode, request_string, data ); - - // for performance measurement -// if (log.isInfoEnabled()) { -// long endTime = System.currentTimeMillis(); -// String toReport = "MOA-PROCESSING;-;-;" + (endTime - startTime) + ";"; -// log.info(toReport); -// } - + return response_properties; } catch (Exception e) @@ -391,14 +387,14 @@ public class MOASoapWithAttachmentConnector implements Connector throw new ConnectorException(330, e); } } - + public void reInitVerifyTemplate(String templatePropKey) throws ConnectorException { this.environment.reInitVerifyTemplate(templatePropKey); } /** * Holds environment configuration information like templates. - * + * * @author wprinz */ public static class Environment extends ConnectorEnvironment @@ -490,7 +486,7 @@ public class MOASoapWithAttachmentConnector implements Connector protected String cert_alg_rsa = null; - + public void reInitVerifyTemplate(String templatePropKey) throws ConnectorException { SettingsReader settings = null; try @@ -501,14 +497,14 @@ public class MOASoapWithAttachmentConnector implements Connector { throw new ConnectorException(300, e); } - + String verify_request_filename = getConnectorValueFromProfile(settings, this.profile, templatePropKey); this.verify_template = settings.readInternalResourceAsString(verify_request_filename); - + } /** * Initializes the environment with a given profile. - * + * * @param profile * The configuration profile. * @throws SettingsException @@ -537,7 +533,7 @@ public class MOASoapWithAttachmentConnector implements Connector this.sign_key_identifier = signKeyIdentifier; } else - { + { this.sign_key_identifier = getConnectorValueFromProfile(settings, profile, SIGN_KEY_IDENTIFIER_KEY); } @@ -570,7 +566,7 @@ public class MOASoapWithAttachmentConnector implements Connector if (this.verify_request_template == null) { - verify_request_filename = getConnectorValueFromProfile(settings, profile, VERIFY_REQUEST_TEMPLATE_KEY); + verify_request_filename = getConnectorValueFromProfile(settings, profile, VERIFY_REQUEST_TEMPLATE_KEY); //this.verify_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_request_filename)); this.verify_request_template = settings.readInternalResourceAsString(verify_request_filename); } @@ -614,7 +610,7 @@ public class MOASoapWithAttachmentConnector implements Connector /** * Returns the URL where to load the detached data from. - * + * * @return Returns the URL where to load the detached data from. */ public String getSignatureDataUrl() @@ -624,7 +620,7 @@ public class MOASoapWithAttachmentConnector implements Connector /** * Returns the sign key identifier. - * + * * @return Returns the sign key identifier. */ public String getSignKeyIdentifier() @@ -634,7 +630,7 @@ public class MOASoapWithAttachmentConnector implements Connector /** * Returns the sign request template. - * + * * @return Returns the sign request template. */ public String getSignRequestTemplate() @@ -644,7 +640,7 @@ public class MOASoapWithAttachmentConnector implements Connector /** * Returns the sign URL. - * + * * @return Returns the sign URL. */ public String getSignURL() @@ -654,7 +650,7 @@ public class MOASoapWithAttachmentConnector implements Connector /** * Returns the verify request template. - * + * * @return Returns the verify request template. */ public String getVerifyRequestTemplate() @@ -664,7 +660,7 @@ public class MOASoapWithAttachmentConnector implements Connector /** * Returns the verify template. - * + * * @return Returns the verify template. */ public String getVerifyTemplate() @@ -674,7 +670,7 @@ public class MOASoapWithAttachmentConnector implements Connector /** * Returns the verify URL. - * + * * @return Returns the verify URL. */ public String getVerifyURL() @@ -684,7 +680,7 @@ public class MOASoapWithAttachmentConnector implements Connector /** * Returns the verify trust profile id. - * + * * @return Returns the verify trust profile id. */ public String getVerifyTrustProfileId() @@ -694,7 +690,7 @@ public class MOASoapWithAttachmentConnector implements Connector /** * Returns the ecdsa cert alg property. - * + * * @return Returns the ecdsa cert alg property. */ public String getCertAlgEcdsa() @@ -704,7 +700,7 @@ public class MOASoapWithAttachmentConnector implements Connector /** * Returns the rsa cert alg property. - * + * * @return Returns the rsa cert alg property. */ public String getCertAlgRsa() @@ -715,7 +711,7 @@ public class MOASoapWithAttachmentConnector implements Connector /** * Reads the configuration entry given by the key, first from the given * profile, if not found from the defaults. - * + * * @param settings * The settings. * @param profile diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/LocRefDetachedMOCCAConnector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/LocRefDetachedMOCCAConnector.java index 12fc709..f9fe70b 100644 --- a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/LocRefDetachedMOCCAConnector.java +++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/LocRefDetachedMOCCAConnector.java @@ -120,10 +120,10 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector { * @throws ConnectorException Thrown in case of an error. */ public SignSignatureObject doSign(SignatureData data) throws ConnectorException { - log.debug("doSign:"); + log.debug("doSign:"); String sign_request_xml = prepareSignRequest(data); - log.debug("sign_request_xml = " + sign_request_xml); + log.debug("sign_request_xml = " + sign_request_xml); String url = this.environment.getSignURL(); Properties response_properties = sendRequest(url, sign_request_xml, data); @@ -132,7 +132,7 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector { sso.response_properties = response_properties; - log.debug("doSign finished."); + log.debug("doSign finished."); return sso; } @@ -148,12 +148,12 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector { * This method analyzes a signature response of the signature device. * @param response_properties The response elements of the signature device. * @return The parsed signed signature object. - * @throws ConnectorException Thrown in case of an error. + * @throws ConnectorException Thrown in case of an error. */ public SignSignatureObject analyzeSignResponse(Properties response_properties) throws ConnectorException { - log.debug("analyzeSignResponse:"); + log.debug("analyzeSignResponse:"); String response_string = response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY); - + String bkuIdentifier = BKUHelper.getBKUIdentifier(response_properties); log.debug("BKU identifier: \"" + bkuIdentifier + "\""); SignatureLayoutHandler sigLayout; @@ -162,13 +162,13 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector { } catch (SettingsException e) { throw new ConnectorException(e.getErrorCode(), e.getMessage()); } - + BKUHelper.checkResponseForError(response_string); - + // SignSignatureObject so = MOCCAHelper.parseCreateXMLResponse(response_string, new DetachedMOCIdFormatter()); SignSignatureObject so = sigLayout.parseCreateXMLSignatureResponse(response_string, this.environment); so.response_properties = response_properties; - log.debug("analyzeSignResponse finished."); + log.debug("analyzeSignResponse finished."); return so; } @@ -187,7 +187,7 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector { * @throws ConnectorException Thrown in case of an error. */ public String prepareSignRequest(SignatureData data) throws ConnectorException { - log.debug("prepareSignRequestDetached:"); + log.debug("prepareSignRequestDetached:"); String sign_request_template = this.environment.getSignRequestTemplate(); @@ -196,9 +196,9 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector { String loc_ref_content = this.environment.getLocRefContent(); if (log.isDebugEnabled()) { - log.debug("sign keybox identifier = " + sign_keybox_identifier); - log.debug("mime type = " + mime_type); - log.debug("loc_ref_content = " + loc_ref_content); + log.debug("sign keybox identifier = " + sign_keybox_identifier); + log.debug("mime type = " + mime_type); + log.debug("loc_ref_content = " + loc_ref_content); } String sign_request_xml = sign_request_template.replaceFirst(TemplateReplaces.KEYBOX_IDENTIFIER_REPLACE, sign_keybox_identifier); @@ -206,7 +206,7 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector { sign_request_xml = sign_request_xml.replaceFirst(TemplateReplaces.LOC_REF_CONTENT_REPLACE, loc_ref_content); log.debug("sign_request_xml = " + sign_request_xml); - log.debug("prepareSignRequestDetached finished."); + log.debug("prepareSignRequestDetached finished."); return sign_request_xml; } @@ -226,15 +226,15 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector { * @throws ConnectorException Thrown in case of an error. */ public String prepareXMLContent(SignatureData data, SignSignatureObject so) throws ConnectorException { - log.debug("prepareXMLContent:"); + log.debug("prepareXMLContent:"); try { - + String ids_string = so.getSigID(); String sigId = this.parseSigId(ids_string); X509Certificate cert = so.getX509Certificate(); - - + + // dferbas AlgorithmSuiteObject algSuite = new AlgorithmSuiteObject(); String verify_xml = AlgorithmSuiteUtil.evaluateReplaceAlgs(algSuite, this.environment, so); @@ -244,7 +244,7 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector { String object_data_hash = CodingHelper.encodeBase64(data_value_hash); // template replacements - + verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_SIGNED_DATA_REPLACE, object_data_hash); verify_xml = verify_xml.replaceFirst(TemplateReplaces.SIGNATURE_VALUE_REPLACE, so.getSignatureValue()); @@ -259,7 +259,11 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector { verify_xml = verify_xml.replaceAll(TemplateReplaces.SIG_ID_REPLACE, sigId); verify_xml = verify_xml.replaceFirst(TemplateReplaces.SIGNING_TIME_REPLACE, so.getDate()); verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_CERTIFICATE_REPLACE, certDigest); - verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_ISSUER_NAME_REPLACE, so.getIssuer()); + // fixed by dti: Issuer names may contain escapted commas ("\,"). As far as replaceFirst (and replaceAll) + // methods are regarded, backslashes in the replacement string may cause the results to be different than + // if it were being treated as a literal replacement string. +// verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_ISSUER_NAME_REPLACE, so.getIssuer()); + verify_xml = verify_xml.replace(TemplateReplaces.X509_ISSUER_NAME_REPLACE, so.getIssuer()); verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_SERIAL_NUMBER_REPLACE, so.getSerialNumber()); // SigDataRefReplace already done above verify_xml = verify_xml.replaceFirst(TemplateReplaces.MIME_TYPE_REPLACE, data.getMimeType()); @@ -270,15 +274,15 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector { if (matcher.find()) { log.debug("SignedProperties found."); String string_to_be_hashed = matcher.group(1); - log.debug("SignedProperties string to be hashed: " + string_to_be_hashed); - final byte[] bytes_to_be_hashed = string_to_be_hashed.getBytes("UTF-8"); + log.debug("SignedProperties string to be hashed: " + string_to_be_hashed); + final byte[] bytes_to_be_hashed = string_to_be_hashed.getBytes("UTF-8"); byte[] sig_prop_code = CodingHelper.buildDigest(bytes_to_be_hashed, algSuite.getPropertiesDigestMethod()); String sig_prop_hash = CodingHelper.encodeBase64(sig_prop_code); verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_SIGNED_PROPERTIES_REPLACE, sig_prop_hash); } - log.debug("prepareXMLContent finished."); + log.debug("prepareXMLContent finished."); return verify_xml; } catch (Exception e) { log.debug(e); @@ -291,21 +295,21 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector { * @author wprinz */ public static class Environment extends ConnectorEnvironment { - + /** * The configuration key of the sign keybox identifier. */ - protected static final String SIGN_KEYBOX_IDENTIFIER_KEY = "moc.sign.KeyboxIdentifier"; + protected static final String SIGN_KEYBOX_IDENTIFIER_KEY = "moc.sign.KeyboxIdentifier"; /** * The configuration key of the sign request template. */ - protected static final String SIGN_REQUEST_TEMPLATE_KEY = "moc.sign.request.detached"; + protected static final String SIGN_REQUEST_TEMPLATE_KEY = "moc.sign.request.detached"; /** * The configuration key of the sign URL. */ - protected static final String SIGN_URL_KEY = "moc.sign.url"; + protected static final String SIGN_URL_KEY = "moc.sign.url"; /** * BKU template file prefix @@ -334,29 +338,29 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector { */ /* signature verification is not supported by mocca protected static final String VERIFY_REQUEST_TEMPLATE_KEY = "moc.verify.request.detached"; - */ + */ /** * The configuration key of the verify template. */ - protected static final String VERIFY_TEMPLATE_KEY = "moc.verify.template.detached"; + protected static final String VERIFY_TEMPLATE_KEY = "moc.verify.template.detached"; /** * The configuration key of the verify URL. */ /* signature verification is not supported by mocca protected static final String xxxVERIFY_URL_KEY = "moc.verify.url"; - */ + */ /** * The configuration key for the ECDSA cert alg property. */ - protected static final String ECDSA_CERT_ALG_KEY = "cert.alg.ecdsa"; + protected static final String ECDSA_CERT_ALG_KEY = "cert.alg.ecdsa"; /** * The configuration key for the RSA cert alg property. */ - protected static final String RSA_CERT_ALG_KEY = "cert.alg.rsa"; + protected static final String RSA_CERT_ALG_KEY = "cert.alg.rsa"; protected String profile = null; @@ -381,7 +385,7 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector { protected String cert_alg_ecdsa = null; protected String cert_alg_rsa = null; - + protected String algorithmId = null; /** @@ -411,7 +415,7 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector { } // SIGN REQUEST - + // try specific file String sign_request_filename = TEMPLATE_FILE_PREFIX + this.algorithmId + SIGN_TEMPLATE_FILE_SUFFIX; log.debug("Trying to load specific sign request file " + sign_request_filename); @@ -428,15 +432,15 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector { // request file is needed !!! if (this.sign_request_template == null) { - throw new ConnectorException(300, "Can not read the create xml request template"); + throw new ConnectorException(300, "Can not read the create xml request template"); } this.sign_url = getConnectorValueFromProfile(settings, profile, SIGN_URL_KEY); - + // VERIFY REQUEST /* signature verification is not supported by mocca - + // try specific file String verify_request_filename = TEMPLATE_FILE_PREFIX + settings.getValueFromKey("default.moc.algorithm.id") + VERIFY_REQUEST_TEMPLATE_FILE_SUFIX; log.debug("Trying to load specific verify request file " + verify_request_filename); @@ -451,11 +455,11 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector { // request file is needed !!! if (this.verify_request_template == null) { - throw new ConnectorException(ErrorCode.SETTING_NOT_FOUND, "Can not read the verify xml request template"); + throw new ConnectorException(ErrorCode.SETTING_NOT_FOUND, "Can not read the verify xml request template"); } - + */ - + // load template file // try specific file String verify_filename = TEMPLATE_FILE_PREFIX + this.algorithmId + VERIFY_TEMPLATE_SUFFIX; @@ -473,7 +477,7 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector { // signature template is needed !!! if (this.verify_template == null) { - throw new ConnectorException(ErrorCode.SETTING_NOT_FOUND, "Can not read the verify template"); + throw new ConnectorException(ErrorCode.SETTING_NOT_FOUND, "Can not read the verify template"); } /* signature verification is not supported by mocca @@ -496,7 +500,7 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector { /** * Returns the LocRef content. - * + * * @return Returns the LocRef content. */ public String getLocRefContent() { @@ -505,7 +509,7 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector { /** * Returns the sign keybox identifier. - * + * * @return Returns the sign keybox identifier. */ public String getSignKeyboxIdentifier() { @@ -514,7 +518,7 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector { /** * Returns the sign request template. - * + * * @return Returns the sign request template. */ public String getSignRequestTemplate() { @@ -523,7 +527,7 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector { /** * Returns the sign URL. - * + * * @return Returns the sign URL. */ public String getSignURL() { @@ -532,7 +536,7 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector { /** * Returns the verify request template. - * + * * @return Returns the verify request template. */ /* signature verification is not supported by mocca @@ -543,7 +547,7 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector { /** * Returns the verify template. - * + * * @return Returns the verify template. */ public String getVerifyTemplate() { @@ -552,7 +556,7 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector { /** * Returns the verify URL. - * + * * @return Returns the verify URL. */ /* signature verification is not supported by mocca @@ -563,7 +567,7 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector { /** * Returns the ecdsa cert alg property. - * + * * @return Returns the ecdsa cert alg property. */ public String getCertAlgEcdsa() { @@ -572,7 +576,7 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector { /** * Returns the rsa cert alg property. - * + * * @return Returns the rsa cert alg property. */ public String getCertAlgRsa() { @@ -582,7 +586,7 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector { /** * Reads the configuration entry given by the key, first from the given * profile, if not found from the defaults. - * + * * @param settings * The settings. * @param profile @@ -599,7 +603,7 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector { return value; } } - + /** * Parses the common part for all id attributes from a given signature parameter string. * @param sigIdString The given signature parameter string. diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigkz/SigKZIDHelper.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigkz/SigKZIDHelper.java index 094880d..03bf931 100644 --- a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigkz/SigKZIDHelper.java +++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigkz/SigKZIDHelper.java @@ -50,49 +50,52 @@ import at.knowcenter.wag.egov.egiz.sig.sigid.HotfixIdFormatter; */ public final class SigKZIDHelper { - + /** * The Logger. */ protected static Log logger = LogFactory.getLog(SigKZIDHelper.class); - + public static boolean isTextual(PdfASID sig_kz) { if (sig_kz == null) { // Old signature -> must be textual. - + return true; } - + // new signauture -> sig_kz decides return sig_kz.getType().equals(SignatorFactory.TYPE_TEXTUAL); } - + public static boolean isBinary(PdfASID sig_kz) { return ! isTextual(sig_kz); } - - + + public static boolean isMOASigned(PdfASID sig_kz, String sig_id) { if (sig_kz == null || sig_kz.getVersion().equals(SignatorFactory.VERSION_1_0_0)) { // old signature - if sig_id is null this means MOA - + return sig_id == null; } - - if(sig_id == null) + + // According to the specification no signature parameter means MOA signature. + // Fixed: empty ("") or blank (" "), non-null signature parameter should also be regarded as "no signature parameter" +// if (sig_id != null) + if (StringUtils.isBlank(sig_id)) return true; - + // new signature - sig_id decides String [] ids = sig_id.split("@"); // dferbas String prefix = (ids[0].split(":"))[0]; - - + + if (prefix.equals(DetachedLocRefMOAIdFormatter.SIG_ID_PREFIX)) { return true; @@ -116,10 +119,10 @@ public final class SigKZIDHelper logger.error(e.getMessage(), e); } } - + return isMOASigned(kz, sig_id); } - + /** * @author tknall */ @@ -128,7 +131,7 @@ public final class SigKZIDHelper if (StringUtils.isEmpty(sig_id)) { return false; } - String[] ids = sig_id.split("@"); + String[] ids = sig_id.split("@"); if (ArrayUtils.isEmpty(ids)) { return false; } @@ -136,7 +139,7 @@ public final class SigKZIDHelper if (algorithmId == null) { return false; } else { - return algorithmId.startsWith("etsi-moc-1.0") || algorithmId.startsWith("etsi-moc-1.1"); + return algorithmId.startsWith("etsi-moc-1.0") || algorithmId.startsWith("etsi-moc-1.1") || algorithmId.startsWith("etsi-moc-1.2"); } } @@ -203,16 +206,16 @@ public final class SigKZIDHelper logger.error(e.getMessage(), e); } } - + return isOldBKU(kz, sig_id); } - + public static String getAlgorithmId(String bkuIdentifier) throws SettingsException, SettingNotFoundException, ConnectorException { SettingsReader sr = SettingsReader.getInstance(); String base = "signaturelayout.pattern"; Vector v = sr.getSettingKeys(base); - + Iterator it = v.iterator(); while (it.hasNext()) { String subKey = (String) it.next(); @@ -225,7 +228,7 @@ public final class SigKZIDHelper return algValue; } } - + if ("true".equalsIgnoreCase(sr.getSetting("signaturelayout.strict", "false"))) { logger.debug("Enforcing bku support check."); throw new ConnectorException(ErrorCode.BKU_NOT_SUPPORTED, "Unsupported BKU: " + bkuIdentifier); @@ -233,7 +236,7 @@ public final class SigKZIDHelper logger.debug("bku support check disabled."); return null; } - + } public static boolean isATrustSigned(SignSignatureObject so) { @@ -241,7 +244,7 @@ public final class SigKZIDHelper if (sig_id == null && StringUtils.isEmpty(sig_id)) { return false; } - return sig_id.startsWith("etsi-bka-atrust-1.0"); + return sig_id.startsWith("etsi-bka-atrust-1.0"); } /** @@ -251,11 +254,11 @@ public final class SigKZIDHelper */ public static boolean isBKUSigned(SignSignatureObject so) throws ConnectorException { if (isOldBKU(so)) return true; - + if (so.id.startsWith("etsi-bka-1.0")) { return true; } - + return false; } diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/mocca/MoccaXades14SignatureLayoutHandler.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/mocca/MoccaXades14SignatureLayoutHandler.java new file mode 100644 index 0000000..ed14315 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/mocca/MoccaXades14SignatureLayoutHandler.java @@ -0,0 +1,53 @@ +/** + ** Note that the given String must only contain Base64 characters. (The string * will be converted to a byte array of "US-ASCII" (7 bit) bytes and then this * byte array will be decoded using the Base64 algorithm. *
- * + * * @param theString * to be decoded * @return a Base64 decoded byte array @@ -166,14 +162,13 @@ public class CodingHelper } catch (UnsupportedEncodingException e) { - e.printStackTrace(); throw new RuntimeException("Very Strange: US-ASCII encoding not supported???", e); } } /** * This method decodes a given Base64 byte array - * + * * @param ba * the byte array to be decoded * @return a Base64 decoded byte array @@ -185,7 +180,7 @@ public class CodingHelper /** * This method encodes a given byte array Base64 - * + * * @param plainString * the byte array to be encoded * @return the Base64 encoded string @@ -199,7 +194,6 @@ public class CodingHelper } catch (UnsupportedEncodingException e) { - e.printStackTrace(); throw new RuntimeException("Very Strange: US-ASCII encoding not supported???", e); } } @@ -207,15 +201,15 @@ public class CodingHelper // dferbas /** * This method builds an hash value of a given byte array. - * + * * @param data * the byte array to build the hash value for - * @param hashAlg hash algorithm for {@link MessageDigest} e.g. "SHA-1" + * @param hashAlg hash algorithm for {@link MessageDigest} e.g. "SHA-1" * @return the calculated hash value as a byte array * @see MessageDigest */ public static byte[] buildDigest(byte[] data, String hashAlg) - { + { MessageDigest digester = null; try { @@ -243,10 +237,10 @@ public class CodingHelper byte [] data = DataSourceHelper.convertDataSourceToByteArray(input); return buildDigest(data, hashAlg); } - + /** * This method escapes a given string with HTML entities. - * + * * @param rawString * the string to escaped * @return the HTML escaped string @@ -263,7 +257,7 @@ public class CodingHelper /** * This method checks, if a byte array contains chars that are not base64 * conform. - * + * * @param byteArray * the array to test * @return boolean, if a byte array is base64 conform, false otherwise @@ -282,7 +276,7 @@ public class CodingHelper /** * This method checks, if a string contains chars that are not base64 conform. - * + * * @param string * the chars to test * @return boolean, if the given string is base64 conform, false otherwise -- cgit v1.2.3