aboutsummaryrefslogtreecommitdiff
path: root/pdf-as-lib/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'pdf-as-lib/src/main/java')
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/Constants.java33
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/DynamicSignatureProfileImpl.java8
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/SignatureProfile.java11
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/SignParameters.java78
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/commandline/Main.java123
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/ErrorCode.java13
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/logging/CsvStatisticLogger.java105
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/logging/StatisticData.java314
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/logging/StatisticLogFactory.java63
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/logging/StatisticLogger.java47
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/PdfAsObject.java441
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/DataSinkAdapter.java6
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/SignatureProfileImpl.java49
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/correction/InternalCorrector.java9
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/binary/BinarySignator_1_0_0.java16
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/detached/DetachedTextualSignator_1_0_0.java7
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/VerificationFilterImpl.java218
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/helper/VerificationFilterBinaryHelper.java19
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/FileBasedTextBasedDataSource.java3
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/StringTextBasedDataSource.java5
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/placeholder/SignaturePlaceholderExtractor.java37
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/CsvUtils.java82
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/PDFASUtils.java268
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/PdfAS.java245
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/CircularIncludeException.java44
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/NestedProperties.java255
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/PropertyTree.java82
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/SettingsReader.java207
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/commandline/Main.java116
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/BinarySignator_1_0_0.java29
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/DetachedSignator_1_0_0.java11
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/DetachedfTextualSignator_1_0_0.java15
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/AbsoluteTextSignature.java4
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/BinarySignature.java215
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFPage.java249
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFSignatureObjectIText.java70
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFUtilities.java25
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/StructContentHelper.java47
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/TextualSignature.java56
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/PathConstructionOperatorProcessor.java62
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/PathPaintingOperatorProcessor.java43
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/construction/ClosePath.java68
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/construction/CurveTo.java85
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/construction/CurveToReplicateFinalPoint.java82
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/construction/CurveToReplicateInitialPoint.java84
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/construction/LineTo.java71
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/construction/MoveTo.java73
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/painting/CloseAndStrokePath.java59
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/painting/CloseFillEvenOddAndStrokePath.java60
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/painting/CloseFillNonZeroAndStrokePath.java60
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/painting/EndPath.java68
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/painting/FillEvenOddAndStrokePath.java72
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/painting/FillNonZeroAndStrokePath.java72
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/painting/FillPathEvenOddRule.java71
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/painting/FillPathNonZeroWindingNumberRule.java72
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/painting/StrokePath.java70
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureObject.java171
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureTypes.java167
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/X509Cert.java32
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/BKUConnector.java81
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/MOAConnector.java47
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUHelper.java75
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/DetachedBKUConnector.java122
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/EnvelopedBase64BKUConnector.java68
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/DetachedLocRefMOAConnector.java48
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/EnvelopingBase64MOAConnector.java72
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapWithAttachmentConnector.java104
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/LocRefDetachedMOCCAConnector.java108
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigkz/SigKZIDHelper.java53
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/mocca/MoccaXades14SignatureLayoutHandler.java53
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/tools/CodingHelper.java34
-rw-r--r--pdf-as-lib/src/main/java/demo/SignatureVerificationDemo.java38
72 files changed, 4496 insertions, 1574 deletions
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/Constants.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/Constants.java
index b351d50..4afec65 100644
--- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/Constants.java
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/Constants.java
@@ -27,7 +27,7 @@ import at.knowcenter.wag.egov.egiz.pdf.AdobeSignatureHelper;
/**
* Contains commonly used constants.
- *
+ *
* @author wprinz
*/
public final class Constants
@@ -52,7 +52,7 @@ public final class Constants
* This value should not be modified due to external dependencies!
*/
public static final String SIGNATURE_TYPE_TEXTUAL = "textual";
-
+
/**
* The default signature type (one of "textual", "binary", "detachedtextual").
*/
@@ -60,7 +60,7 @@ public final class Constants
/**
* A "detached" textual signature.
- *
+ *
* <p>
* The document text is signed, but instead of returning the pdf with the signature block,
* the sign result XML of the connector is returned.
@@ -98,14 +98,14 @@ public final class Constants
* This value should not be modified due to external dependencies!
*/
public static final String SIGNATURE_DEVICE_MOBILE = "mobile";
-
+
/**
* Added by rpiazzi
* The signature device MOBILETEST for the test version of the MOBILE CCS.
* This value should not be modified due to external dependencies!
*/
public static final String SIGNATURE_DEVICE_MOBILETEST = "mobiletest";
-
+
/**
* Only binary signatures are verified.
*/
@@ -113,7 +113,7 @@ public final class Constants
/**
* Binary and textual signatures are verified with time optimization.
- *
+ *
* <p>
* This mode of operation tries to minimize the numbers of text extractions,
* which are very time intensive, at the cost of some rare cases, in which some
@@ -141,19 +141,19 @@ public final class Constants
* The zip file containing the default configuration.
*/
public static final String DEFAULT_CONFIGURATION_ZIP_RESOURCE = "DefaultConfiguration.zip";
-
+
/**
* The configuration folder for pdf-as within the user's home folder.
*/
public static final String USERHOME_CONFIG_FOLDER = "PDF-AS";
-
+
/**
* The name of the directory, where temporary files are stored.
*/
public static final String TEMP_DIR_NAME = "pdfastmp";
-
+
public static final String BKU_HEADER_SIGNATURE_LAYOUT = "SignatureLayout";
-
+
public static final String ADOBE_SIG_FILTER = AdobeSignatureHelper.ADOBE_SIG_FILTER;
/**
@@ -161,25 +161,30 @@ public final class Constants
* If the placeholder with the given id is not found in the document, an exception will be thrown.
*/
public static final int PLACEHOLDER_MATCH_MODE_STRICT = 0;
-
+
/**
* A moderate matching mode for placeholder extraction.<br/>
* If the placeholder with the given id is not found in the document, the first placeholder without an id will be taken.<br/>
* If there is no such placeholder, the signature will be placed as usual, according to the pos parameter of the signature profile used.
*/
public static final int PLACEHOLDER_MATCH_MODE_MODERATE = 1;
-
+
/**
* A more lenient matching mode for placeholder extraction.<br/>
* If the placeholder with the given id is not found in the document, the first found placeholder will be taken, regardless if it has an id set, or not.<br/>
* If there is no placeholder at all, the signature will be placed as usual, according to the pos parameter of the signature profile used.
*/
public static final int PLACEHOLDER_MATCH_MODE_LENIENT = 2;
-
+
/**
* Identifier for QR based placeholders.
*/
public static final String QR_PLACEHOLDER_IDENTIFIER = "PDF-AS-POS";
-
+
+ /**
+ * The name of a logger used for statistical logging.
+ */
+ public static final String STATISTIC_LOGGER_NAME = "statistic";
+
}
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/DynamicSignatureProfileImpl.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/DynamicSignatureProfileImpl.java
index 7e1672a..e1f31f7 100644
--- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/DynamicSignatureProfileImpl.java
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/DynamicSignatureProfileImpl.java
@@ -159,8 +159,10 @@ public class DynamicSignatureProfileImpl implements DynamicSignatureProfile {
cfg = SettingsReader.getInstance();
- Properties props = cfg.getProperties();
- for (Enumeration e = props.keys(); e.hasMoreElements();) {
+ Properties props = cfg.getProperties();
+ // DTI: props.keys() does not support default properties, therefore we should better use props.propertyNames()
+// for (Enumeration e = props.keys(); e.hasMoreElements();) {
+ for (Enumeration e = props.propertyNames(); e.hasMoreElements();) {
String oldKey = (String) e.nextElement();
if (oldKey.startsWith("sig_obj." + parentProfile + ".")) {
String newKey = StringUtils.replace(oldKey, parentProfile, name);
@@ -168,7 +170,7 @@ public class DynamicSignatureProfileImpl implements DynamicSignatureProfile {
this.newProps.put(newKey, val);
}
}
- this.newProps.put("sig_obj.types." + name, "on");
+ this.newProps.put("sig_obj.types." + name, "on");
} catch (Exception e) {
throw new RuntimeException(e);
}
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/SignatureProfile.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/SignatureProfile.java
index 8cd3108..1325d04 100644
--- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/SignatureProfile.java
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/SignatureProfile.java
@@ -25,6 +25,8 @@ package at.gv.egiz.pdfas.api.commons;
import java.util.Properties;
+import at.knowcenter.wag.egov.egiz.sig.SignatureTypes.State;
+
/**
* Definition of a signature profile.
*
@@ -73,4 +75,13 @@ public interface SignatureProfile {
* @return
*/
public boolean isDefault();
+
+ /**
+ * Returns the state of the signature profile. Signature profiles may be restricted to signature (
+ * {@link State#SIGN_ONLY}) or to verification ({@link State#VERIFY_ONLY}).
+ *
+ * @return The state of the profile.
+ */
+ public State getState();
+
}
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/SignParameters.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/SignParameters.java
index 8834481..5533b8b 100644
--- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/SignParameters.java
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/SignParameters.java
@@ -34,16 +34,16 @@ import at.knowcenter.wag.egov.egiz.sig.SignatureTypes;
/**
* Parameter object that holds the sign parameters.
- *
+ *
* @author wprinz
*/
public class SignParameters
{
// 23.11.2010 changed by exthex - added parameters for placeholder handling
-
+
/**
* The document to be signed.
- *
+ *
* <p>
* The DataSource implementation encapsulates the actual representaion of the
* data. E.g. the DataSource may be File based or byte array based. See
@@ -54,7 +54,7 @@ public class SignParameters
/**
* The type of the signature.
- *
+ *
* <p>
* May be {@link Constants#SIGNATURE_TYPE_BINARY} or
* {@link Constants#SIGNATURE_TYPE_TEXTUAL}.
@@ -64,7 +64,7 @@ public class SignParameters
/**
* The signature device to perform the actual signature.
- *
+ *
* <p>
* May be {@link Constants#SIGNATURE_DEVICE_MOA} or
* {@link Constants#SIGNATURE_DEVICE_BKU}.
@@ -75,18 +75,18 @@ public class SignParameters
/**
* The signature profile identifier identifying the profile to be used in the
* config file.
- *
+ *
* <p>
* Note: In near future it will be possible to provide a full specified
* profile here instead of the profile id.
* </p>
*/
protected String signatureProfileId = null;
-
+
/**
* The signature key identifier specifying which signature key should be used
* by the signature device to perform the signature.
- *
+ *
* <p>
* Providing a null value (default) means that no explicit signature key
* identifier is provided. The selected signature device will then use its
@@ -122,7 +122,7 @@ public class SignParameters
* The output DataSink that will receive the signed document.
*/
protected DataSink output = null;
-
+
protected TimeStamper timeStamperImpl;
/**
@@ -142,12 +142,12 @@ public class SignParameters
* Defaults to {@link Constants#PLACEHOLDER_MATCH_MODE_MODERATE}.
*/
protected int placeholderMatchMode = Constants.PLACEHOLDER_MATCH_MODE_MODERATE;
-
+
protected Properties overrideProps = new Properties();
-
-
+
+
/**
* {@link #setTimeStamperImpl(TimeStamper)}
@@ -158,7 +158,7 @@ public class SignParameters
}
/**
- * Set a {@link TimeStamper} to create a timestamp on the signature value. Will be
+ * Set a {@link TimeStamper} to create a timestamp on the signature value. Will be
* called after sign. For binary signatures only. Timestamp will be embedded in egiz dict /TimeStamp.
* @param timeStamperImpl
*/
@@ -285,21 +285,21 @@ public class SignParameters
}
/**
- * Override user defined values from the used signature profile like "value.SIG_META".
- * You cannot override pre defined values like SIG_VALUE, SIG_DATE {@link SignatureTypes#REQUIRED_SIG_KEYS}.
+ * Override user defined values from the used signature profile like "value.SIG_META".
+ * You cannot override pre defined values like SIG_VALUE, SIG_DATE {@link SignatureTypes#REQUIRED_SIG_KEYS}.
* The override values are bound to the {@link SignParameters} instance.
* <p>
* Sample usage:
* <pre>
SignParameters sp = new SignParameters();
. . .
-
- sp.setSignatureProfileId("SIGNATURBLOCK_DE");
-
+
+ sp.setSignatureProfileId("SIGNATURBLOCK_DE");
+
// expressions do not work on binary signature fields without phlength setting!!
sp.setProfileOverrideValue("SIG_META", "It's nice to be important, but it is more important to be nice ${subject.L}");;
- sp.setProfileOverrideValue("SIG_LABEL", "./images/signatur-logo_en.png");
-
+ sp.setProfileOverrideValue("SIG_LABEL", "./images/signatur-logo_en.png");
+
// execute sign using the overrides
pdfAs.sign(sp);
</pre>
@@ -311,51 +311,51 @@ public class SignParameters
if (SignatureTypes.isRequredSigTypeKey(key)) {
throw new RuntimeException("cannot set value for pre defined signature field names");
}
- this.overrideProps.put(key, value);
+ this.overrideProps.put(key, value);
}
-
+
/**
* Get override values created via {@link #setProfileOverrideValue(String, String)}
* @return
*/
public Properties getProfileOverrideProperties() {
return this.overrideProps;
-
+
}
/**
* Get the value of the checkForPlaceholder flag.
- *
+ *
* @return
*/
public Boolean isCheckForPlaceholder() {
return this.checkForPlaceholder;
}
-
+
/**
- * Set this to true, if you want a search for placeholder images to be performed and
+ * Set this to true, if you want a search for placeholder images to be performed and
* appropriate images to be replaced.
* If this is not set, a search will only be performed if the configuration property "enable_placeholder_search" is set to true.
- *
+ *
* @param check
*/
- public void setCheckForPlaceholder(boolean check) {
- this.checkForPlaceholder = Boolean.valueOf(check);
+ public void setCheckForPlaceholder(Boolean searchForPlaceHolder) {
+ this.checkForPlaceholder = searchForPlaceHolder;
}
/**
- * Set an explicit placeholder id.
+ * Set an explicit placeholder id.
* Only placeholder images that have a matching ID property embedded will be considered for replacement.
- *
+ *
* @param placeholderId
*/
public void setPlaceholderId(String placeholderId) {
- this.placeholderId = placeholderId;
+ this.placeholderId = placeholderId;
}
-
+
/**
* The id of the placeholder to replace.
- *
+ *
* @return the placeholderId
*/
public String getPlaceholderId() {
@@ -367,13 +367,13 @@ public class SignParameters
* Exactly matching meaning:<br/>
* <ul><li>If a placeholderId is set: a placeholder which has exactly this id embedded</li>
* <li>If no placeholderId is set: a placeholder without an embedded id is found</li></ul>
- *
+ *
* @see Constants#PLACEHOLDER_MATCH_MODE_LENIENT
* @see Constants#PLACEHOLDER_MATCH_MODE_MODERATE
* @see Constants#PLACEHOLDER_MATCH_MODE_STRICT
- *
+ *
* Defaults to {@link Constants#PLACEHOLDER_MATCH_MODE_MODERATE}.
- *
+ *
* @param placeholderMatchMode
*/
public void setPlaceholderMatchMode(int placeholderMatchMode) {
@@ -382,12 +382,12 @@ public class SignParameters
/**
* Get the placeholder matching mode.
- *
+ *
* @see SignParameters#getPlaceholderMatchMode()
* @return the placeholderMatchMode
*/
public int getPlaceholderMatchMode() {
return this.placeholderMatchMode;
}
-
+
}
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/commandline/Main.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/commandline/Main.java
index 52355f8..d5f7e2f 100644
--- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/commandline/Main.java
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/commandline/Main.java
@@ -36,6 +36,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Set;
+import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -78,11 +79,11 @@ import at.knowcenter.wag.egov.egiz.sig.SignatureTypes;
/**
* The main program entry point of the commandline tool.
- *
+ *
* <p>
* The commandline uses the PDF-AS API.
* </p>
- *
+ *
* @author wprinz
*/
public abstract class Main
@@ -127,12 +128,12 @@ public abstract class Main
* Command line parameter signaling to search the source document for a placeholder for the signature
*/
protected static final String PARAMETER_PLACEHOLDER_SEARCH = "-searchplaceholder";
-
+
/**
* Command line parameter selecting the id of the placeholder to use
*/
protected static final String PARAMETER_PLACEHOLDER_ID = "-placeholder_id";
-
+
/**
* Command line parameter selecting the match mode for the placeholder
*/
@@ -143,7 +144,7 @@ public abstract class Main
* verified.
*/
protected static final String PARAMETER_VERIFY_WHICH = "-verify_which";
-
+
/**
* Command line parameter that starts the deployment of the default configuration to the current
* user's home folder.
@@ -195,7 +196,7 @@ public abstract class Main
* The placeholder match mode STRICT
*/
public static final String VALUE_PLACEHOLDER_MATCH_MODE_LENIENT = "lenient";
-
+
/**
* The log.
*/
@@ -203,7 +204,7 @@ public abstract class Main
/**
* Main program entry point.
- *
+ *
* @param args
* The commandline arguments.
* @throws IOException
@@ -216,7 +217,7 @@ public abstract class Main
for (int i = 0; i < args.length; i++) {
if (args[i].trim().equals(PARAMETER_DEPLOY_DEFAULT_CONFIGURATION)) {
try {
- String defaultConfigurationDeployedTo = ConfigUtils.deployDefaultConfiguration();
+ String defaultConfigurationDeployedTo = ConfigUtils.deployDefaultConfiguration();
if (defaultConfigurationDeployedTo != null) {
System.out.println("Default configuration successfully deployed to \"" + defaultConfigurationDeployedTo + "\".");
} else {
@@ -229,7 +230,7 @@ public abstract class Main
} catch (ConfigUtilsException e) {
System.err.println("Deployment of default configuration failed: " + e.getMessage());
System.exit(1);
- }
+ }
}
}
@@ -247,7 +248,8 @@ public abstract class Main
String user_password = null;
String pos_string = null;
- boolean search_placeholder = true;
+ // DTI: fixed searchplaceholder parameter handling preventing consideration of respective configuration parameter
+ Boolean searchPlaceHolder = null;
String placeholderId = null;
int placeholderMatchMode = Constants.PLACEHOLDER_MATCH_MODE_MODERATE;
@@ -274,7 +276,7 @@ public abstract class Main
// already applied
continue;
}
-
+
if (cur_arg.equals(PARAMETER_MODE))
{
i++;
@@ -351,7 +353,8 @@ public abstract class Main
printNoValue(PARAMETER_PLACEHOLDER_SEARCH);
return;
}
- search_placeholder = Boolean.valueOf(args[i]).booleanValue();
+// search_placeholder = Boolean.valueOf(args[i]).booleanValue();
+ searchPlaceHolder = BooleanUtils.toBooleanObject(args[i]);
continue;
}
@@ -522,7 +525,7 @@ public abstract class Main
output = generateOutputFileNameFromInput(input, signature_mode);
}
- carryOutCommand(mode, signature_mode, connector, signature_type, user_name, user_password, verify_which, input, output, pos_string, search_placeholder, placeholderId, placeholderMatchMode);
+ carryOutCommand(mode, signature_mode, connector, signature_type, user_name, user_password, verify_which, input, output, pos_string, searchPlaceHolder, placeholderId, placeholderMatchMode);
}
catch (PdfAsException e)
@@ -549,7 +552,7 @@ public abstract class Main
}
protected static void carryOutCommand(final String mode, final String signature_mode, final String connector, final String signature_type, final String user_name, final String user_password,
- final int verify_which, final String input, String output, final String pos_string, boolean search_placeholder, String placeholderId, int placeholderMatchMode) throws PdfAsException
+ final int verify_which, final String input, String output, final String pos_string, Boolean searchPlaceHolder, String placeholderId, int placeholderMatchMode) throws PdfAsException
{
// File file = new File(input);
//
@@ -570,7 +573,7 @@ public abstract class Main
if (mode.equals(VALUE_MODE_SIGN))
{
- carryOutSign(input, connector, signature_mode, signature_type, pos_string, user_name, user_password, output, messageOutput, search_placeholder, placeholderId, placeholderMatchMode);
+ carryOutSign(input, connector, signature_mode, signature_type, pos_string, user_name, user_password, output, messageOutput, searchPlaceHolder, placeholderId, placeholderMatchMode);
}
else
{
@@ -580,7 +583,7 @@ public abstract class Main
}
public static void carryOutSign(String input, String connector, String signature_mode, String signature_type, String pos_string, String user_name, String user_password, String output,
- PrintWriter messageOutput, boolean search_placeholder, String placeholderId, int placeholderMatchMode) throws PdfAsException
+ PrintWriter messageOutput, Boolean searchPlaceHolder, String placeholderId, int placeholderMatchMode) throws PdfAsException
{
messageOutput.println("Signing " + input + "...");
@@ -621,7 +624,7 @@ public abstract class Main
}
try {
- processSign(dataSource, connector, signature_mode, signature_type, pos_string, search_placeholder, placeholderId, placeholderMatchMode, dataSink);
+ processSign(dataSource, connector, signature_mode, signature_type, pos_string, searchPlaceHolder, placeholderId, placeholderMatchMode, dataSink);
} catch (Exception e) {
// Exception caught in order to delete file based datasink
if (outputFile != null && outputFile.exists())
@@ -641,14 +644,6 @@ 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 (" + output + ").");
}
@@ -656,22 +651,10 @@ public abstract class Main
{
messageOutput.println("Verifying " + input + "...");
- // 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"))
{
@@ -705,23 +688,15 @@ 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.
- *
+ *
* <p>
* The extension of a file name is whatever text follows the last '.'.
* </p>
- *
+ *
* @param file_name
* The file name.
* @return Returns the extension. If the file name ends with the '.', then an
@@ -743,7 +718,7 @@ public abstract class Main
return file_name.substring(dot_index + 1);
}
- public static void processSign(DataSource dataSource, String connector, String signature_mode, String signature_type, String pos_string, boolean search_placeholder, String placeholderId, int placeholderMatchMode, DataSink dataSink) throws PdfAsException
+ public static void processSign(DataSource dataSource, String connector, String signature_mode, String signature_type, String pos_string, Boolean searchPlaceHolder, String placeholderId, int placeholderMatchMode, DataSink dataSink) throws PdfAsException
{
TablePos pos = null;
if (pos_string != null)
@@ -795,7 +770,7 @@ public abstract class Main
sp.setSignatureDevice(connector);
sp.setSignatureProfileId(signature_type);
sp.setSignaturePositioning(posi);
- sp.setCheckForPlaceholder(search_placeholder);
+ sp.setCheckForPlaceholder(searchPlaceHolder);
sp.setPlaceholderId(placeholderId);
sp.setPlaceholderMatchMode(placeholderMatchMode);
pdfAs.sign(sp);
@@ -853,7 +828,7 @@ public abstract class Main
/**
* Prints that the provided option was unrecognized.
- *
+ *
* @param option
* The unrecognized option.
* @throws PresentableException
@@ -867,7 +842,7 @@ public abstract class Main
/**
* Prints that the provided value was unrecognized.
- *
+ *
* @param parameter
* The parameter, which is missing a value.
* @throws PresentableException
@@ -881,7 +856,7 @@ public abstract class Main
/**
* Prints that the provided value was unrecognized.
- *
+ *
* @param value
* The unrecognized value.
* @throws PresentableException
@@ -895,7 +870,7 @@ public abstract class Main
/**
* Prints that the provided additional commandline argument was unrecognized.
- *
+ *
* @param argument
* The unrecognized argument.
* @throws PresentableException
@@ -909,7 +884,7 @@ public abstract class Main
/**
* Prints that a certain parameter was missing.
- *
+ *
* @param missing_term
* A description of the missing parameter ("e.g. a mode").
* @param parameter
@@ -924,7 +899,7 @@ public abstract class Main
/**
* Prints that something is missing.
- *
+ *
* @param missing_term
* A descriptive message of the missing thing.
* @throws PresentableException
@@ -938,7 +913,7 @@ public abstract class Main
/**
* Prints out the ErrorCodeException in a descriptive form.
- *
+ *
* @param ece
* The ErrorCodeException to be printed.
*/
@@ -974,7 +949,7 @@ public abstract class Main
/**
* Prints the usage text.
- *
+ *
* @param writer
* The writer to print the text to.
* @throws PresentableException
@@ -991,7 +966,7 @@ public abstract class Main
writer.print(" " + PARAMETER_CONNECTOR + " ");
ConnectorInformation[] ci = ConnectorFactory.getConnectorInformationArray();
-
+
// prepare list of connectors available for commandline
ArrayList ciList = new ArrayList();
for (int i = 0; i < ci.length; i++) {
@@ -1000,7 +975,7 @@ public abstract class Main
ciList.add(ci[i]);
}
}
-
+
// list available connectors wrapped in <...|...>
Iterator ciIt = ciList.iterator();
writer.print("<");
@@ -1012,7 +987,7 @@ public abstract class Main
}
writer.print(">");
writer.println();
-
+
// for (int i = 0; i < ci.length; i++)
// {
// String id = ci[i].getIdentifier();
@@ -1046,7 +1021,7 @@ public abstract class Main
writer.println(" " + PARAMETER_DEPLOY_DEFAULT_CONFIGURATION + " ... deploys the default configuration to the current user's home");
- writer.println(" OPTIONS for signation:");
+ writer.println(" OPTIONS for signature:");
writer.println(" " + PARAMETER_SIGNATURE_MODE + " <" + VALUE_SIGNATURE_MODE_BINARY + "|" + VALUE_SIGNATURE_MODE_TEXTUAL + "> [optional]");
writer.println(" " + VALUE_SIGNATURE_MODE_BINARY + " ... signs the complete binary document" + (Constants.DEFAULT_SIGNATURE_TYPE.equals(VALUE_SIGNATURE_MODE_BINARY) ? " (default)" : ""));
@@ -1056,7 +1031,9 @@ public abstract class Main
writer.print(" " + PARAMETER_SIGNATURE_TYPE + " <");
SignatureTypes sig_types = SignatureTypes.getInstance();
SettingsReader settings = SettingsReader.getInstance();
- Set types_array = sig_types.getSignatureTypes();
+ // show only signature profiles that can be used for signature
+// Set types_array = sig_types.getSignatureTypes();
+ Set types_array = sig_types.getSignatureTypesForSignature();
Iterator it = types_array.iterator();
while (it.hasNext())
{
@@ -1117,7 +1094,7 @@ public abstract class Main
/**
* Checks the value for correctness.
- *
+ *
* @param mode
* The parameter's value.
* @return Returns true, if the value is correct, false otherwise.
@@ -1129,7 +1106,7 @@ public abstract class Main
/**
* Checks the value for correctness.
- *
+ *
* @param signature_mode
* The parameter's value.
* @return Returns true, if the value is correct, false otherwise.
@@ -1143,7 +1120,7 @@ public abstract class Main
/**
* Checks the value for correctness.
- *
+ *
* @param connector
* The parameter's value.
* @return Returns true, if the value is correct, false otherwise.
@@ -1157,7 +1134,7 @@ public abstract class Main
/**
* Checks the value for correctness (meaning if it exists)
- *
+ *
* @param signature_type
* The parameter's value.
* @return Returns true, if the value is correct, false otherwise.
@@ -1166,10 +1143,10 @@ public abstract class Main
{
return SignatureTypes.getInstance().getSignatureTypes().contains(signature_type);
}
-
+
/**
* Translates the commandline argument to a PDF-AS-ID.
- *
+ *
* @param signature_mode
* The signator mode commandline argument.
* @return Returns the corresponding PDFASID.
@@ -1197,7 +1174,7 @@ public abstract class Main
/**
* Formats the verification results.
- *
+ *
* @param results
* The List of SignatureResponse verification results.
* @param writer
@@ -1223,9 +1200,9 @@ public abstract class Main
/**
* Formats the verification results for debugging. Returns 0 if no error
* occurs or the sum of all error-codes.
- *
+ *
* @param results
- *
+ *
* @param writer
* The output sink to write the formatted text to.
* @throws SettingNotFoundException
@@ -1259,7 +1236,7 @@ public abstract class Main
String public_property = (String) it.next();
writer.println(" Eigenschaft: " + public_property);
}
-
+
writer.println(" Zertifikat-Check:");
writer.println(" " + result.getCertificateCheck().getCode() + " - " + result.getCertificateCheck().getMessage());
writer.println(" Signatur-Check:");
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/ErrorCode.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/ErrorCode.java
index e0ddbf2..e7d2b47 100644
--- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/ErrorCode.java
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/ErrorCode.java
@@ -23,6 +23,8 @@
*/
package at.gv.egiz.pdfas.exceptions;
+import at.knowcenter.wag.egov.egiz.exceptions.SignatureException;
+
/**
* Contains constants for the error codes.
*
@@ -44,6 +46,8 @@ public final class ErrorCode
public static final int NO_EMBEDABLE_TTF_CONFIGURED_FOR_PDFA = 103;
public static final int INVALID_SIGNATURE_LAYOUT_IMPL_CONFIGURED = 104;
public static final int MISSING_HEADER_SERVER_USER_AGENT = 105;
+ public static final int CIRCULAR_INCLUDE_INSTRUCTION_DETECTED = 106;
+ public static final int UNABLE_TO_LOAD_DEFAULT_CONFIG = 107;
public static final int DOCUMENT_CANNOT_BE_READ = 201;
public static final int TEXT_EXTRACTION_EXCEPTION = 202;
@@ -56,6 +60,15 @@ public final class ErrorCode
//23.11.2010 changed by exthex - added error code for failed extraction
public static final int SIGNATURE_PLACEHOLDER_EXTRACTION_FAILED = 233;
+ /**
+ * Error code for {@code SignatureException}s occurring when trying to sign with a certain signature profile that
+ * is not allowed to be used for signature, e.g. because ist has been set to
+ * <p/>
+ * {@code sig_obj.types.<PROFILE_ID> = verify_only}
+ * @author Datentechnik Innovation GmbH
+ */
+ public static final int SIGNATURE_PROFILE_IS_NOT_ALLOWED_FOR_SIGNATURE = 234;
+
public static final int INVALID_SIGNATURE_POSITION = 224;
public static final int NO_TEXTUAL_CONTENT = 251;
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/logging/CsvStatisticLogger.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/logging/CsvStatisticLogger.java
new file mode 100644
index 0000000..a295a7b
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/logging/CsvStatisticLogger.java
@@ -0,0 +1,105 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.framework.logging;
+
+import org.apache.commons.logging.Log;
+
+import at.gv.egiz.pdfas.api.exceptions.PdfAsException;
+import at.gv.egiz.pdfas.exceptions.external.ExternalErrorException;
+import at.gv.egiz.pdfas.utils.CsvUtils;
+
+/**
+ * A statistic logger implementation that prodoces csv based logging entries.
+ *
+ * @author Datentechnik Innovation GmbH
+ */
+public class CsvStatisticLogger implements StatisticLogger {
+
+ /**
+ * The underlying logging implementation.
+ */
+ private Log log;
+
+ /**
+ * A csv value indication error conditions.
+ */
+ private static final String VALUE_ERROR = "ERROR";
+
+ /**
+ * A csv value indication success conditions.
+ */
+ private static final String VALUE_OK = "OK";
+
+ /**
+ * Creates a new instance.
+ *
+ * @param log
+ * The underlying logger.
+ */
+ CsvStatisticLogger(Log log) {
+ this.log = log;
+ }
+
+ public void log(StatisticData data) {
+ if (isEnabled()) {
+ StringBuffer msg = new StringBuffer();
+
+ // add escapted fields
+ msg.append(CsvUtils.escapeCsvValue(data.operation)).append(CsvUtils.DEFAULT_DELIMITER);
+ msg.append(CsvUtils.escapeCsvValue(data.signatureMode)).append(CsvUtils.DEFAULT_DELIMITER);
+ msg.append(CsvUtils.escapeCsvValue(data.connector)).append(CsvUtils.DEFAULT_DELIMITER);
+ msg.append(CsvUtils.escapeCsvValue(data.signatureProfileId)).append(CsvUtils.DEFAULT_DELIMITER);
+ msg.append(CsvUtils.escapeCsvValue(data.fileSize)).append(CsvUtils.DEFAULT_DELIMITER);
+ msg.append(CsvUtils.escapeCsvValue(data.userAgent)).append(CsvUtils.DEFAULT_DELIMITER);
+
+ // handle error conditions
+ Integer errorCode = null;
+ String externalErrorCode = null;
+ if (data.exception != null) {
+ msg.append(VALUE_ERROR).append(CsvUtils.DEFAULT_DELIMITER);
+ if (data.exception instanceof PdfAsException) {
+ PdfAsException pdfAsException = (PdfAsException) data.exception;
+ errorCode = pdfAsException.getErrorCode();
+ if (pdfAsException instanceof ExternalErrorException) {
+ externalErrorCode = ((ExternalErrorException) pdfAsException).getExternalErrorCode();
+ }
+ }
+ msg.append(CsvUtils.escapeCsvValue(data.exception.getClass().getName())).append(CsvUtils.DEFAULT_DELIMITER);
+ } else {
+ msg.append(VALUE_OK).append(CsvUtils.DEFAULT_DELIMITER).append(CsvUtils.DEFAULT_DELIMITER);
+ }
+ msg.append(CsvUtils.escapeCsvValue(errorCode)).append(CsvUtils.DEFAULT_DELIMITER);
+ msg.append(CsvUtils.escapeCsvValue(externalErrorCode)).append(CsvUtils.DEFAULT_DELIMITER);
+
+ msg.append(CsvUtils.escapeCsvValue(data.duration));
+
+ log.info(msg);
+ }
+ }
+
+ public boolean isEnabled() {
+ return log.isInfoEnabled();
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/logging/StatisticData.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/logging/StatisticData.java
new file mode 100644
index 0000000..3cb1c66
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/logging/StatisticData.java
@@ -0,0 +1,314 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.framework.logging;
+
+import at.gv.egiz.pdfas.api.analyze.AnalyzeParameters;
+import at.gv.egiz.pdfas.api.commons.Constants;
+import at.gv.egiz.pdfas.api.sign.SignParameters;
+import at.gv.egiz.pdfas.api.verify.VerifyAfterAnalysisParameters;
+import at.gv.egiz.pdfas.api.verify.VerifyAfterReconstructXMLDsigParameters;
+import at.gv.egiz.pdfas.api.verify.VerifyParameters;
+import at.gv.egiz.pdfas.api.xmldsig.ReconstructXMLDsigAfterAnalysisParameters;
+import at.gv.egiz.pdfas.api.xmldsig.ReconstructXMLDsigParameters;
+
+public class StatisticData {
+
+ String operation;
+ String connector;
+ String signatureMode;
+ String signatureProfileId;
+ Integer fileSize;
+ Long duration;
+ String userAgent;
+ Exception exception;
+
+ /**
+ * Creates new data for statistical logging purposes.
+ */
+ public StatisticData() {
+ }
+
+ /**
+ * Creates new data for statistical logging purposes.
+ *
+ * @param operation
+ * The operation (one of 'SIGN' and 'VERIFY').
+ * @param connector
+ * The connector being used for the certain operation (one of {@link Constants#SIGNATURE_DEVICE_BKU},
+ * {@link Constants#SIGNATURE_DEVICE_MOA}, {@link Constants#SIGNATURE_DEVICE_MOC},
+ * {@link Constants#SIGNATURE_DEVICE_MOBILE}...)
+ * @param fileSize
+ * The size of the file being processed.
+ * @param signatureMode
+ * The signature mode (one of {@link Constants#SIGNATURE_TYPE_BINARY},
+ * {@link Constants#SIGNATURE_TYPE_BINARY} or {@code null} in case of verification.
+ * @param duration
+ * The duration the certain operation took (in ms).
+ * @param userAgent
+ * The user agent String.
+ * @param errorCode
+ * The error code resulting from the current operation (0 means no error).
+ */
+ public StatisticData(String operation, String connector, Integer fileSize, String signatureMode, Long duration,
+ String userAgent, Integer errorCode) {
+ this();
+ this.operation = operation;
+ this.connector = connector;
+ this.signatureMode = signatureMode;
+ this.fileSize = fileSize;
+ this.duration = duration;
+ this.userAgent = userAgent;
+ }
+
+ /**
+ * Creates new data for statistical logging purposes.
+ *
+ * @param operation
+ * The operation (one of 'SIGN' and 'VERIFY').
+ * @param connector
+ * The connector being used for the certain operation (one of {@link Constants#SIGNATURE_DEVICE_BKU},
+ * {@link Constants#SIGNATURE_DEVICE_MOA}, {@link Constants#SIGNATURE_DEVICE_MOC},
+ * {@link Constants#SIGNATURE_DEVICE_MOBILE}...)
+ * @param fileSize
+ * The size of the file being processed.
+ */
+ public StatisticData(String operation, String connector, Integer fileSize) {
+ this();
+ this.operation = operation;
+ this.connector = connector;
+ this.fileSize = fileSize;
+ }
+
+ /**
+ * Creates new data for statistical logging purposes.
+ *
+ * @param operation
+ * The operation (one of 'SIGN' and 'VERIFY').
+ * @param connector
+ * The connector being used for the certain operation (one of {@link Constants#SIGNATURE_DEVICE_BKU},
+ * {@link Constants#SIGNATURE_DEVICE_MOA}, {@link Constants#SIGNATURE_DEVICE_MOC},
+ * {@link Constants#SIGNATURE_DEVICE_MOBILE}...)
+ * @param fileSize
+ * The size of the file being processed.
+ * @param signatureMode
+ * The signature mode (one of {@link Constants#SIGNATURE_TYPE_BINARY},
+ * {@link Constants#SIGNATURE_TYPE_BINARY} or {@code null} in case of verification.
+ * @param duration
+ * The duration the certain operation took (in ms).
+ * @param userAgent
+ * The user agent String.
+ */
+ public StatisticData(String operation, String connector, Integer fileSize, String signatureMode, Long duration,
+ String userAgent) {
+ this(operation, connector, fileSize, signatureMode, duration, userAgent, null);
+ }
+
+ /**
+ * Creates statistical data based on given sign parameters.
+ *
+ * @param signParameters
+ * The given sign parameters.
+ */
+ public StatisticData(SignParameters signParameters) {
+ this();
+ operation = "SIGN";
+ connector = signParameters.getSignatureDevice();
+ signatureMode = signParameters.getSignatureType();
+ fileSize = signParameters.getDocument().getLength();
+ signatureProfileId = signParameters.getSignatureProfileId();
+ }
+
+ /**
+ * Creates statistical data based on given verify parameters.
+ *
+ * @param verifyParameters
+ * The given verify parameters.
+ */
+ public StatisticData(VerifyParameters verifyParameters) {
+ this();
+ operation = "VERIFY";
+ connector = verifyParameters.getSignatureDevice();
+ fileSize = verifyParameters.getDocument().getLength();
+ }
+
+ /**
+ * Creates statistical data based on given analyze parameters.
+ *
+ * @param varxdp
+ * The given analyze parameters.
+ */
+ public StatisticData(AnalyzeParameters analyzeParameters) {
+ this();
+ operation = "ANALYZE";
+ fileSize = analyzeParameters.getDocument().getLength();
+ }
+
+ /**
+ * Creates statistical data based on given reconstruction parameters.
+ *
+ * @param rxdaap
+ * The given reconstruction parameters.
+ */
+ public StatisticData(ReconstructXMLDsigAfterAnalysisParameters rxdaap) {
+ this();
+ operation = "RECONSTRUCT";
+ connector = rxdaap.getSignatureDevice();
+ }
+
+ /**
+ * Creates statistical data based on given reconstruction parameters.
+ *
+ * @param reconstructParameters
+ * The given reconstruction parameters.
+ */
+ public StatisticData(ReconstructXMLDsigParameters reconstructParameters) {
+ this();
+ operation = "RECONSTRUCT";
+ fileSize = reconstructParameters.getDocument().getLength();
+ connector = reconstructParameters.getSignatureDevice();
+ }
+
+ /**
+ * Creates statistical data based on given parameters.
+ *
+ * @param vaaParameters
+ * The given verify parameters after analysis.
+ */
+ public StatisticData(VerifyAfterAnalysisParameters vaaParameters) {
+ this();
+ operation = "VERIFY";
+ connector = vaaParameters.getSignatureDevice();
+ }
+
+ /**
+ * Creates statistical data based on given verify parameters after reconstruction.
+ *
+ * @param varxdp
+ * The given verify parameters after reconstruction.
+ */
+ public StatisticData(VerifyAfterReconstructXMLDsigParameters varxdp) {
+ this();
+ operation = "VERIFY";
+ connector = varxdp.getSignatureDevice();
+ }
+
+ /**
+ * Sets the current operation name.
+ *
+ * @param operation
+ * The operation name.
+ */
+ public StatisticData setOperation(String operation) {
+ this.operation = operation;
+ return this;
+ }
+
+ /**
+ * Sets the connector.
+ *
+ * @param connector
+ * The connector.
+ */
+ public StatisticData setConnector(String connector) {
+ this.connector = connector;
+ return this;
+ }
+
+ /**
+ * Sets the file size of the processed document.
+ *
+ * @param fileSize
+ * The file size in bytes.
+ */
+ public StatisticData setFileSize(Integer fileSize) {
+ this.fileSize = fileSize;
+ return this;
+ }
+
+ /**
+ * Sets the duration of the performed operation.
+ *
+ * @param duration
+ * The duration in ms.
+ */
+ public StatisticData setDuration(Long duration) {
+ this.duration = duration;
+ return this;
+ }
+
+ /**
+ * Sets the user agent identifier.
+ *
+ * @param userAgent
+ * The user agent identifier.
+ */
+ public StatisticData setUserAgent(String userAgent) {
+ this.userAgent = userAgent;
+ return this;
+ }
+
+ /**
+ * Sets the signature mode.
+ *
+ * @param signatureMode
+ * The signature mode (one of {@link Constants#SIGNATURE_TYPE_TEXTUAL} and
+ * {@link Constants#SIGNATURE_TYPE_BINARY}).
+ */
+ public StatisticData setSignatureMode(String signatureMode) {
+ this.signatureMode = signatureMode;
+ return this;
+ }
+
+ /**
+ * Sets the profile id.
+ *
+ * @param profileId
+ * The profile id.
+ */
+ public StatisticData setSignatureProfileId(String signatureProfileId) {
+ this.signatureProfileId = signatureProfileId;
+ return this;
+ }
+
+ /**
+ * Sets the exception that has been thrown.
+ *
+ * @param exception
+ * The exception.
+ */
+ public StatisticData setException(Exception exception) {
+ this.exception = exception;
+ return this;
+ }
+
+ /**
+ * Returns {@code true} if an error condition has been set, {@code false} otherwise.
+ *
+ * @return {@code true} in case of an error, {@code false} if not.
+ */
+ public boolean isError() {
+ return exception != null;
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/logging/StatisticLogFactory.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/logging/StatisticLogFactory.java
new file mode 100644
index 0000000..2b6671c
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/logging/StatisticLogFactory.java
@@ -0,0 +1,63 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.framework.logging;
+
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * This factory creates statistic logger implementations.<br/>
+ * Note that it exclusively creates {@link CsvStatisticLogger} implementations at the moment. It should just be regarded
+ * as template for further factory implementations. Strictly speaking this factory does not fulfil the respective GoF
+ * pattern.
+ *
+ * @see StatisticLogger
+ * @author Datentechnik Innovation GmbH
+ */
+public class StatisticLogFactory {
+
+ /**
+ * Returns a statistic logger implementation.
+ *
+ * @param clazz
+ * The class.
+ * @return A statistic logger implementation.
+ */
+ public static StatisticLogger getLog(Class<?> clazz) {
+ return getLog(clazz.getName());
+ }
+
+ /**
+ * Returns a statistic logger implementation.
+ *
+ * @param name
+ * The name of the logger.
+ * @return A statistic logger implementation.
+ */
+ public static StatisticLogger getLog(String name) {
+
+ // to be changed some day, producing various logger implementations
+ return new CsvStatisticLogger(LogFactory.getLog(name));
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/logging/StatisticLogger.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/logging/StatisticLogger.java
new file mode 100644
index 0000000..6e2c587
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/logging/StatisticLogger.java
@@ -0,0 +1,47 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.framework.logging;
+
+/**
+ *
+ * @author Datentechnik Innovation GmbH
+ */
+public interface StatisticLogger {
+
+ /**
+ * Creates a log entry with the given statistical data.
+ *
+ * @param statisticData
+ * The statistical data.
+ */
+ public void log(StatisticData statisticData);
+
+ /**
+ * Returns {@code true} in case the logger is enabled, {@code false} if not.
+ *
+ * @return {@code true} in case the logger is enabled, {@code false} if not.
+ */
+ public boolean isEnabled();
+
+}
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/PdfAsObject.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/PdfAsObject.java
index eda94c0..a2bcd15 100644
--- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/PdfAsObject.java
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/PdfAsObject.java
@@ -33,6 +33,7 @@ import java.util.Properties;
import java.util.Vector;
import org.apache.commons.lang.math.NumberUtils;
+import org.apache.commons.lang.time.StopWatch;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -66,6 +67,9 @@ import at.gv.egiz.pdfas.framework.DataSourceHolder;
import at.gv.egiz.pdfas.framework.config.SettingsHelper;
import at.gv.egiz.pdfas.framework.input.ExtractionStage;
import at.gv.egiz.pdfas.framework.input.PdfDataSource;
+import at.gv.egiz.pdfas.framework.logging.StatisticData;
+import at.gv.egiz.pdfas.framework.logging.StatisticLogFactory;
+import at.gv.egiz.pdfas.framework.logging.StatisticLogger;
import at.gv.egiz.pdfas.framework.signator.Signator;
import at.gv.egiz.pdfas.framework.signator.SignatorInformation;
import at.gv.egiz.pdfas.framework.vfilter.VerificationFilterParameters;
@@ -87,6 +91,7 @@ import at.gv.egiz.pdfas.placeholder.SignaturePlaceholderContext;
import at.gv.egiz.pdfas.placeholder.SignaturePlaceholderData;
import at.gv.egiz.pdfas.placeholder.SignaturePlaceholderExtractor;
import at.gv.egiz.pdfas.utils.ConfigUtils;
+import at.gv.egiz.pdfas.utils.PDFASUtils;
import at.knowcenter.wag.egov.egiz.PdfAS;
import at.knowcenter.wag.egov.egiz.PdfASID;
import at.knowcenter.wag.egov.egiz.cfg.OverridePropertyHolder;
@@ -111,12 +116,13 @@ import at.knowcenter.wag.egov.egiz.sig.SignatureDataImpl;
import at.knowcenter.wag.egov.egiz.sig.SignatureResponse;
import at.knowcenter.wag.egov.egiz.sig.SignatureTypeDefinition;
import at.knowcenter.wag.egov.egiz.sig.SignatureTypes;
+import at.knowcenter.wag.egov.egiz.sig.SignatureTypes.State;
import at.knowcenter.wag.egov.egiz.sig.connectors.Connector;
import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject;
/**
* Implementation of the {@link PdfAs} interface.
- *
+ *
* @author wprinz
*/
public class PdfAsObject implements PdfAs
@@ -127,25 +133,26 @@ public class PdfAsObject implements PdfAs
* The log.
*/
private static Log log = LogFactory.getLog(PdfAsObject.class);
-
+ private static StatisticLogger statLog = StatisticLogFactory.getLog(Constants.STATISTIC_LOGGER_NAME);
+
private static final String ENABLE_PLACEHOLDER_SEARCH_KEY = "enable_placeholder_search";
-
+
/**
* Configuration key for minimal signature block width threshold. Any width below this certain value will lead to a warning log entry."
*/
private static final String SIGNATURE_BLOCK_WIDTH_THRESHOLD_FOR_WARNING_KEY = "signature_block_width_warning_threshold";
-
+
/**
* Minimal signature block width. If a width below that value is defined (by parameter, by placeholder or by configuration) a warning log entry is created.
*/
public static final float DEFAULT_SIGNATURE_BLOCK_WIDTH_THRESHOLD = 150;
-
+
/**
* This constructor is for internal use only - use
* {@link at.gv.egiz.pdfas.PdfAsFactory} instead.
* Note: IAIK JCE and IAIK ECC security providers are automatically registered.
- *
+ *
* @param workDirectory
* The work directory.
* @throws PdfAsException
@@ -155,16 +162,16 @@ public class PdfAsObject implements PdfAs
{
this(workDirectory, SettingsReader.REGISTER_IAIK_PROVIDERS_ON_DEFAULT);
}
-
+
/**
* This constructor is for internal use only - use
* {@link at.gv.egiz.pdfas.PdfAsFactory} instead.
- *
+ *
* @param workDirectory
* The work directory.
* @param registerProvider <code>true</code>: automatically registers IAIK JCE and ECC Provider;
* <code>false</code>: 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 PdfAsException
* Thrown, if the configuration cannot be processed.
*/
@@ -174,12 +181,12 @@ public class PdfAsObject implements PdfAs
SettingsReader.initialize(path, path);
reloadConfig(registerProvider);
}
-
+
/**
* This constructor is for internal use only - use
* {@link at.gv.egiz.pdfas.PdfAsFactory} instead.
* Note: IAIK JCE and IAIK ECC security providers are automatically registered.
- *
+ *
* @throws PdfAsException
* Thrown, if the configuration cannot be processed.
*/
@@ -187,7 +194,7 @@ public class PdfAsObject implements PdfAs
{
this(null);
}
-
+
/**
* @see at.gv.egiz.pdfas.api.PdfAs#reloadConfig()
*/
@@ -197,11 +204,11 @@ public class PdfAsObject implements PdfAs
SettingsReader.createInstance();
SignatureTypes.createInstance();
}
-
+
/**
* @param registerProvider <code>true</code>: automatically registers IAIK JCE and ECC Provider;
* <code>false</code>: 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
* @see at.gv.egiz.pdfas.api.PdfAs#reloadConfig()
*/
private void reloadConfig(boolean registerProvider) throws PdfAsException
@@ -228,7 +235,7 @@ public class PdfAsObject implements PdfAs
List profileInformation = new ArrayList(profiles.size());
String default_type = settings.getValueFromKey(SignatureTypes.DEFAULT_TYPE);
-
+
Iterator it = profiles.iterator();
while (it.hasNext())
{
@@ -240,14 +247,17 @@ public class PdfAsObject implements PdfAs
final String profileDescription = settings.getSetting("sig_obj." + profileId + "." + SignatureTypes.SIG_DESCR, null);
boolean isDefault = (default_type != null && default_type.equals(profileId));
+
+ State state = State.fromString(settings.getSetting(SignatureTypes.TYPES + "." + profileId));
+
// modified by tknall
- SignatureProfileImpl signatureProfile = new SignatureProfileImpl(profileId, profileDescription, moaKeyIdentifier, isDefault);
+ SignatureProfileImpl signatureProfile = new SignatureProfileImpl(profileId, state, profileDescription, moaKeyIdentifier, isDefault);
// start - added by tknall
-
+
// signature entries relevant to the search algorithm
Properties signatureEntries = new Properties();
-
+
// search for table entries
String parentPropertyKey = "sig_obj." + profileId + ".table";
log.debug("Looking for subkeys of \"" + parentPropertyKey + "\".");
@@ -275,7 +285,7 @@ public class PdfAsObject implements PdfAs
}
}
}
-
+
// search for table entries
parentPropertyKey = "sig_obj." + profileId + ".key";
log.debug("Looking for subkeys of \"" + parentPropertyKey + "\".");
@@ -295,46 +305,89 @@ public class PdfAsObject implements PdfAs
}
}
}
-
+
// set properties
signatureProfile.setSignatureBlockEntries(signatureEntries);
// stop - added by tknall
-
+
profileInformation.add(signatureProfile);
}
return profileInformation;
}
- /**
- * @see at.gv.egiz.pdfas.api.PdfAs#sign(at.gv.egiz.pdfas.api.sign.SignParameters)
- */
- public SignResult sign(SignParameters signParameters) throws PdfAsException
+ public SignResult sign(SignParameters signParameters) throws PdfAsException {
+ // prepare log data
+ StatisticData sd = new StatisticData(signParameters);
+ StopWatch sw = new StopWatch();
+ try {
+ sw.start();
+ return performSign(signParameters);
+ } catch (PdfAsException e) {
+ sd.setException(e);
+ throw e;
+ } catch (RuntimeException e) {
+ sd.setException(e);
+ throw e;
+ } finally {
+ sw.stop();
+ sd.setDuration(sw.getTime());
+ statLog.log(sd);
+ }
+ }
+
+ private SignResult performSign(SignParameters signParameters) throws PdfAsException
{
CheckHelper.checkSignParameters(signParameters, false);
-
+
+ // make sure that the selected profile is allowed to be used for signature
+ SettingsReader settings = SettingsReader.getInstance();
+ if (!State.fromString(settings.getSetting(SignatureTypes.TYPES + "." + signParameters.getSignatureProfileId()))
+ .canSign()) {
+ throw new SignatureException(ErrorCode.SIGNATURE_PROFILE_IS_NOT_ALLOWED_FOR_SIGNATURE,
+ "The signature profile '" + signParameters.getSignatureProfileId()
+ + "' is not allowed to be used for signature.");
+ }
+
try {
- SignatureDetailInformation signatorInfo = prepareSign(signParameters);
-
- return sign(signParameters, signatorInfo);
-
+
+ SignatureDetailInformation signatorInfo = performPrepareSign(signParameters);
+ return performSign(signParameters, signatorInfo);
+
} catch (java.lang.OutOfMemoryError e) {
throw new OutOfMemoryException(ErrorCode.OUT_OF_MEMORY_ERROR, "Insufficient memory allocated to virtual machine. Start Java with parameters \"-Xms128m -Xmx786m -XX:MaxPermSize=256m\".", e);
}
}
- /**
- * @see at.gv.egiz.pdfas.api.PdfAs#verify(at.gv.egiz.pdfas.api.verify.VerifyParameters)
- */
- public VerifyResults verify(VerifyParameters verifyParameters) throws PdfAsException
+ public VerifyResults verify(VerifyParameters verifyParameters) throws PdfAsException {
+ // prepare log data
+ StatisticData sd = new StatisticData(verifyParameters);
+ StopWatch sw = new StopWatch();
+ try {
+ sw.start();
+ return performVerify(verifyParameters);
+ } catch (PdfAsException e) {
+ sd.setException(e);
+ throw e;
+ } catch (RuntimeException e) {
+ sd.setException(e);
+ throw e;
+ } finally {
+ sw.stop();
+ sd.setDuration(sw.getTime());
+ statLog.log(sd);
+ }
+ }
+
+ private VerifyResults performVerify(VerifyParameters verifyParameters) throws PdfAsException
{
CheckHelper.checkVerifyParameters(verifyParameters);
AnalyzeParameters ap = new AnalyzeParameters();
fillAnalyzeParametersWithVerifyParameters(ap, verifyParameters);
- AnalyzeResult analyzeResult = analyze(ap);
+ AnalyzeResult analyzeResult = performAnalyze(ap);
if (verifyParameters.getSignatureToVerify() != Constants.VERIFY_ALL)
{
@@ -352,17 +405,17 @@ public class PdfAsObject implements PdfAs
VerifyAfterAnalysisParameters vaap = new VerifyAfterAnalysisParameters();
vaap.setAnalyzeResult(analyzeResult);
fillVerifyAfterAnalysisParametersWithVerifyParameters(vaap, verifyParameters);
- VerifyResults res = verify(vaap);
-
+ VerifyResults res = performVerify(vaap);
+
return res;
-
+
}
-
+
/**
* Copies all adequate parameters from the {@link VerifyParameters} to the
* {@link AnalyzeParameters}.
- *
+ *
* @param ap
* The {@link AnalyzeParameters}.
* @param vp
@@ -385,7 +438,7 @@ public class PdfAsObject implements PdfAs
/**
* Copies all adequate parameters from the {@link VerifyParameters} to the
* {@link VerifyAfterAnalysisParameters}.
- *
+ *
* @param vaap
* The {@link VerifyAfterAnalysisParameters}.
* @param vp
@@ -406,10 +459,30 @@ public class PdfAsObject implements PdfAs
reconstructParams.setSignatureDevice(verifyAfterAnalysisParameters.getSignatureDevice());
}
- /**
- * @see at.gv.egiz.pdfas.api.PdfAs#analyze(at.gv.egiz.pdfas.api.analyze.AnalyzeParameters)
- */
- public AnalyzeResult analyze(AnalyzeParameters analyzeParameters) throws PdfAsException
+ public AnalyzeResult analyze(AnalyzeParameters analyzeParameters) throws PdfAsException {
+ // prepare log data
+ StatisticData sd = new StatisticData(analyzeParameters);
+ StopWatch sw = new StopWatch();
+ try {
+ sw.start();
+ return performAnalyze(analyzeParameters);
+ } catch (PdfAsException e) {
+ sd.setException(e);
+ throw e;
+ } catch (RuntimeException e) {
+ sd.setException(e);
+ throw e;
+ } finally {
+ sw.stop();
+ sd.setDuration(sw.getTime());
+ // only log in case of error
+ if (sd.isError()) {
+ statLog.log(sd);
+ }
+ }
+ }
+
+ private AnalyzeResult performAnalyze(AnalyzeParameters analyzeParameters) throws PdfAsException
{
CheckHelper.checkAnalyzeParameters(analyzeParameters);
@@ -429,10 +502,12 @@ public class PdfAsObject implements PdfAs
assumeOnlySB = false;
}
VerificationFilterParameters parameters = new VerificationFilterParametersImpl(binaryOnly, assumeOnlySB, parametersConfig.scanForOldSignatures());
-
+
at.gv.egiz.pdfas.framework.input.DataSource inputDataSource = null;
if (analyzeParameters.getDocument().getMimeType().equals("application/pdf"))
{
+ // check document permissions
+ PDFASUtils.createPdfReaderCheckingPermissions(analyzeParameters.getDocument());
inputDataSource = new PdfDataSourceAdapter(analyzeParameters.getDocument());
}
else
@@ -447,13 +522,13 @@ public class PdfAsObject implements PdfAs
}
}
assert inputDataSource != null;
-
+
try {
ExtractionStage es = new ExtractionStage();
DataSourceHolder dsh = new DataSourceHolder(inputDataSource);
List signature_holders = es.extractSignatureHolders(dsh, parameters);
-
-
+
+
// List sigInfs = new ArrayList(signature_holders.size());
List sigInfs = new ArrayList();
List noSigs = new ArrayList();
@@ -461,24 +536,24 @@ public class PdfAsObject implements PdfAs
while (it.hasNext())
{
SignatureHolder sh = (SignatureHolder)it.next();
-
+
if(sh instanceof NoSignatureHolder) {
noSigs.add(sh);
} else {
-
+
SignatureInformation si = new SignatureInformationAdapter(sh);
sigInfs.add(si);
- if (analyzeParameters.isReturnNonTextualObjects()) {
- si.setNonTextualObjects(doExtractNonTexualObjects(sh, (PdfDataSource) dsh.getDataSource()));
- }
-
+ if (analyzeParameters.isReturnNonTextualObjects()) {
+ si.setNonTextualObjects(doExtractNonTexualObjects(sh, (PdfDataSource) dsh.getDataSource()));
+ }
+
}
}
return new AnalyzeResultImpl(sigInfs, noSigs, parameters.hasBeenCorrected());
} catch (java.lang.OutOfMemoryError e) {
throw new OutOfMemoryException(ErrorCode.OUT_OF_MEMORY_ERROR, "Insufficient memory allocated to virtual machine. Start Java with parameters \"-Xms128m -Xmx786m -XX:MaxPermSize=256m\".", e);
}
-
+
}
private List doExtractNonTexualObjects(SignatureHolder sh, PdfDataSource pdfDataSource) {
@@ -499,30 +574,47 @@ public class PdfAsObject implements PdfAs
}
}
-/**
- * @see at.gv.egiz.pdfas.api.PdfAs#verify(at.gv.egiz.pdfas.api.verify.VerifyAfterAnalysisParameters)
- */
- public VerifyResults verify(VerifyAfterAnalysisParameters verifyAfterAnalysisParameters) throws PdfAsException
+ public VerifyResults verify(VerifyAfterAnalysisParameters verifyAfterAnalysisParameters) throws PdfAsException {
+ // prepare log data
+ StatisticData sd = new StatisticData(verifyAfterAnalysisParameters);
+ StopWatch sw = new StopWatch();
+ try {
+ sw.start();
+ return performVerify(verifyAfterAnalysisParameters);
+ } catch (PdfAsException e) {
+ sd.setException(e);
+ throw e;
+ } catch (RuntimeException e) {
+ sd.setException(e);
+ throw e;
+ } finally {
+ sw.stop();
+ sd.setDuration(sw.getTime());
+ statLog.log(sd);
+ }
+ }
+
+ private VerifyResults performVerify(VerifyAfterAnalysisParameters verifyAfterAnalysisParameters) throws PdfAsException
{
CheckHelper.checkVerifyAfterAnalysisParameters(verifyAfterAnalysisParameters);
List signatures = verifyAfterAnalysisParameters.getAnalyzeResult().getSignatures();
-
+
// added by tknall
if (signatures == null || signatures.isEmpty()) {
throw new PDFDocumentException(ErrorCode.DOCUMENT_NOT_SIGNED, "PDF document not signed."); //$NON-NLS-1$
}
-
+
ReconstructXMLDsigAfterAnalysisParameters rxaap = new ReconstructXMLDsigAfterAnalysisParameters();
fillReconstructXMLDsigAfterAnalysisParametersWithVerifyAfterAnalysisParameters(rxaap, verifyAfterAnalysisParameters);
- ReconstructXMLDsigResult reconstructResult = reconstructXMLDSIG(rxaap);
-
+ ReconstructXMLDsigResult reconstructResult = performReconstructXMLDSIG(rxaap);
+
VerifyAfterReconstructXMLDsigParameters varxp = new VerifyAfterReconstructXMLDsigParameters();
fillVerifyAfterReconstructXMLDsigParametersWithVerifyAfterAnalysisParameters(varxp, verifyAfterAnalysisParameters);
varxp.setReconstructXMLDsigResult(reconstructResult);
-
- return verify(varxp);
-
+
+ return performVerify(varxp);
+
}
protected void fillVerifyAfterReconstructXMLDsigParametersWithVerifyAfterAnalysisParameters(
@@ -534,31 +626,75 @@ public class PdfAsObject implements PdfAs
varxp.setVerifySignatureIndex(verifyAfterAnalysisParameters.getVerifySignatureIndex());
}
- /**
- * @see PdfAs#reconstructXMLDSIG(ReconstructXMLDsigParameters)
- */
public ReconstructXMLDsigResult reconstructXMLDSIG(
+ ReconstructXMLDsigParameters reconstructXMLDsigParameters)
+ throws PdfAsException {
+ // prepare log data
+ StatisticData sd = new StatisticData(reconstructXMLDsigParameters);
+ StopWatch sw = new StopWatch();
+ try {
+ sw.start();
+ return performReconstructXMLDSIG(reconstructXMLDsigParameters);
+ } catch (PdfAsException e) {
+ sd.setException(e);
+ throw e;
+ } catch (RuntimeException e) {
+ sd.setException(e);
+ throw e;
+ } finally {
+ sw.stop();
+ sd.setDuration(sw.getTime());
+ // only log in case of error
+ if (sd.isError()) {
+ statLog.log(sd);
+ }
+ }
+ }
+
+ private ReconstructXMLDsigResult performReconstructXMLDSIG(
ReconstructXMLDsigParameters reconstructXMLDsigParameters)
throws PdfAsException {
-
+
AnalyzeParameters analyzeParameters = new AnalyzeParameters();
fillAnalyzeParametersWithReconstructXMLDsigParameters(analyzeParameters, reconstructXMLDsigParameters);
- AnalyzeResult ar = analyze(analyzeParameters);
-
+ AnalyzeResult ar = performAnalyze(analyzeParameters);
+
ReconstructXMLDsigAfterAnalysisParameters rxaap = new ReconstructXMLDsigAfterAnalysisParameters();
rxaap.setSignatureDevice(reconstructXMLDsigParameters.getSignatureDevice());
rxaap.setAnalyzeResult(ar);
-
- return reconstructXMLDSIG(rxaap);
+
+ return performReconstructXMLDSIG(rxaap);
}
- /**
- * @see PdfAs#reconstructXMLDSIG(ReconstructXMLDsigAfterAnalysisParameters)
- */
public ReconstructXMLDsigResult reconstructXMLDSIG(
+ ReconstructXMLDsigAfterAnalysisParameters reconstructXMLDsigParameters)
+ throws PdfAsException {
+ // prepare log data
+ StatisticData sd = new StatisticData(reconstructXMLDsigParameters);
+ StopWatch sw = new StopWatch();
+ try {
+ sw.start();
+ return performReconstructXMLDSIG(reconstructXMLDsigParameters);
+ } catch (PdfAsException e) {
+ sd.setException(e);
+ throw e;
+ } catch (RuntimeException e) {
+ sd.setException(e);
+ throw e;
+ } finally {
+ sw.stop();
+ sd.setDuration(sw.getTime());
+ // only log in case of error
+ if (sd.isError()) {
+ statLog.log(sd);
+ }
+ }
+ }
+
+ private ReconstructXMLDsigResult performReconstructXMLDSIG(
ReconstructXMLDsigAfterAnalysisParameters reconstructXMLDsigParameters)
throws PdfAsException {
-
+
AnalyzeResult ar = reconstructXMLDsigParameters.getAnalyzeResult();
List extendedSignatureInfos = new Vector();
for (int i = 0; i < ar.getSignatures().size(); i++)
@@ -572,31 +708,52 @@ public class PdfAsObject implements PdfAs
// don't care for connector exceptions because of mutli signs. they are handled during verify
extendedSignatureInfos.add(new ExtendedSignatureInformation(si, null));
}
-
+
}
return new ReconstructXMLDsigResult(extendedSignatureInfos, reconstructXMLDsigParameters.getSignatureDevice());
}
+ public VerifyResults verify(VerifyAfterReconstructXMLDsigParameters verifyAfterReconstructXMLDsigParameters)
+ throws PdfAsException {
+ // prepare log data
+ StatisticData sd = new StatisticData(verifyAfterReconstructXMLDsigParameters);
+ StopWatch sw = new StopWatch();
+ try {
+ sw.start();
+ return performVerify(verifyAfterReconstructXMLDsigParameters);
+ } catch (PdfAsException e) {
+ sd.setException(e);
+ throw e;
+ } catch (RuntimeException e) {
+ sd.setException(e);
+ throw e;
+ } finally {
+ sw.stop();
+ sd.setDuration(sw.getTime());
+ statLog.log(sd);
+ }
+ }
+
/**
* @see PdfAs#verify(VerifyAfterReconstructXMLDsigParameters)
*/
- public VerifyResults verify(
+ private VerifyResults performVerify(
VerifyAfterReconstructXMLDsigParameters verifyAfterReconstructXMLDsigParameters)
throws PdfAsException {
-
+
try {
List extSignatures = verifyAfterReconstructXMLDsigParameters.getReconstructXMLDsigResult().getExtendedSignatures();
String signatureDevice = verifyAfterReconstructXMLDsigParameters.getSignatureDevice();
if (signatureDevice == null){
signatureDevice = verifyAfterReconstructXMLDsigParameters.getReconstructXMLDsigResult().getDevice();
}
- List results = PdfAS.verifyExtendedSignatureHolders(extSignatures,
- signatureDevice,
- verifyAfterReconstructXMLDsigParameters.isReturnHashInputData(),
+ List results = PdfAS.verifyExtendedSignatureHolders(extSignatures,
+ signatureDevice,
+ verifyAfterReconstructXMLDsigParameters.isReturnHashInputData(),
verifyAfterReconstructXMLDsigParameters.getVerificationTime(), verifyAfterReconstructXMLDsigParameters.getVerifySignatureIndex());
-
+
List vrs = new ArrayList(results.size());
-
+
int verifySignatureIndex = verifyAfterReconstructXMLDsigParameters.getVerifySignatureIndex();
if (verifySignatureIndex < 0)
{
@@ -605,23 +762,23 @@ public class PdfAsObject implements PdfAs
SignatureResponse response = (SignatureResponse) results.get(i);
ExtendedSignatureInformation extSigInfo = (ExtendedSignatureInformation)extSignatures.get(i);
SignatureHolder holder = (SignatureHolder) extSigInfo.getSignatureInformation().getInternalSignatureInformation();
-
+
VerifyResult vr = new VerifyResultAdapter(response, holder, verifyAfterReconstructXMLDsigParameters.getVerificationTime(), extSigInfo.getXmlDsigData());
vr.setNonTextualObjects( extSigInfo.getSignatureInformation().getNonTextualObjects());
-
+
vrs.add(vr);
}
}else{
SignatureResponse response = (SignatureResponse) results.get(0);
ExtendedSignatureInformation extSigInfo = (ExtendedSignatureInformation)extSignatures.get(verifySignatureIndex);
SignatureHolder holder = (SignatureHolder) extSigInfo.getSignatureInformation().getInternalSignatureInformation();
-
+
VerifyResult vr = new VerifyResultAdapter(response, holder, verifyAfterReconstructXMLDsigParameters.getVerificationTime(), extSigInfo.getXmlDsigData());
vr.setNonTextualObjects( extSigInfo.getSignatureInformation().getNonTextualObjects());
-
+
vrs.add(vr);
}
-
+
VerifyResultsImpl verifyResults = new VerifyResultsImpl(vrs);
return verifyResults;
} catch (java.lang.OutOfMemoryError e) {
@@ -632,7 +789,7 @@ public class PdfAsObject implements PdfAs
public DynamicSignatureProfile createDynamicSignatureProfile(String parentProfile, DynamicSignatureLifetimeEnum mode) {
return DynamicSignatureProfileImpl.createFromParent(null, parentProfile, mode);
}
-
+
public DynamicSignatureProfile createEmptyDynamicSignatureProfile(DynamicSignatureLifetimeEnum mode) {
return DynamicSignatureProfileImpl.createEmptyProfile(null, mode);
}
@@ -648,19 +805,44 @@ public class PdfAsObject implements PdfAs
public DynamicSignatureProfile createEmptyDynamicSignatureProfile(String myUniqueName,
DynamicSignatureLifetimeEnum mode) {
- return DynamicSignatureProfileImpl.createEmptyProfile(myUniqueName, mode);
+ return DynamicSignatureProfileImpl.createEmptyProfile(myUniqueName, mode);
+ }
+
+ public SignatureDetailInformation prepareSign(SignParameters signParameters) throws PdfAsException {
+ // prepare log data
+ StatisticData sd = new StatisticData(signParameters);
+ StopWatch sw = new StopWatch();
+ try {
+ sw.start();
+ return performPrepareSign(signParameters);
+ } catch (PdfAsException e) {
+ sd.setException(e);
+ throw e;
+ } catch (RuntimeException e) {
+ sd.setException(e);
+ throw e;
+ } finally {
+ sw.stop();
+ sd.setDuration(sw.getTime());
+ // only log in case of error
+ if (sd.isError()) {
+ statLog.log(sd);
+ }
+ }
}
/**
* @see PdfAs#prepareSign(SignParameters)
*/
- public SignatureDetailInformation prepareSign(SignParameters signParameters) throws PdfAsException {
+ private SignatureDetailInformation performPrepareSign(SignParameters signParameters) throws PdfAsException {
CheckHelper.checkSignParameters(signParameters, true);
-
+
if (signParameters.getProfileOverrideProperties() != null) {
OverridePropertyHolder.setOverrideProps(signParameters.getProfileOverrideProperties());
}
+ PDFASUtils.createPdfReaderCheckingPermissions(signParameters.getDocument());
+
signParameters.setDocument(PdfAS.applyStrictMode(signParameters.getDocument()));
SettingsReader settings = SettingsReader.getInstance();
@@ -730,29 +912,29 @@ public class PdfAsObject implements PdfAs
} else if (fromConfig) {
arguments[0] = "width defined by the profile " + signParameters.getSignatureProfileId();
}
- log.warn(MessageFormat.format(msg, arguments));
+ log.warn(MessageFormat.format(msg, (Object[]) arguments));
}
}
-
+
Signator signator = createSignator(signParameters.getSignatureType());
SignatorInformation signatorInfo = signator.prepareSign(
- new PdfDataSourceAdapter(signParameters.getDocument()),
- signParameters.getSignatureProfileId(),
- pos,
+ new PdfDataSourceAdapter(signParameters.getDocument()),
+ signParameters.getSignatureProfileId(),
+ pos,
signParameters.getTimeStamperImpl());
-
+
SignatureDetailInformationImpl ret = new SignatureDetailInformationImpl();
ret.setSignatorInformation(signatorInfo);
return ret;
}
-
+
private SignaturePlaceholderData getSignaturePlaceholder(SignParameters signParameters,
String defaultProfile) throws SettingsException, PDFDocumentException, PlaceholderExtractionException {
SignaturePlaceholderData spd = null;
SignaturePlaceholderContext.setSignaturePlaceholderData(null);
-
+
SettingsReader settings = SettingsReader.getInstance();
// check sig_obj.PROFILEID.enable_placeholder_search
@@ -766,15 +948,15 @@ public class PdfAsObject implements PdfAs
// check global enable_placeholder_search
configFileActivedString = settings.getValueFromKey(ENABLE_PLACEHOLDER_SEARCH_KEY);
}
-
+
Boolean configFileActived = null;
if (configFileActivedString != null)
configFileActived = Boolean.valueOf(configFileActivedString);
Boolean signParamsActivated = signParameters.isCheckForPlaceholder();
-
+
boolean enableSearch;
-
+
if (signParamsActivated != null)
{
enableSearch = signParamsActivated.booleanValue();
@@ -788,8 +970,8 @@ public class PdfAsObject implements PdfAs
if (enableSearch)
{
spd = SignaturePlaceholderExtractor.extract(
- signParameters.getDocument().createInputStream(),
- signParameters.getPlaceholderId(),
+ signParameters.getDocument().createInputStream(),
+ signParameters.getPlaceholderId(),
signParameters.getPlaceholderMatchMode());
}
return spd;
@@ -809,15 +991,36 @@ public class PdfAsObject implements PdfAs
{
signatorId = SignatorFactory.MOST_RECENT_DETACHEDTEXT_SIGNATOR_ID;
}
-
+
return at.gv.egiz.pdfas.framework.SignatorFactory.createSignator(signatorId);
}
- public SignResult sign(SignParameters signParameters, SignatureDetailInformation signatorInfo)
+ public SignResult sign(SignParameters signParameters, SignatureDetailInformation signatorInfo)
+ throws PdfAsException {
+ // prepare log data
+ StatisticData sd = new StatisticData(signParameters);
+ StopWatch sw = new StopWatch();
+ try {
+ sw.start();
+ return performSign(signParameters, signatorInfo);
+ } catch (PdfAsException e) {
+ sd.setException(e);
+ throw e;
+ } catch (RuntimeException e) {
+ sd.setException(e);
+ throw e;
+ } finally {
+ sw.stop();
+ sd.setDuration(sw.getTime());
+ statLog.log(sd);
+ }
+ }
+
+ private SignResult performSign(SignParameters signParameters, SignatureDetailInformation signatorInfo)
throws PdfAsException {
CheckHelper.checkSignParametersForSignAfterPrepare(signParameters, false);
-
+
if (signParameters.getProfileOverrideProperties() != null) {
OverridePropertyHolder.setOverrideProps(signParameters.getProfileOverrideProperties());
}
@@ -832,34 +1035,34 @@ public class PdfAsObject implements PdfAs
SignatureData sd = new SignatureDataImpl(new PdfDataSourceAdapter(signatorInfo.getSignatureData()), signatorInfo.getSignatureData().getMimeType());
SignSignatureObject sso = PdfAS.sign(sd, c, signParameters.getTimeStamperImpl());
((SignatureDetailInformationImpl)signatorInfo).setSignSignatureObject(sso);
-
+
return finishSign(signParameters, signatorInfo);
}
- public SignResult finishSign(SignParameters signParameters, SignatureDetailInformation signatureDetailInformation)
+ public SignResult finishSign(SignParameters signParameters, SignatureDetailInformation signatureDetailInformation)
throws PdfAsException {
try {
CheckHelper.checkSignParametersForSignAfterPrepare(signParameters, true);
CheckHelper.checkSignatureDetailInformation(signatureDetailInformation);
-
+
if (signParameters.getProfileOverrideProperties() != null) {
OverridePropertyHolder.setOverrideProps(signParameters.getProfileOverrideProperties());
}
-
+
Signator signator = createSignator(signParameters.getSignatureType());
SignatorInformation signatorInfo = ((SignatureDetailInformationImpl)signatureDetailInformation).getSignatorInfo();
signator.finishSign(signatorInfo, new DataSinkAdapter(signParameters.getOutput()));
return new SignResultImpl(
- signParameters.getOutput(),
+ signParameters.getOutput(),
signatorInfo.getSignSignatureObject().getX509Certificate(),
- new ActualSignaturePositionAdapter(signatorInfo.getActualTablePos()),
+ new ActualSignaturePositionAdapter(signatorInfo.getActualTablePos()),
signatorInfo.getNonTextualObjects());
} finally {
OverridePropertyHolder.removeProperties();
DynamicSignatureProfileImpl.disposeLocalProfile();
}
}
-
+
}
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/DataSinkAdapter.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/DataSinkAdapter.java
index 2aee44f..b91d5a9 100644
--- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/DataSinkAdapter.java
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/DataSinkAdapter.java
@@ -30,7 +30,7 @@ import at.gv.egiz.pdfas.api.io.DataSink;
/**
* Adapter that converts an API DataSink to a framework DataSink.
- *
+ *
* @author wprinz
*/
public class DataSinkAdapter implements at.gv.egiz.pdfas.framework.output.DataSink
@@ -42,7 +42,7 @@ public class DataSinkAdapter implements at.gv.egiz.pdfas.framework.output.DataSi
/**
* Constructor.
- *
+ *
* @param apiDataSink
* The API DataSink to be adapted to a framework DataSink.
*/
@@ -62,7 +62,6 @@ public class DataSinkAdapter implements at.gv.egiz.pdfas.framework.output.DataSi
}
catch (IOException e)
{
- e.printStackTrace();
throw new RuntimeException(e);
}
}
@@ -79,7 +78,6 @@ public class DataSinkAdapter implements at.gv.egiz.pdfas.framework.output.DataSi
}
catch (IOException e)
{
- e.printStackTrace();
throw new RuntimeException(e);
}
}
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/SignatureProfileImpl.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/SignatureProfileImpl.java
index 35d8c17..1df1a65 100644
--- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/SignatureProfileImpl.java
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/SignatureProfileImpl.java
@@ -28,6 +28,7 @@ import java.util.Properties;
import org.apache.commons.lang.builder.ToStringBuilder;
import at.gv.egiz.pdfas.api.commons.SignatureProfile;
+import at.knowcenter.wag.egov.egiz.sig.SignatureTypes.State;
/**
* Holds the data of a signature profile.
@@ -61,6 +62,13 @@ public class SignatureProfileImpl implements SignatureProfile {
* true if this is the default profile, false otherwise.
*/
protected boolean defaultProfile = false;
+
+ /**
+ * The state of the signature profile. Signature profiles may be disabled (OFF), allowed for signature only
+ * (SIGN_ONLY), allowed for verification only (VERIFY_ONLY) or just enabled (ON).
+ * Default value here of ON in order to assure backward compatibility.
+ */
+ private State state = State.ON;
/**
* Constructor.
@@ -88,14 +96,26 @@ public class SignatureProfileImpl implements SignatureProfile {
* @param isDefault
*/
public SignatureProfileImpl(String profileId, String profileDescription, String moaKeyIdentifier, boolean isDefault) {
- this.profileId = profileId;
- this.moaKeyIdentifier = moaKeyIdentifier;
- this.profileDescription = profileDescription;
- this.signatureBlockEntries = new Properties();
- this.defaultProfile = isDefault;
+ this(profileId, moaKeyIdentifier);
+ this.profileDescription = profileDescription;
+ this.defaultProfile = isDefault;
}
/**
+ * Creates a new signature profile instance.
+ * @param profileId The profile identifier.
+ * @param state The profile's state.
+ * @param profileDescription The profile description.
+ * @param moaKeyIdentifier The MOA-SS key identifier.
+ * @param isDefault {@code true} if this is a default profile, {@code false} if not.
+ */
+ public SignatureProfileImpl(String profileId, State state, String profileDescription, String moaKeyIdentifier, boolean isDefault) {
+ this(profileId, profileDescription, moaKeyIdentifier, isDefault);
+ this.state = state;
+ }
+
+
+ /**
* @see at.gv.egiz.pdfas.api.commons.SignatureProfile#getProfileId()
*/
public String getProfileId() {
@@ -140,19 +160,22 @@ public class SignatureProfileImpl implements SignatureProfile {
return this.profileDescription;
}
- public String toString() {
- return new ToStringBuilder(this)
- .append("profileId", this.profileId)
- .append("profileDescription", this.profileDescription)
- .append("moaKeyIdentifier", this.moaKeyIdentifier)
- .toString();
- }
+ @Override
+ public String toString() {
+ return "SignatureProfileImpl [profileId=" + profileId + ", state=" + state + ", profileDescription="
+ + profileDescription + ", moaKeyIdentifier=" + moaKeyIdentifier + ", defaultProfile=" + defaultProfile
+ + "]";
+ }
- /**
+/**
*
*/
public boolean isDefault() {
return this.defaultProfile;
}
+ public State getState() {
+ return state;
+ }
+
}
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/correction/InternalCorrector.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/correction/InternalCorrector.java
index eaa6b7f..b193936 100644
--- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/correction/InternalCorrector.java
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/correction/InternalCorrector.java
@@ -26,6 +26,7 @@ package at.gv.egiz.pdfas.impl.input.correction;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import at.gv.egiz.pdfas.api.io.DataSource;
import at.gv.egiz.pdfas.exceptions.ErrorCode;
import at.gv.egiz.pdfas.exceptions.framework.CorrectorException;
import at.gv.egiz.pdfas.framework.input.PdfDataSource;
@@ -40,7 +41,7 @@ import com.lowagie.text.pdf.PdfStamper;
/**
* Corrects a document using iText.
- *
+ *
* @author wprinz
*/
public class InternalCorrector implements Corrector
@@ -53,11 +54,9 @@ public class InternalCorrector implements Corrector
{
try
{
- byte[] pdf = document.getAsByteArray();
- PdfReader reader = new PdfReader(pdf);
- PDFASUtils.checkReaderPermissions(reader);
+ PdfReader reader = PDFASUtils.createPdfReaderCheckingPermissions(document);
- ByteArrayOutputStream baos = new ByteArrayOutputStream(pdf.length);
+ ByteArrayOutputStream baos = new ByteArrayOutputStream(document.getLength());
PdfStamper stamper = new PdfStamper(reader, baos, '\0', false);
stamper.close();
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/binary/BinarySignator_1_0_0.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/binary/BinarySignator_1_0_0.java
index 0af6538..a3ff856 100644
--- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/binary/BinarySignator_1_0_0.java
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/binary/BinarySignator_1_0_0.java
@@ -83,7 +83,7 @@ import com.lowagie.text.pdf.PdfPTable;
/**
* Signs the document binary.
- *
+ *
* <p>
* In prepareSign, an Incremental Update is created that contains the Signature block and the egiz dictionary. For
* formatting the layout, variable values are filled with placeholders. After the layout has been fixed, all variable
@@ -92,7 +92,7 @@ import com.lowagie.text.pdf.PdfPTable;
* <p>
* In finishSign, the variable fields (values, /Cert) are replaced with the values according to the encoding.
* </p>
- *
+ *
* @author wprinz
*/
public class BinarySignator_1_0_0 implements Signator {
@@ -204,13 +204,19 @@ public class BinarySignator_1_0_0 implements Signator {
// on a new page, prevent pdf-as to do that, because why should make
// a new page just for an invisible block
// added by rpiazzi
+
+ // disabled by dti: code fixes certain cases with invisible signatures but prevents usage of minimal
+ // signature profiles; the actual invisible signature issue has fixed in method
+ // adjustSignatureTableandCalculatePosition(...) in class at.knowcenter.wag.egov.egiz.PdfAS
+ /*
if (signature_object.getSignatureTypeDefinition().getInvisibleFieldDefinitions().size() == SignatureTypes.REQUIRED_SIG_KEYS.length) {
if (pi.isMakeNewPage()) {
int pageNumber = pi.getPage();
pi = new PositioningInstruction(false, pageNumber - 1, 0, 0);
}
}
- // end added
+ */
+ // end added (rpiazzi)
IncrementalUpdateInformation iui = IncrementalUpdateHelper.writeIncrementalUpdate(pdfDataSource, pdf_table,
profile, pi, variable_field_definitions, all_field_definitions, invisible_field_definitions,
@@ -318,7 +324,7 @@ public class BinarySignator_1_0_0 implements Signator {
/**
* Reads the signature values from the signed signature object and fills the corresponding value in the Replaces
* array.
- *
+ *
* @param iui
* The IncrementalUpdateInformation.
*/
@@ -394,7 +400,7 @@ public class BinarySignator_1_0_0 implements Signator {
/**
* Forms the SignatureData to be used for signing.
- *
+ *
* @param iui
* The IncrementalUpdateInformation.
* @return Returns the SignatureData to be used for signing.
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/detached/DetachedTextualSignator_1_0_0.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/detached/DetachedTextualSignator_1_0_0.java
index 7fcdb2a..16e2718 100644
--- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/detached/DetachedTextualSignator_1_0_0.java
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/detached/DetachedTextualSignator_1_0_0.java
@@ -41,7 +41,7 @@ import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUPostConnection;
/**
* Signs a document textually.
- *
+ *
* <p>
* In prepareSign, the document text is extracted and normalized.
* </p>
@@ -49,7 +49,7 @@ import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUPostConnection;
* In finishSign, the signed SignatureObject is transformed into a Signature
* block, which is then written as an Incremental Update.
* </p>
- *
+ *
* @author wprinz
*/
public class DetachedTextualSignator_1_0_0 extends TextualSignator_1_0_0
@@ -93,7 +93,7 @@ public class DetachedTextualSignator_1_0_0 extends TextualSignator_1_0_0
// String document_text =
// PdfAS.extractNormalizedTextTextual(pdf.createInputStream());
// // logger_.debug("signed_text = " + document_text);
- //
+ //
// DataSource ds = new TextDataSourceImpl(document_text);
// iui.signature_data = new SignatureDataImpl(ds, MIME_TYPE, "UTF-8");
// //$NON-NLS-1$ //$NON-NLS-2$
@@ -119,7 +119,6 @@ public class DetachedTextualSignator_1_0_0 extends TextualSignator_1_0_0
// }
// catch (UnsupportedEncodingException e)
// {
- // e.printStackTrace();
// throw new PDFDocumentException(300, e);
// }
// }
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/VerificationFilterImpl.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/VerificationFilterImpl.java
index 3f0f482..0e0da78 100644
--- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/VerificationFilterImpl.java
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/VerificationFilterImpl.java
@@ -80,7 +80,7 @@ public class VerificationFilterImpl implements VerificationFilter
public static final String SUPRESS_EXCEPTION_WHEN_LAST_UIBLOCK_IS_NO_SIGNATURE = "supress_exception_when_last_iublock_is_no_signature";
public static final String BINARY_ONLY = "binary_only";
public static final String ASSUME_ONLY_SIGNATURE_BLOCKS = "assume_only_signature_blocks";
-
+
/**
* @see at.gv.egiz.pdfas.framework.vfilter.VerificationFilter#extractSignatureHolders(at.gv.egiz.pdfas.framework.input.PdfDataSource,
* java.util.List,
@@ -97,7 +97,7 @@ public class VerificationFilterImpl implements VerificationFilter
log.debug("Original IU blocks: " + blocks.size());
debugIUBlocks(blocks);
}
-
+
unrollLinearization(blocks);
if (log.isDebugEnabled())
@@ -106,7 +106,7 @@ public class VerificationFilterImpl implements VerificationFilter
debugIUBlocks(blocks);
}
-
+
SettingsReader settings;
try {
settings = SettingsReader.getInstance();
@@ -115,7 +115,7 @@ public class VerificationFilterImpl implements VerificationFilter
}
String check_doc = settings.getSetting(CHECK_DOCUMENT, "false");
- // check document for textual sigs here here if binary_only is set
+ // check document for textual sigs here here if binary_only is set
if ("true".equalsIgnoreCase(check_doc) &&
parameters.extractBinarySignaturesOnly()) {
@@ -125,7 +125,7 @@ public class VerificationFilterImpl implements VerificationFilter
log.debug("Skipping checkDocument for textual sigs.");
}
// end add
-
+
List signatureHolderChain = null;
if (parameters.extractBinarySignaturesOnly())
@@ -156,11 +156,11 @@ public class VerificationFilterImpl implements VerificationFilter
}
}
-
+
log.trace("extractSignaturHolders finished (" + (signatureHolderChain != null ? signatureHolderChain.size() : 0) + " elements).");
sw.stop();
log.debug("extractSignatureHolders: " + sw.getTime() + "ms.");
-
+
return signatureHolderChain;
}
@@ -194,12 +194,12 @@ public class VerificationFilterImpl implements VerificationFilter
foundSignatures = extractNewSignaturesFromText(normalizedText);
}
-
+
List textOnlySignatures = filterOutBinarySignatures(foundSignatures);
-
+
return textOnlySignatures;
}
-
+
protected String normalizeText(String freetext) throws VerificationFilterException
{
try
@@ -214,7 +214,7 @@ public class VerificationFilterImpl implements VerificationFilter
/**
* Removes the linearization footer from the list of update blocks.
- *
+ *
* @param blocks
* The list of FooterParseResult objects in \prev order.
*/
@@ -263,15 +263,15 @@ public class VerificationFilterImpl implements VerificationFilter
if (sao.oldSignature != null)
{
extractedSignatures.add(0, sao.oldSignature);
- }
+ }
}
else
{
log.debug("extracting signatures from last partition...");
extractedSignatures = extractSignaturesFromPartition(pdf, lastTextPartition);
}
-
-
+
+
List signatureHolderChain = intermingleSignatures(binarySignatures, extractedSignatures);
return signatureHolderChain;
@@ -287,15 +287,15 @@ public class VerificationFilterImpl implements VerificationFilter
Set binarySigValues = new HashSet();
Iterator iterator = binarySignatures.iterator();
while(iterator.hasNext()) {
-
+
SignatureHolder sh = (SignatureHolder)iterator.next();
-
+
String sigVal = sh.getSignatureObject().getSignationValue();
binarySigValues.add(sigVal);
}
-
+
SignatureHolder oldSignature = null;
-
+
//List originalPartitions = partitions;
// This gives every IU block an own text partition
// This allows text signatures to be found correctly if there are
@@ -313,36 +313,36 @@ public class VerificationFilterImpl implements VerificationFilter
}
String check_doc = settings.getSetting(CHECK_DOCUMENT, "false");
boolean supressException = "true".equalsIgnoreCase(settings.getSetting(SUPRESS_EXCEPTION_WHEN_LAST_UIBLOCK_IS_NO_SIGNATURE, "false"));
-
+
// flag indicating that the last IU-block of the document is a non-signature IU-block
boolean lastBlockWasModified = false;
-
+
// counter of all signatures (textual and binary) of this document
int signatureCounter = 0;
-
+
// counter of all textual signatures in this document
int txtSigsSoFar = 0;
-
+
// counter of all textual signatures in the current partition
int txtSigsThisPartition = 0;
-
+
List partitionResults = new ArrayList(partitions.size());
- List nshList = new ArrayList();
-
+ List nshList = new ArrayList();
+
boolean sigFound = false;
-
+
for (int i = 0; i < partitions.size(); i++)
{
Partition p = (Partition) partitions.get(i);
-
+
// updating flag and counter
boolean partitionContainsNewTextSignatures = true;
txtSigsSoFar = txtSigsThisPartition;
-
+
if (p instanceof TextPartition)
{
TextPartition tp = (TextPartition) p;
-
+
List partitionResult = null;
boolean scanThisPartitionForOldSignature = (i == 0) && scanForOldSignatures;
@@ -356,34 +356,34 @@ public class VerificationFilterImpl implements VerificationFilter
{
partitionResult = extractSignaturesFromPartition(pdf, tp);
}
-
- // binary signature blocks that have been detected as well are identified by comparing their signature values
+
+ // binary signature blocks that have been detected as well are identified by comparing their signature values
// with those stored in our Set above and are not considered for our IU-check
List onlyTextSignatures = new ArrayList();
Iterator iter = partitionResult.iterator();
while(iter.hasNext()) {
-
+
SignatureHolder sh = (SignatureHolder)iter.next();
if(!binarySigValues.contains(sh.getSignatureObject().getSignationValue())) {
-
+
onlyTextSignatures.add(sh);
}
}
-
+
// update signature counters
txtSigsThisPartition = onlyTextSignatures.size();
int newTextSignatures = txtSigsThisPartition - txtSigsSoFar;
signatureCounter = signatureCounter + newTextSignatures;
-
+
// update sigFound flag
if(txtSigsThisPartition > 0) {
-
+
sigFound = true;
}
-
+
// TextPartition is only valid, if at least one more text signature has been found than in the previous text partition
if(!(newTextSignatures > 0)) {
-
+
partitionContainsNewTextSignatures = false;
}
@@ -391,39 +391,39 @@ public class VerificationFilterImpl implements VerificationFilter
} else {
// should be binary partition
if(p instanceof BinaryPartition) {
-
+
BinaryPartition binpart = (BinaryPartition)p;
// updating counter and flag
signatureCounter = signatureCounter + binpart.blocks.size();
sigFound = true;
-
+
}
}
-
+
// if document checking is enabled, at least one signature has been found so far, we are dealing with a
// non-signature IU-block
if ((check_doc.equalsIgnoreCase("true"))&& (sigFound && !partitionContainsNewTextSignatures)) {
-
- nshList.add(new NoSignatureHolder(signatureCounter));
+
+ nshList.add(new NoSignatureHolder(signatureCounter));
lastBlockWasModified = true;
-
+
} else {
-
+
lastBlockWasModified = false;
}
-
+
}
// throw an exception if the last update block does not contain a signature and signatures have been found in this document
if (lastBlockWasModified) {
if (!supressException) {
- throw new VerificationFilterException(ErrorCode.MODIFIED_AFTER_SIGNATION, "The document has been modified after being signed.");
+ throw new VerificationFilterException(ErrorCode.MODIFIED_AFTER_SIGNATION, "The document has been modified after being signed.");
} else {
log.debug("The document has been modified after being signed. According to the configuration, no exception is thrown.");
}
}
-
+
List extractedSignatures = new ArrayList();
Iterator it = partitionResults.iterator();
List prevPartitionResult = null;
@@ -451,54 +451,54 @@ public class VerificationFilterImpl implements VerificationFilter
}
List signatureHolderChain = intermingleSignatures(binarySignatures, extractedSignatures);
-
+
if (oldSignature != null)
{
signatureHolderChain.add(0, oldSignature);
}
-
+
// add the created NoSignatureHolders
signatureHolderChain.addAll(nshList);
-
+
return signatureHolderChain;
}
-
+
private void mergeSignatures(List oldList, List newList, List result) {
-
+
for(int i=0; i < newList.size(); i++) {
-
+
SignatureHolder currentNewSh = (SignatureHolder)newList.get(i);
-
+
boolean shAlreadyPresentInOldList = false;
int pos = -1;
-
+
for(int j=0; j<oldList.size(); j++) {
-
+
SignatureHolder currentOldSh = (SignatureHolder)oldList.get(j);
-
+
if(currentNewSh.getSignatureObject().getSignationValue().equals(currentOldSh.getSignatureObject().getSignationValue())) {
-
+
shAlreadyPresentInOldList = true;
pos = j;
}
}
-
+
if(!shAlreadyPresentInOldList) {
-
+
// signature holder has not been found earlier -> add
result.add(currentNewSh);
}
-
+
}
-
-
+
+
return;
}
-
-
+
+
protected List flattenOutTextPartitions (List partitions, List blocks)
{
-
+
List blockPartitions = new ArrayList(blocks.size());
Iterator it = partitions.iterator();
while (it.hasNext())
@@ -523,10 +523,10 @@ public class VerificationFilterImpl implements VerificationFilter
blockPartitions.add(p);
}
}
-
+
// note: successive binary blocks are still combined to one binary partition
assert blockPartitions.size() <= blocks.size();
-
+
return blockPartitions;
}
@@ -536,15 +536,15 @@ public class VerificationFilterImpl implements VerificationFilter
protected String extractText(PdfDataSource pdf, int endOfDocument, String encoding) throws PresentableException
{
-
+
log.debug("EXTRACTING TEXT (" + encoding + ")... end index = " + endOfDocument);
-
+
DelimitedPdfDataSource dds = new DelimitedPdfDataSource(pdf, endOfDocument);
//DelimitedInputStream dis = new DelimitedInputStream(pdf.createInputStream(), endOfDocument);
return PdfAS.extractNormalizedTextTextual(dds, encoding);
}
-
-
+
+
protected List extractNewSignaturesFromText(String text) throws VerificationFilterException
{
try
@@ -556,7 +556,7 @@ public class VerificationFilterImpl implements VerificationFilter
throw new VerificationFilterException(e);
}
}
-
+
protected List extractNewAndOldSignaturesFromText(String text) throws VerificationFilterException
{
SignaturesAndOld sao = extractSignaturesAndOld(text);
@@ -651,11 +651,11 @@ public class VerificationFilterImpl implements VerificationFilter
/**
* Extracts the binary singatures from the given PDF.
- *
+ *
* <p>
* IU blocks without an egiz dict are not considered.
* </p>
- *
+ *
* @param pdf
* @param blocks
* @return Returns the List of signature holders.
@@ -673,7 +673,7 @@ public class VerificationFilterImpl implements VerificationFilter
String binary_only = settings.getSetting(BINARY_ONLY, "false");
String assume_sigs_only = settings.getSetting(ASSUME_ONLY_SIGNATURE_BLOCKS, "false");
boolean supressException = "true".equalsIgnoreCase(settings.getSetting(SUPRESS_EXCEPTION_WHEN_LAST_UIBLOCK_IS_NO_SIGNATURE, "false"));
-
+
try
{
// PERF: extract binary signatures needs byte array
@@ -689,15 +689,15 @@ public class VerificationFilterImpl implements VerificationFilter
FooterParseResult fpr = (FooterParseResult) it.next();
assert fpr.next_index > prev_end;
- if (VerificationFilterBinaryHelper.containsEGIZDict(data, fpr))
+ PdfASID kz = null;
+ if (VerificationFilterBinaryHelper.containsEGIZDict(data, fpr) &&
+ (kz = VerificationFilterBinaryHelper.extractKZFromEGIZBlock(data, fpr)) != null)
{
- PdfASID kz = VerificationFilterBinaryHelper.extractKZFromEGIZBlock(data, fpr);
-
// TODO dferbas hack baik test
//kz = new PdfASID("urn:pdfsigfilter:bka.gv.at:binaer:v1.1.0");
-
+
Verificator verificator = VerificatorFactory.createBinaryVerificator(kz);
- List binary_holders = verificator.parseBlock(pdf, data, fpr, prev_end);
+ List binary_holders = verificator.parseBlock(pdf, data, fpr, prev_end);
binarySignatures.addAll(binary_holders);
if(binary_holders.size() > 0) {
@@ -707,21 +707,21 @@ public class VerificationFilterImpl implements VerificationFilter
// an Exception is thrown here if:
// 1) check_document is activated
// 2) assume_only_signature_blocks is false - otherwise we permit updates
- // 3) binary_only is true - otherwise updates are handled in method performFullConservative().
- // when binary-only is true, we can be sure that a block that contains no egiz-dict is no textual
+ // 3) binary_only is true - otherwise updates are handled in method performFullConservative().
+ // when binary-only is true, we can be sure that a block that contains no egiz-dict is no textual
// signature either but an illegal update, otherwise an Exception (doc contains textual sig) would have been thrown before
// 4) a binary signature has been detected in a previous block
- if(check_doc.equalsIgnoreCase("true") &&
+ if(check_doc.equalsIgnoreCase("true") &&
binary_only.equalsIgnoreCase("true") &&
assume_sigs_only.equalsIgnoreCase("false") &&
- sig_detected) {
-
+ sig_detected) {
+
if (!supressException) {
- throw new VerificationFilterException(ErrorCode.MODIFIED_AFTER_SIGNATION, "The document has been modified after being signed.");
+ throw new VerificationFilterException(ErrorCode.MODIFIED_AFTER_SIGNATION, "The document has been modified after being signed.");
} else {
log.debug("The document has been modified after being signed. According to the configuration, no exception is thrown.");
}
-
+
}
}
@@ -749,7 +749,7 @@ public class VerificationFilterImpl implements VerificationFilter
List extractedSignatures = extractNewSignaturesFromText(extractedText);
log.debug("Extracting signatures finished.");
log.debug("Number of found signatures: " + extractedSignatures.size());
-
+
if (extractedSignatures.size() > 0) {
List cp1252SignaturesPositions = new ArrayList();
//boolean iscp1252Sig = false;
@@ -760,19 +760,19 @@ public class VerificationFilterImpl implements VerificationFilter
log.debug("found cp1252 signature");
cp1252SignaturesPositions.add(new Integer(i));
//iscp1252Sig = true;
- //break;
+ //break;
}
- }
+ }
if (cp1252SignaturesPositions.size() > 0) {
log.debug("redo text and signature extraction with cp1252 encoding");
extractedText = extractText(pdf, endOfDocument, "cp1252");
log.debug("Extracting text finished.");
-
+
log.debug("Extracting signatures:");
List cp1252ExtractedSignatures = extractNewSignaturesFromText(extractedText);
log.debug("Extracting signatures finished.");
log.debug("Number of found signatures: " + extractedSignatures.size());
-
+
if (cp1252ExtractedSignatures.size() != extractedSignatures.size()) {
log.error("Invalid cp1252 signatures found. Skipping cp1252 compatibility.");
}
@@ -780,12 +780,12 @@ public class VerificationFilterImpl implements VerificationFilter
for (int i = 0; i < cp1252SignaturesPositions.size(); i++) {
int replaceIndex = ((Integer)cp1252SignaturesPositions.get(i)).intValue();
extractedSignatures.remove(replaceIndex);
- extractedSignatures.add(replaceIndex, cp1252ExtractedSignatures.get(replaceIndex));
+ extractedSignatures.add(replaceIndex, cp1252ExtractedSignatures.get(replaceIndex));
}
}
-
+
}
-
+
if (log.isDebugEnabled())
{
log.debug("extracted signatures:");
@@ -856,7 +856,7 @@ public class VerificationFilterImpl implements VerificationFilter
}
protected void checkBinaryOnly(PdfDataSource pdf, boolean considerOldSigs) throws VerificationFilterException {
-
+
DelimitedPdfDataSource dds = new DelimitedPdfDataSource(pdf, pdf.getLength());
String text = null;
try {
@@ -864,10 +864,10 @@ public class VerificationFilterImpl implements VerificationFilter
} catch (PresentableException e) {
throw new VerificationFilterException(e);
}
-
+
List sigs = new ArrayList();
-
- if(considerOldSigs) {
+
+ if(considerOldSigs) {
SignaturesAndOld sao = extractSignaturesAndOld(text);
if(sao != null) {
if(sao.newSignatures != null) {
@@ -877,30 +877,30 @@ public class VerificationFilterImpl implements VerificationFilter
sigs.add(sao.oldSignature);
}
}
- } else {
+ } else {
List signatures = extractSignatures(pdf, pdf.getLength());
if(signatures != null) {
sigs.addAll(signatures);
}
}
-
+
Iterator it = sigs.iterator();
while(it.hasNext()) {
SignatureHolder current = (SignatureHolder)it.next();
if((current != null)&&(!current.getSignatureObject().isBinary())) {
throw new VerificationFilterException(ErrorCode.NON_BINARY_SIGNATURES_PRESENT, "The document contains non-binary signatures.");
}
- }
+ }
}
-
-
+
+
protected static class SignaturesAndOld
{
public List newSignatures = null;
public SignatureHolder oldSignature = null;
}
-
+
protected SignaturesAndOld extractSignaturesAndOld(String text) throws VerificationFilterException
{
try
@@ -908,7 +908,7 @@ public class VerificationFilterImpl implements VerificationFilter
log.debug("Extracting signatures:");
List extractedSignatures = extractNewSignaturesFromText(text);
log.debug("Extracting signatures finished.");
-
+
log.debug("Extracting old signatures:");
SignatureHolder oldSignature = extractOldSignature(text, extractedSignatures);
log.debug("Extracting old signatures finished.");
@@ -929,7 +929,7 @@ public class VerificationFilterImpl implements VerificationFilter
/**
* Extracts the old signature from the text, but only if it is older than the
* oldest signature of the new signatueres.
- *
+ *
* @param extractedText
* @param newSignatures
* @return
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/helper/VerificationFilterBinaryHelper.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/helper/VerificationFilterBinaryHelper.java
index 735b874..3093c36 100644
--- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/helper/VerificationFilterBinaryHelper.java
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/helper/VerificationFilterBinaryHelper.java
@@ -48,7 +48,7 @@ import at.knowcenter.wag.exactparser.parsing.results.ObjectParseResult;
/**
* Contains helpful methods used by the VerificationFilter to analyze the PDF for binary signatures.
- *
+ *
* @author wprinz
*/
public final class VerificationFilterBinaryHelper
@@ -70,12 +70,12 @@ public final class VerificationFilterBinaryHelper
/**
* Tells, if the given incremental update block contains a binary signature.
- *
+ *
* <p>
* According to definition, if a block is a binary block, it must/cannot
* contain other signatures than this one.
* </p>
- *
+ *
* @param block
* The incremental update block.
* @return Returns true, if this block is a binary signature block, false
@@ -94,7 +94,7 @@ public final class VerificationFilterBinaryHelper
/**
* Extracts the PDF AS ID of the egiz block.
- *
+ *
* @param pdf
* The pdf.
* @param block
@@ -120,6 +120,13 @@ public final class VerificationFilterBinaryHelper
IndirectObjectReference ior = egiz_dict_iorpr.ior;
final int egiz_dict_offset = PDFUtils.getObjectOffsetFromXRefByIndirectObjectReference(block.xpr, ior);
+
+ // fix dti:
+ if (egiz_dict_offset < 0) {
+ log.debug("Current ui block contains a /EGIZSigDict trailer entry but no respective xref table entry. This indicates that this ui block does not contain binary signatures.");
+ return null;
+ }
+
// logger_.debug("egiz_dict_offset = " + egiz_dict_offset);
ObjectParseResult obj = PDFUtils.parseObject(pdf, egiz_dict_offset);
@@ -140,7 +147,7 @@ public final class VerificationFilterBinaryHelper
/**
* Restores the Kennzeichnung String from an Array.
- *
+ *
* @param pdf
* The PDF.
* @param kz_apr
@@ -174,7 +181,7 @@ public final class VerificationFilterBinaryHelper
si.pdf = pdf;
log.trace("Adding KZ: " + si.toString());
-
+
partition.add(si);
}
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/FileBasedTextBasedDataSource.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/FileBasedTextBasedDataSource.java
index aaf99ea..918b13d 100644
--- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/FileBasedTextBasedDataSource.java
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/FileBasedTextBasedDataSource.java
@@ -33,7 +33,7 @@ import at.gv.egiz.pdfas.api.io.TextBased;
/**
* FileBased DataSource that is TextBased.
- *
+ *
* @author wprinz
*/
public class FileBasedTextBasedDataSource extends FileBasedDataSource implements TextBased
@@ -113,7 +113,6 @@ public class FileBasedTextBasedDataSource extends FileBasedDataSource implements
}
catch (UnsupportedEncodingException e)
{
- e.printStackTrace();
throw new RuntimeException(e);
}
}
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/StringTextBasedDataSource.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/StringTextBasedDataSource.java
index 8fe0dd6..8234b2a 100644
--- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/StringTextBasedDataSource.java
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/StringTextBasedDataSource.java
@@ -32,9 +32,9 @@ import at.gv.egiz.pdfas.api.io.TextBased;
/**
* A String TextBased DataSource.
- *
+ *
* @author wprinz
- *
+ *
*/
public class StringTextBasedDataSource implements DataSource, TextBased
{
@@ -74,7 +74,6 @@ public class StringTextBasedDataSource implements DataSource, TextBased
}
catch (UnsupportedEncodingException e)
{
- e.printStackTrace();
throw new RuntimeException(e);
}
}
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/placeholder/SignaturePlaceholderExtractor.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/placeholder/SignaturePlaceholderExtractor.java
index 8b8c22e..453b620 100644
--- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/placeholder/SignaturePlaceholderExtractor.java
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/placeholder/SignaturePlaceholderExtractor.java
@@ -71,7 +71,7 @@ import com.google.zxing.common.HybridBinarizer;
/**
* Extract all relevant information from a placeholder image.
- *
+ *
* @author exthex
*
*/
@@ -80,10 +80,10 @@ public class SignaturePlaceholderExtractor extends PDFStreamEngine {
* The log.
*/
private static Log log = LogFactory.getLog(SignaturePlaceholderExtractor.class);
-
+
private List placeholders = new Vector();
private int currentPage = 0;
-
+
private SignaturePlaceholderExtractor(String placeholderId, int placeholderMatchMode) throws IOException {
super(ResourceLoader.loadProperties("at/gv/egiz/pdfas/placeholder/pdfbox-reader.properties",
true));
@@ -93,7 +93,7 @@ public class SignaturePlaceholderExtractor extends PDFStreamEngine {
* Search the document for placeholder images and possibly included
* additional info.<br/>
* Searches only for the first placeholder page after page from top.
- *
+ *
* @param inputStream
* @return all available info from the first found placeholder.
* @throws PDFDocumentException if the document could not be read.
@@ -103,14 +103,13 @@ public class SignaturePlaceholderExtractor extends PDFStreamEngine {
throws PDFDocumentException, PlaceholderExtractionException {
SignaturePlaceholderContext.setSignaturePlaceholderData(null);
PDDocument doc = null;
- try
+ try
{
try {
doc = PDDocument.load(inputStream);
} catch (IOException e) {
throw new PDFDocumentException(ErrorCode.DOCUMENT_CANNOT_BE_READ, e);
}
- PDFASUtils.checkDocumentPermissions(doc);
SignaturePlaceholderExtractor extractor;
try
{
@@ -135,7 +134,7 @@ public class SignaturePlaceholderExtractor extends PDFStreamEngine {
} catch (IOException e1) {
throw new PDFDocumentException(ErrorCode.DOCUMENT_CANNOT_BE_READ, e1);
}
-
+
}
if (extractor.placeholders.size() > 0){
SignaturePlaceholderData ret = matchPlaceholderDocument(extractor.placeholders, placeholderId, matchMode);
@@ -146,7 +145,7 @@ public class SignaturePlaceholderExtractor extends PDFStreamEngine {
if (matchMode == Constants.PLACEHOLDER_MATCH_MODE_STRICT) {
throw new PlaceholderExtractionException(ErrorCode.SIGNATURE_PLACEHOLDER_EXTRACTION_FAILED, "no suitable placeholder found and STRICT matching mode requested.");
}
-
+
return null;
} finally {
if (doc != null)
@@ -158,23 +157,23 @@ public class SignaturePlaceholderExtractor extends PDFStreamEngine {
}
}
-
+
private static SignaturePlaceholderData matchPlaceholderDocument(
List placeholders, String placeholderId, int matchMode) throws PlaceholderExtractionException {
-
+
if (matchMode == Constants.PLACEHOLDER_MATCH_MODE_STRICT)
throw new PlaceholderExtractionException(ErrorCode.SIGNATURE_PLACEHOLDER_EXTRACTION_FAILED, "no suitable placeholder found and STRICT matching mode requested.");
-
+
if (placeholders.size() == 0)
return null;
-
+
for (int i = 0; i < placeholders.size(); i++)
{
SignaturePlaceholderData spd = (SignaturePlaceholderData)placeholders.get(i);
if (spd.getId() == null)
return spd;
}
-
+
if (matchMode == Constants.PLACEHOLDER_MATCH_MODE_LENIENT)
return (SignaturePlaceholderData)placeholders.get(0);
@@ -219,7 +218,7 @@ public class SignaturePlaceholderExtractor extends PDFStreamEngine {
PDPage page = getCurrentPage();
Matrix ctm = getGraphicsState().getCurrentTransformationMatrix();
double rotationInRadians = (page.findRotation() * Math.PI)/180;
-
+
AffineTransform rotation = new AffineTransform();
rotation.setToRotation( rotationInRadians );
AffineTransform rotationInverse = rotation.createInverse();
@@ -227,13 +226,13 @@ public class SignaturePlaceholderExtractor extends PDFStreamEngine {
rotationInverseMatrix.setFromAffineTransform( rotationInverse );
Matrix rotationMatrix = new Matrix();
rotationMatrix.setFromAffineTransform( rotation );
-
+
Matrix unrotatedCTM = ctm.multiply( rotationInverseMatrix );
-
+
float x = unrotatedCTM.getXPosition();
float y = unrotatedCTM.getYPosition() + unrotatedCTM.getYScale();
float w = unrotatedCTM.getXScale();
-
+
String posString = "p:" + currentPage + ";x:" + x + ";y:" + y + ";w:" + w;
try
{
@@ -259,7 +258,7 @@ public class SignaturePlaceholderExtractor extends PDFStreamEngine {
/**
* Checks an image if it is a placeholder for a signature.
- *
+ *
* @param image
* @return
* @throws IOException
@@ -291,7 +290,7 @@ public class SignaturePlaceholderExtractor extends PDFStreamEngine {
formats.add(BarcodeFormat.QR_CODE);
hints.put(DecodeHintType.POSSIBLE_FORMATS, formats);
result = new MultiFormatReader().decode(bitmap, hints);
-
+
String text = result.getText();
String profile = null;
String type = null;
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/CsvUtils.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/CsvUtils.java
new file mode 100644
index 0000000..a78da93
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/CsvUtils.java
@@ -0,0 +1,82 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.utils;
+
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * Methods in order to create valid delimiter separated data, where the semicolon as used as delimiter, also known as
+ * the German version of CSV.
+ *
+ * @author Datentechnik Innovation GmbH
+ * @see <a href="http://tools.ietf.org/html/rfc4180">RFC 4180</a>
+ */
+public class CsvUtils {
+
+ /**
+ * The delimiter char used instead of COMMA.
+ */
+ public static final char DEFAULT_DELIMITER = ';';
+
+ private static final char QUOTE_CHAR = '"';
+ private static final char LF_CHAR = '\n';
+ private static final char CR_CHAR = '\r';
+
+ private static final char[] SHOULD_BE_QUOTED = { LF_CHAR, CR_CHAR, DEFAULT_DELIMITER, QUOTE_CHAR };
+ private static final String CSV_QUOTE = String.valueOf(QUOTE_CHAR);
+
+ /**
+ * Returns an DSV escapted representation of the given object using the default delimiter character (
+ * {@link #DEFAULT_DELIMITER}).
+ *
+ * @param obj
+ * The object.
+ * @return An escapted representation of the given object.
+ */
+ public static String escapeCsvValue(Object obj) {
+ // null value should be printed as empty column
+ if (obj == null) {
+ return "";
+ }
+ // get String representation of object
+ String asString = String.valueOf(obj);
+ // do we need to escape anything?
+ if (StringUtils.containsNone(asString, SHOULD_BE_QUOTED)) {
+ return asString;
+ }
+
+ // RFC 4180 (7): If double-quotes are used to enclose fields, then a double-quote
+ // appearing inside a field must be escaped by preceding it with
+ // another double quote.
+ asString = StringUtils.replace(asString, CSV_QUOTE, CSV_QUOTE + CSV_QUOTE);
+
+ // RFC 4180 (6): Fields containing line breaks (CRLF), double quotes, and commas
+ // should be enclosed in double-quotes.
+ if (StringUtils.containsAny(asString, SHOULD_BE_QUOTED)) {
+ return QUOTE_CHAR + asString + QUOTE_CHAR;
+ }
+ return asString;
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/PDFASUtils.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/PDFASUtils.java
index 7f09dfc..a2332dd 100644
--- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/PDFASUtils.java
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/PDFASUtils.java
@@ -30,63 +30,233 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.BooleanUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.apache.pdfbox.pdmodel.PDDocument;
+import at.gv.egiz.pdfas.api.io.DataSource;
import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException;
+import com.lowagie.text.Document;
+import com.lowagie.text.pdf.BadPasswordException;
import com.lowagie.text.pdf.PdfReader;
/**
- * @author tknall
+ * Collection of useful utilities.
*/
public class PDFASUtils {
-//23.11.2010 changed by exthex - added checkDocumentPermissions(PDDocument doc)
-
- private PDFASUtils() {
- }
-
- /**
- * Verifies that a document could be opened with full permissions.
- * @param pdfReader The PdfReader
- * @throws PDFDocumentException Thrown if document has not been opened with full permissions.
- */
- public static void checkReaderPermissions(PdfReader pdfReader) throws PDFDocumentException {
- if (pdfReader.isEncrypted()) {
- throw new PDFDocumentException(ErrorCode.DOCUMENT_IS_PROTECTED, "Document is encrypted.");
- }
- if (!pdfReader.isOpenedWithFullPermissions()) {
- throw new PDFDocumentException(ErrorCode.DOCUMENT_IS_PROTECTED, "Document is protected.");
- }
- }
-
- public static boolean toFile(byte[] data, File file) throws IOException {
- return PDFASUtils.toFile(new ByteArrayInputStream(data), file);
- }
-
- public static boolean toFile(InputStream inputStream, File file) throws IOException {
- boolean result = false;
- BufferedOutputStream bufferedOutputStream = null;
- try {
- bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(file));
- ConfigUtils.writeInputStreamToOutputStream(inputStream, bufferedOutputStream);
- } finally {
- if (bufferedOutputStream != null) {
- try {
- bufferedOutputStream.close();
- result = true;
- } catch (IOException e) {
- result = false;
- }
- }
- }
- return result;
- }
-
- public static void checkDocumentPermissions(PDDocument doc) throws PDFDocumentException {
- if (doc.isEncrypted()) {
- throw new PDFDocumentException(ErrorCode.DOCUMENT_IS_PROTECTED, "Document is encrypted.");
- }
- }
-
+
+ private static Log log = LogFactory.getLog(PDFASUtils.class);
+
+ /**
+ * The configuration key for PDF/A support.
+ */
+ public static final String CFG_KEY_PDFA = "SIG_PDFA1B_VALID";
+
+ private PDFASUtils() {
+ }
+
+ /**
+ * Verifies that a document could be opened with full permissions.
+ *
+ * @param pdfReader
+ * The PdfReader.
+ * @throws PDFDocumentException
+ * Thrown if document has not been opened with full permissions.
+ */
+ private static void checkReaderPermissions(PdfReader pdfReader) throws PDFDocumentException {
+ if (pdfReader.isEncrypted()) {
+ throw new PDFDocumentException(ErrorCode.DOCUMENT_IS_PROTECTED, "Document is encrypted.");
+ }
+ if (!pdfReader.isOpenedWithFullPermissions()) {
+ throw new PDFDocumentException(ErrorCode.DOCUMENT_IS_PROTECTED, "Document is protected.");
+ }
+ }
+
+ /**
+ * Verifies that the document is not encrypted and/or protected. In case no restrictions have been applied to the
+ * document a pdf reader is returned.
+ *
+ * @param dataSource
+ * The document data source.
+ * @throws PDFDocumentException
+ * Thrown if the document could not be opened with full permissions.
+ */
+ public static PdfReader createPdfReaderCheckingPermissions(DataSource dataSource) throws PDFDocumentException {
+ return createPdfReaderCheckingPermissions(dataSource.createInputStream());
+ }
+
+ /**
+ * Verifies that the document is not encrypted and/or protected. In case no restrictions have been applied to the
+ * document a pdf reader is returned.
+ *
+ * @param dataSource
+ * The document data source.
+ * @throws PDFDocumentException
+ * Thrown if the document could not be opened with full permissions.
+ */
+ public static PdfReader createPdfReaderCheckingPermissions(at.gv.egiz.pdfas.framework.input.DataSource dataSource)
+ throws PDFDocumentException {
+ return createPdfReaderCheckingPermissions(dataSource.createInputStream());
+ }
+
+ /**
+ * Verifies that the document is not encrypted and/or protected. In case no restrictions have been applied to the
+ * document a pdf reader is returned.
+ *
+ * @param inputStream
+ * The document data input stream.
+ * @throws PDFDocumentException
+ * Thrown if the document could not be opened with full permissions.
+ */
+ public static PdfReader createPdfReaderCheckingPermissions(InputStream inputStream) throws PDFDocumentException {
+ PdfReader reader = null;
+ try {
+ // try to parse document
+ // If fully encrypted, PdfReader will fail;
+ // It should throw a BadPasswordException, but unfortunately does not (throws an IOException instead,
+ // internally catching BadPAsswordException; see comments below).
+ reader = new PdfReader(inputStream);
+ checkReaderPermissions(reader);
+ return reader;
+ } catch (BadPasswordException e) {
+ // will never be reached with itext-2.1.5-rev3628-pdfas:v1.1
+ // just added for later versions... (see comments below)
+ // itext-2.1.5-rev3628-pdfas:v1.2 correctly throws BadPasswordException
+ throw new PDFDocumentException(ErrorCode.DOCUMENT_IS_PROTECTED, "Document is protected.");
+ } catch (PDFDocumentException e) {
+ throw e;
+ } catch (Exception e) {
+ final String EX_MSG_FOR_ENCRYPTED_DOCUMENT = "Bad user Password";
+ // Inspecting the exception message seems to be the only way when using itext-2.1.5-rev3628-pdfas:v1.1:
+ // itext neither externally throws a BadPasswordException nor passed the cause...,
+ // later versions do!
+ // String "Bad user Password" is set in com.lowagie.text.pdf.BadPasswordException so this approach will
+ // work as long as the underlying itext library is not beeing updated.
+ if (StringUtils.containsIgnoreCase(e.getMessage(), EX_MSG_FOR_ENCRYPTED_DOCUMENT)) {
+ throw new PDFDocumentException(ErrorCode.DOCUMENT_IS_PROTECTED, "Document is protected.");
+ }
+ throw new PDFDocumentException(ErrorCode.DOCUMENT_CANNOT_BE_READ, "Unable to parse document.");
+ } finally {
+ IOUtils.closeQuietly(inputStream);
+ closeQuietly(reader);
+ }
+ }
+
+ /**
+ * Quietly closes a pdf reader.
+ *
+ * @param reader
+ * The reader.
+ */
+ public static void closeQuietly(PdfReader reader) {
+ if (reader != null) {
+ try {
+ reader.close();
+ } catch (Throwable e) {
+ // ignore
+ }
+ }
+ }
+
+ /**
+ * Quietly closes a pdf document.
+ *
+ * @param pdDocument
+ * The pdf document.
+ */
+ public static void closeQuietly(PDDocument pdDocument) {
+ if (pdDocument != null) {
+ try {
+ pdDocument.close();
+ } catch (Throwable e) {
+ // ignore
+ }
+ }
+ }
+
+ /**
+ * Quietly closes a pdf document.
+ *
+ * @param pdDocument
+ * The pdf document.
+ */
+ public static void closeQuietly(org.pdfbox.pdmodel.PDDocument pdDocument) {
+ if (pdDocument != null) {
+ try {
+ pdDocument.close();
+ } catch (Throwable e) {
+ // ignore
+ }
+ }
+ }
+
+ /**
+ * Quietly closes a pdf document.
+ *
+ * @param pdDocument
+ * The pdf document.
+ */
+ public static void closeQuietly(Document doc) {
+ if (doc != null) {
+ try {
+ doc.close();
+ } catch (Throwable e) {
+ // ignore
+ }
+ }
+ }
+
+ public static boolean toFile(byte[] data, File file) throws IOException {
+ return PDFASUtils.toFile(new ByteArrayInputStream(data), file);
+ }
+
+ public static boolean toFile(InputStream inputStream, File file) throws IOException {
+ boolean result = false;
+ BufferedOutputStream bufferedOutputStream = null;
+ try {
+ bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(file));
+ ConfigUtils.writeInputStreamToOutputStream(inputStream, bufferedOutputStream);
+ } finally {
+ if (bufferedOutputStream != null) {
+ try {
+ bufferedOutputStream.close();
+ result = true;
+ } catch (IOException e) {
+ result = false;
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Returns {@code true} if the given {@code profileId} is PDF/A-1b enabled, {@code false} if not.
+ *
+ * @param profileId
+ * The signature profile.
+ * @return {@code true} if the given {@code profileId} is PDF/A-1b enabled, {@code false} if not.
+ */
+ public static boolean isPdfAEnabled(String profileId) {
+ if (profileId == null) {
+ throw new NullPointerException("Profile identifier must not be null.");
+ }
+ if (StringUtils.isEmpty(profileId)) {
+ throw new IllegalArgumentException("Profile identifier must not be empty.");
+ }
+ try {
+ String pdfa = SettingsReader.getInstance().getSetting("sig_obj." + profileId + ".key." + CFG_KEY_PDFA,
+ "default." + CFG_KEY_PDFA, "false");
+ return BooleanUtils.toBoolean(pdfa);
+ } catch (Exception e) {
+ log.error("Unable to read settings for PDF/A functionality.", e);
+ return false;
+ }
+ }
+
}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/PdfAS.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/PdfAS.java
index fa9d4c1..2681f80 100644
--- a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/PdfAS.java
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/PdfAS.java
@@ -115,7 +115,7 @@ public abstract class PdfAS
* The current version of the pdf-as library. This version string is logged on every invocation
* of the api or the web application.
*/
- public static final String PDFAS_VERSION = "3.3-SNAPSHOT";
+ public static final String PDFAS_VERSION = "3.3";
/**
* The key of the strict mode setting.
@@ -1306,122 +1306,135 @@ public abstract class PdfAS
*/
public static PositioningInstruction adjustSignatureTableandCalculatePosition(final PdfDataSource pdfDataSource, PdfPTable pdf_table, TablePos pos) throws PDFDocumentException
{
- // first check pageinstruction in TablePos-object
- // new,auto,absolut
- PdfReader reader = readInPdfDocument(pdfDataSource);
- PDFASUtils.checkReaderPermissions(reader);
- // get pages of currentdocument
- int doc_pages = reader.getNumberOfPages();
- int page = doc_pages;
- boolean make_new_page = pos.isNewPage();
- if (!(pos.isNewPage() || pos.isPauto()))
- {
- // we should posit signaturtable on this page
-
- page = pos.getPage();
- // System.out.println("XXXXPAGE="+page+" doc_pages="+doc_pages);
- if (page > doc_pages)
- {
- make_new_page = true;
- page = doc_pages;
- // throw new PDFDocumentException(227, "Page number is to big(=" + page+
- // ") cannot be parsed.");
- }
- }
-
- // getPagedimensions
- Rectangle psize = reader.getPageSizeWithRotation(page);
- int page_rotation = reader.getPageRotation(page);
-
- float page_width = psize.getWidth();
- float page_height = psize.getHeight();
- // now we can calculate x-position
- float pre_pos_x = SIGNATURE_MARGIN_HORIZONTAL;
- if (!pos.isXauto())
- {
- // we do have absolute x
- pre_pos_x = pos.getPosX();
- }
- // calculate width
- // center
- float pre_width = page_width - 2*pre_pos_x;
- if (!pos.isWauto())
- {
- // we do have absolute width
- pre_width = pos.getWidth();
- if (pos.isXauto())
- { // center x
- pre_pos_x = (page_width - pre_width) / 2;
- }
- }
- final float pos_x = pre_pos_x;
- final float width = pre_width;
- // Signatur table dimensions are complete
- pdf_table.setTotalWidth(width);
- pdf_table.setLockedWidth(true);
-
- final float table_height = pdf_table.getTotalHeight();
- // now check pos_y
- float pos_y = pos.getPosY();
- if (!pos.isYauto())
- {
- // we do have y-position too --> all parameters but page ok
- if (make_new_page)
- {
- page++;
- }
- return new PositioningInstruction(make_new_page, page, pos_x, pos_y);
- }
- // pos_y is auto
- if (make_new_page)
- {
- // ignore footer in new page
- page++;
- pos_y = page_height - SIGNATURE_MARGIN_VERTICAL;
- return new PositioningInstruction(make_new_page, page, pos_x, pos_y);
- }
- // up to here no checks have to be made if Tablesize and Pagesize are fit
- // Now we have to getfreespace in page and reguard footerline
- float footer_line = pos.getFooterLine();
- float pre_page_length = PDFUtilities.calculatePageLength(pdfDataSource, page - 1, page_height - footer_line, page_rotation);
- if (pre_page_length == Float.NEGATIVE_INFINITY)
- {
- // we do have an empty page or nothing in area above footerline
- pre_page_length = page_height;
- // no text --> SIGNATURE_BORDER
- pos_y = page_height - SIGNATURE_MARGIN_VERTICAL;
- if (pos_y - footer_line <= table_height)
- {
- make_new_page = true;
- if (!pos.isPauto())
- {
- // we have to correct pagenumber
- page = reader.getNumberOfPages();
- }
- page++;
- // no text --> SIGNATURE_BORDER
- pos_y = page_height - SIGNATURE_MARGIN_VERTICAL;
- }
- return new PositioningInstruction(make_new_page, page, pos_x, pos_y);
- }
- final float page_length = pre_page_length;
- // we do have text take SIGNATURE_MARGIN
- pos_y = page_height - page_length - SIGNATURE_MARGIN_VERTICAL;
- if (pos_y - footer_line <= table_height)
- {
- make_new_page = true;
- if (!pos.isPauto())
- {
- // we have to correct pagenumber in case of absolute page and not enough
- // space
- page = reader.getNumberOfPages();
- }
- page++;
- // no text --> SIGNATURE_BORDER
- pos_y = page_height - SIGNATURE_MARGIN_VERTICAL;
- }
- return new PositioningInstruction(make_new_page, page, pos_x, pos_y);
+ PdfReader reader = null;
+ try {
+ reader = PDFASUtils.createPdfReaderCheckingPermissions(pdfDataSource);
+ // get pages of currentdocument
+ int doc_pages = reader.getNumberOfPages();
+ int page = doc_pages;
+ boolean make_new_page = pos.isNewPage();
+ if (!(pos.isNewPage() || pos.isPauto()))
+ {
+ // we should posit signaturtable on this page
+
+ page = pos.getPage();
+ // System.out.println("XXXXPAGE="+page+" doc_pages="+doc_pages);
+ if (page > doc_pages)
+ {
+ make_new_page = true;
+ page = doc_pages;
+ // throw new PDFDocumentException(227, "Page number is to big(=" + page+
+ // ") cannot be parsed.");
+ }
+ }
+
+ // getPagedimensions
+ Rectangle psize = reader.getPageSizeWithRotation(page);
+ int page_rotation = reader.getPageRotation(page);
+
+ float page_width = psize.getWidth();
+ float page_height = psize.getHeight();
+
+ // now we can calculate x-position
+ float pre_pos_x = SIGNATURE_MARGIN_HORIZONTAL;
+ if (!pos.isXauto())
+ {
+ // we do have absolute x
+ pre_pos_x = pos.getPosX();
+ }
+ // calculate width
+ // center
+ float pre_width = page_width - 2*pre_pos_x;
+ if (!pos.isWauto())
+ {
+ // we do have absolute width
+ pre_width = pos.getWidth();
+ if (pos.isXauto())
+ { // center x
+ pre_pos_x = (page_width - pre_width) / 2;
+ }
+ }
+ final float pos_x = pre_pos_x;
+ final float width = pre_width;
+ // Signatur table dimensions are complete
+ pdf_table.setTotalWidth(width);
+ pdf_table.setLockedWidth(true);
+
+ final float table_height = pdf_table.getTotalHeight();
+ // now check pos_y
+ float pos_y = pos.getPosY();
+
+ // in case an absolute y position is already given OR
+ // if the table is related to an invisible signature
+ // there is no need for further calculations
+ // (fixed adding new page in case of invisible signatures)
+ if (!pos.isYauto() || table_height == 0)
+ {
+ // we do have y-position too --> all parameters but page ok
+ if (make_new_page)
+ {
+ page++;
+ }
+ return new PositioningInstruction(make_new_page, page, pos_x, pos_y);
+ }
+ // pos_y is auto
+ if (make_new_page)
+ {
+ // ignore footer in new page
+ page++;
+ pos_y = page_height - SIGNATURE_MARGIN_VERTICAL;
+ return new PositioningInstruction(make_new_page, page, pos_x, pos_y);
+ }
+ // up to here no checks have to be made if Tablesize and Pagesize are fit
+ // Now we have to getfreespace in page and reguard footerline
+ float footer_line = pos.getFooterLine();
+ float pre_page_length = PDFUtilities.calculatePageLength(pdfDataSource, page - 1, page_height - footer_line, page_rotation);
+ if (pre_page_length == Float.NEGATIVE_INFINITY)
+ {
+ // we do have an empty page or nothing in area above footerline
+ pre_page_length = page_height;
+ // no text --> SIGNATURE_BORDER
+ pos_y = page_height - SIGNATURE_MARGIN_VERTICAL;
+ if (pos_y - footer_line <= table_height)
+ {
+ make_new_page = true;
+ if (!pos.isPauto())
+ {
+ // we have to correct pagenumber
+ page = reader.getNumberOfPages();
+ }
+ page++;
+ // no text --> SIGNATURE_BORDER
+ pos_y = page_height - SIGNATURE_MARGIN_VERTICAL;
+ }
+ return new PositioningInstruction(make_new_page, page, pos_x, pos_y);
+ }
+ final float page_length = pre_page_length;
+ // we do have text take SIGNATURE_MARGIN
+ pos_y = page_height - page_length - SIGNATURE_MARGIN_VERTICAL;
+ if (pos_y - footer_line <= table_height)
+ {
+ make_new_page = true;
+ if (!pos.isPauto())
+ {
+ // we have to correct pagenumber in case of absolute page and not enough
+ // space
+ page = reader.getNumberOfPages();
+ }
+ page++;
+ // no text --> SIGNATURE_BORDER
+ pos_y = page_height - SIGNATURE_MARGIN_VERTICAL;
+ }
+ return new PositioningInstruction(make_new_page, page, pos_x, pos_y);
+ } finally {
+ if (reader != null) {
+ try {
+ reader.close();
+ } catch (Exception e) {
+ }
+ }
+ }
}
// /**
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/CircularIncludeException.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/CircularIncludeException.java
new file mode 100644
index 0000000..6ff7d3a
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/CircularIncludeException.java
@@ -0,0 +1,44 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.cfg;
+
+/**
+ * Exception indicating that circular includes were detected.
+ *
+ * @author Datentechnik Innovation GmbH
+ *
+ */
+public class CircularIncludeException extends RuntimeException {
+
+ private static final long serialVersionUID = 1L;
+
+ public CircularIncludeException() {
+ super();
+ }
+
+ public CircularIncludeException(String message) {
+ super(message);
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/NestedProperties.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/NestedProperties.java
new file mode 100644
index 0000000..259a1dc
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/NestedProperties.java
@@ -0,0 +1,255 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.cfg;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.InvalidPropertiesFormatException;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOCase;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.filefilter.WildcardFileFilter;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Enhanced Java Properties allowing nested include instructions.<br/>
+ * In order to include further Properties use the following instruction:
+ * <p/>
+ * <code>include = [path/to/]foo.properties</code>
+ * <p/>
+ * Note that wildcard imports are allowed, e.g.
+ * <p/>
+ * <code>include = [path/to/]profile.*.properties</code>
+ * <p/>
+ * In order to use more than one include instruction within a file append an arbitary postfix to <code>include.</code>
+ * in order to make each include key unique within a properties file, e.g.
+ * <p/>
+ * <code>include = profile.SIGNATURBLOCK*.properties</code><br/>
+ * <code>include.amtssignaturen = profile.AMTSSIGNATURBLOCK*.properties</code><br/>
+ * <code>include.1 = myProfiles1/*.properties</code><br/>
+ * <code>include.2 = myProfiles2/*.properties</code>
+ * <p/>
+ * Note that
+ * <ul>
+ * <li>all include instructions of a certain properties file are sorted alphabetically by their key name before being
+ * executed,</li>
+ * <li>include instructions can be used within any properties files being loaded (even within other includes) and that</li>
+ * <li>(wildcard) path/file declarations are always case <b>insensitive</b>, regardless of the underlying operating
+ * system.</li>
+ * <li>included properties always override locally defined properties</li>
+ * </ul>
+ * <p/>
+ * <b>Mind creating circular includes!</b>
+ *
+ * @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<String, String> sortedIncludeInstructions = new TreeMap<String, String>();
+
+ // Walk through properties, collecting include instructions.
+ // Since the backing Hashtable does not guarantee any order, import instructions need to be sorted according to
+ // their keys (natural order -> alphabetically).
+ // This allows for defining a pseudo load order: include.1=path/to/settings.propertes,
+ // include.2=other/path/to/settings.properties
+ @SuppressWarnings("unchecked")
+ Enumeration<String> propertyNames = (Enumeration<String>) propertyNames();
+ while (propertyNames.hasMoreElements()) {
+ String key = propertyNames.nextElement();
+ // valid include instructions: include=xxx, include.foo=xxx, include.foo.foo=xxx... (keys are case
+ // insensitive)
+ if (INCLUDE_KEY_NAME.equalsIgnoreCase(key) || StringUtils.startsWithIgnoreCase(key, INCLUDE_KEY_NAME + ".")) {
+ String includeValue = StringUtils.trimToNull(getProperty(key));
+ if (includeValue != null) {
+ sortedIncludeInstructions.put(key, includeValue);
+ }
+ }
+ }
+
+ // performing imports
+ Iterator<String> includeIt = sortedIncludeInstructions.keySet().iterator();
+ while (includeIt.hasNext()) {
+ String includeInstructionKey = includeIt.next();
+ String includePath = getProperty(includeInstructionKey);
+ processInclude(contextFolder, includePath, currentDepth);
+ // remove import instruction from properties
+ remove(includeInstructionKey);
+ }
+ }
+
+ /**
+ * Processes a single include instruction (which may lead to several imports due to wildcard support).
+ *
+ * @param contextFolder
+ * The folder that should be assumed as starting folder for relative include instructions.
+ * @param includePath
+ * The include path instruction.
+ * @param currentDepth
+ * The current include depth.
+ * @throws IOException
+ * Thrown in case of error.
+ */
+ private void processInclude(File contextFolder, String includePath, int currentDepth) throws IOException {
+ // Combine contextFolder with relative path instructions from includePath.
+ File includeInstruction = new File(contextFolder, includePath);
+ contextFolder = includeInstruction.getParentFile();
+ String includeName = includeInstruction.getName();
+
+ WildcardFileFilter fileFilter = new WildcardFileFilter(includeName, DEFAULT_IOCASE);
+ Collection<File> includeFiles = null;
+ if (contextFolder != null && contextFolder.exists() && contextFolder.isDirectory()) {
+ includeFiles = FileUtils.listFiles(contextFolder, fileFilter, null);
+ }
+ if (includeFiles != null && !includeFiles.isEmpty()) {
+ log.info("Including '" + includePath + "'.");
+ for (File includeFile : includeFiles) {
+ NestedProperties includeProperties = new NestedProperties();
+ includeProperties.load(includeFile, currentDepth + 1);
+ putAll(includeProperties);
+ }
+ } else {
+ log.warn("Unable to find '" + includeName + "' in folder '" + contextFolder.getCanonicalPath() + "'.");
+ }
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/PropertyTree.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/PropertyTree.java
index 49ba003..e9276b8 100644
--- a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/PropertyTree.java
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/PropertyTree.java
@@ -38,7 +38,7 @@ import java.util.Vector;
* the values of a configuration is stored in nested hashes. The keys in an area are stored in a
* HashMap. The values of a key are stored in a Vector to overload some keys. The property tree can
* be used to extract sub nodes and sub keys of different tree levels.
- *
+ *
* @author wlackner
* @see java.util.HashMap
* @see java.util.Vector
@@ -49,7 +49,7 @@ public class PropertyTree implements Serializable {
* SVUID.
*/
private static final long serialVersionUID = -1686170519955886222L;
-
+
/**
* The key split string. A key can be a complex key. Sub keys are separated from each other with
* the split string. This string is used to devide the complex key.
@@ -77,7 +77,7 @@ public class PropertyTree implements Serializable {
* the tree will be created. The last part of the key (last splitted element) adds the value to
* there own value data structure (Vector). <br />
* <strong>Example: </strong> <code>setKeyValue("key.1_level.2_level","the value for k_1_2")</code
- *
+ *
* @param splitKey the key that has to be store the value
* @param value only String values can be stored
*/
@@ -97,7 +97,7 @@ public class PropertyTree implements Serializable {
/**
* Adds a String value to the current key
- *
+ *
* @param value
*/
private void addValue(String value) {
@@ -108,7 +108,7 @@ public class PropertyTree implements Serializable {
* This method takes a key as input value, split them into subnodes and return the sub tree of the
* last node of the key. If the key or a sub node not found, the method return null. This means
* the key is not part of the sub property tree.
- *
+ *
* @param splitKey the key that has to be found as sub node of the current node
* @return the sub tree (PropertyTree) or <code>null</code> 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 <code>null</code> 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 <code>null.</code>
- *
+ *
* @param key the key that holds the value (can be a nested key like <code>"key.1.2.3"</code>)
* @return the value of the key (last node of the key) or <code>null</code> 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 <code>null</code>.
- *
+ *
* @param key the key that holds the value (can be a nested key like <code>"key.1.2.3"</code>)
* @return the value of the key (last node of the key) or <code>null</code> 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 <code>"key.1.2.3"</code>)
* @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 <code>"key.1.2.3"</code>)
* @return the values (type Vector) of the key or <code>null</code> 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.
* <strong>Example: </strong>if the key is like: <code>key.1.2.3</code> the sub tree of the last
* node <code>3</code> is returned.
- *
+ *
* @param key the reference of the sub tree
* @return a sub tree of the key or <code>null</code> 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 ;-).<p/>
+ * 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 <code>settings.txt</code> file. The
* <code>settings.txt</code> 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:
- *
+ *
* <pre>
- *
+ *
* #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
- *
+ *
* </pre>
- *
+ *
* The internal representation of the example above is:
- *
+ *
* <pre>
- *
+ *
* .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
+ *
* </pre>
- *
+ *
* @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.
- *
+ *
* <p>
* This usually contains sub directories for the templates, the configuration
* files, etc.
* </p>
*/
public static String RESOURCES_PATH = null;
-
+
/**
* The path for temporary files.
*/
@@ -237,7 +243,7 @@ public class SettingsReader implements Serializable
/**
* The reference to the settings file.
*/
- private static String settingsFile_ = null;
+ private static File settingsFile_ = null;
/**
* The reference to the property representation of the settings file.
@@ -258,7 +264,7 @@ public class SettingsReader implements Serializable
* The only cause to do this is that the definition file should only be read
* once while getting often this instance. The method throws an IOException if
* the settings file could not be read.
- *
+ *
* @param settingsFile
* load this file, if the <code>settingsFile == null</code> 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.
- *
+ *
* <p>
* Subsequent calls to getInstance will return the new settings.
* Note: IAIK JCE and IAIK ECC security providers are automatically registered.
* </p>
- *
+ *
* @throws SettingsException f.e.
*/
public synchronized static void createInstance() throws SettingsException
@@ -356,16 +370,16 @@ public class SettingsReader implements Serializable
instance_ = null;
getInstance();
}
-
+
/**
* Reloads the Settings file.
- *
+ *
* <p>
* Subsequent calls to getInstance will return the new settings.
* </p>
* @param registerProvider <code>true</code>: automatically registers IAIK JCE and ECC Provider;
* <code>false</code>: 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
* <code>settingsFile == null</code> 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 <code>true</code>: automatically registers IAIK JCE and ECC Provider;
* <code>false</code>: 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 <code>Object[]</code> 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 <code>null</code> 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.
- *
+ *
* <p>
* If the directory doesn't exist, it is created.
* </p>
- *
+ *
* @return Returns the directory where temporary files should be stored.
* @see TempDirHelper#getTemporaryDirectory()
*/
@@ -773,7 +780,7 @@ public class SettingsReader implements Serializable
/**
* Deletes all files in the temporary directory, if it exists.
- *
+ *
* <p>
* 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.
- *
+ *
* <p>
* The extension of a file name is whatever text follows the last '.'.
* </p>
- *
+ *
* @param file_name
* The file name.
* @return Returns the extension. If the file name ends with the '.', then an
@@ -664,14 +630,14 @@ public abstract class Main
// }
}
// logger_.debug("Finally used sign algorithm = " + signatorId);
-
+
String connectorId = CommandlineConnectorChooser.chooseCommandlineConnectorForSign(connector);
PdfAS.signCommandline(pdfDataSource, dataSink, signatorId, connectorId, signature_type, null, pos, null, null);
// PdfAS.sign(algorithm, pdfDataSource, dataSink, signature_type, connector, pos);
}
-
+
public static List processVerify(DataSourceHolder dataSource, String connector, int verify_which) throws PresentableException
{
VerificationFilterParameters parameters = SettingsHelper.readVerificationFilterParametersFromSettings();
@@ -698,7 +664,7 @@ public abstract class Main
holders_to_verify = new ArrayList();
holders_to_verify.add(holder);
}
-
+
List results = PdfAS.verifySignatureHolders(holders_to_verify, connector, false, null);
return results;
@@ -749,7 +715,7 @@ public abstract class Main
/**
* Prints that the provided option was unrecognized.
- *
+ *
* @param option
* The unrecognized option.
* @throws PresentableException
@@ -763,7 +729,7 @@ public abstract class Main
/**
* Prints that the provided value was unrecognized.
- *
+ *
* @param parameter
* The parameter, which is missing a value.
* @throws PresentableException
@@ -777,7 +743,7 @@ public abstract class Main
/**
* Prints that the provided value was unrecognized.
- *
+ *
* @param value
* The unrecognized value.
* @throws PresentableException
@@ -791,7 +757,7 @@ public abstract class Main
/**
* Prints that the provided additional commandline argument was unrecognized.
- *
+ *
* @param argument
* The unrecognized argument.
* @throws PresentableException
@@ -805,7 +771,7 @@ public abstract class Main
/**
* Prints that a certain parameter was missing.
- *
+ *
* @param missing_term
* A description of the missing parameter ("e.g. a mode").
* @param parameter
@@ -820,7 +786,7 @@ public abstract class Main
/**
* Prints that something is missing.
- *
+ *
* @param missing_term
* A descriptive message of the missing thing.
* @throws PresentableException
@@ -834,7 +800,7 @@ public abstract class Main
/**
* Prints out the ErrorCodeException in a descriptive form.
- *
+ *
* @param ece
* The ErrorCodeException to be printed.
*/
@@ -868,7 +834,7 @@ public abstract class Main
/**
* Prints the usage text.
- *
+ *
* @param writer
* The writer to print the text to.
* @throws PresentableException
@@ -920,7 +886,9 @@ public abstract class Main
writer.print(" " + PARAMETER_SIGNATURE_TYPE + " <");
SignatureTypes sig_types = SignatureTypes.getInstance();
SettingsReader settings = SettingsReader.getInstance();
- Set types_array = sig_types.getSignatureTypes();
+ // show only signature profiles that can be used for signature
+// Set types_array = sig_types.getSignatureTypes();
+ Set types_array = sig_types.getSignatureTypesForSignature();
Iterator it = types_array.iterator();
while (it.hasNext())
{
@@ -973,7 +941,7 @@ public abstract class Main
/**
* Checks the value for correctness.
- *
+ *
* @param mode
* The parameter's value.
* @return Returns true, if the value is correct, false otherwise.
@@ -985,7 +953,7 @@ public abstract class Main
/**
* Checks the value for correctness.
- *
+ *
* @param signature_mode
* The parameter's value.
* @return Returns true, if the value is correct, false otherwise.
@@ -998,7 +966,7 @@ public abstract class Main
/**
* Checks the value for correctness.
- *
+ *
* @param connector
* The parameter's value.
* @return Returns true, if the value is correct, false otherwise.
@@ -1012,7 +980,7 @@ public abstract class Main
/**
* Checks the value for correctness.
- *
+ *
* @param signature_type
* The parameter's value.
* @return Returns true, if the value is correct, false otherwise.
@@ -1020,8 +988,8 @@ public abstract class Main
protected static boolean checkSignatureType(String signature_type) throws SignatureTypesException
{
return SignatureTypes.getInstance().getSignatureTypes().contains(signature_type);
-
- // exthex: uuuaaaahhhhh WHY??? wprinz again?, dont do that. Use List.contains(o), please
+
+ // exthex: uuuaaaahhhhh WHY??? wprinz again?, dont do that. Use List.contains(o), please
// take a java course and read: http://www.amazon.de/Java-f%C3%BCr-Dummies-Barry-Burd/dp/382662999X
// List types_array = sig_types.getSignatureTypes();
// Iterator it = types_array.iterator();
@@ -1038,7 +1006,7 @@ public abstract class Main
/**
* Translates the commandline argument to a PDF-AS-ID.
- *
+ *
* @param signature_mode
* The signator mode commandline argument.
* @return Returns the corresponding PDFASID.
@@ -1066,7 +1034,7 @@ public abstract class Main
/**
* Formats the verification results.
- *
+ *
* @param results
* The List of SignatureResponse verification results.
* @param writer
@@ -1088,12 +1056,12 @@ public abstract class Main
}
}
}
-
+
/**
* Formats the verification results for debugging. Returns 0 if no error occurs or the sum of all error-codes.
- *
+ *
* @param results
- *
+ *
* @param writer
* The output sink to write the formatted text to.
* @throws SettingNotFoundException
@@ -1106,16 +1074,16 @@ public abstract class Main
while (it.hasNext())
{
SignatureResponse result = (SignatureResponse) it.next();
-
+
toreturn += Integer.valueOf(result.getSignatureCheckCode()).intValue();
}
return toreturn;
}
-
+
/**
* Formats the SignatureResponse.
- *
+ *
* @param result
* The SignatureResponse to be printed.
* @param writer
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/BinarySignator_1_0_0.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/BinarySignator_1_0_0.java
index 46245d2..de94527 100644
--- a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/BinarySignator_1_0_0.java
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/BinarySignator_1_0_0.java
@@ -60,7 +60,7 @@ import com.lowagie.text.pdf.PdfPTable;
/**
* Signs the document binary.
- *
+ *
* <p>
* 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.
* </p>
- *
+ *
* @deprecated moved to new-framework
- *
+ *
* @author wprinz
*/
public class BinarySignator_1_0_0 implements Signator
@@ -131,18 +131,6 @@ public class BinarySignator_1_0_0 implements Signator
variable_field_definitions.add(sfd);
}
}
-
- //check if signature block is invisible, and if so and if also signature block is positioned
- //on a new page, prevent pdf-as to do that, because why should make a new page just for an invisible block
- //added by rpiazzi
- if (signature_object.getSignatureTypeDefinition().getInvisibleFieldDefinitions().size()==SignatureTypes.REQUIRED_SIG_KEYS.length) {
- if (pi.isMakeNewPage()) {
- int pageNumber = pi.getPage();
- pi = new PositioningInstruction(false, pageNumber-1, 0, 0);
- }
- }
- //end added
-
IncrementalUpdateInformation iui = IncrementalUpdateHelper.writeIncrementalUpdate(pdf, pdf_table, signature_type, pi, variable_field_definitions, all_field_definitions, null, null, null);
String temp_string = iui.temp_ir_number + " " + iui.temp_ir_generation + " obj"; //$NON-NLS-1$//$NON-NLS-2$
@@ -187,7 +175,6 @@ public class BinarySignator_1_0_0 implements Signator
}
catch (UnsupportedEncodingException e)
{
- e.printStackTrace();
throw new PDFDocumentException(201, e);
}
}
@@ -198,10 +185,10 @@ public class BinarySignator_1_0_0 implements Signator
public SignResult finishSign(IncrementalUpdateInformation iui) throws PresentableException
{
restoreSignedPdf(iui);
-
+
// PdfAS.prefixID(iui.signed_signature_object, PdfAS.BINARY_ID);
fillReplacesWithValues(iui);
-
+
BinarySignature.replaceCertificate(iui);
BinarySignature.replacePlaceholders(iui);
@@ -212,7 +199,7 @@ public class BinarySignator_1_0_0 implements Signator
/**
* Reads the signature values from the signed signature object and fills the
* corresponding value in the Replaces array.
- *
+ *
* @param iui
* The IncrementalUpdateInformation.
*/
@@ -222,7 +209,7 @@ public class BinarySignator_1_0_0 implements Signator
while (it.hasNext())
{
ReplaceInfo ri = (ReplaceInfo) it.next();
-
+
ri.value = iui.signed_signature_object.retrieveStringValue(ri.sfd.field_name);
}
}
@@ -256,7 +243,7 @@ public class BinarySignator_1_0_0 implements Signator
/**
* Forms the SignatureData to be used for signing.
- *
+ *
* @param iui
* The IncrementalUpdateInformation.
* @return Returns the SignatureData to be used for signing.
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/DetachedSignator_1_0_0.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/DetachedSignator_1_0_0.java
index 9ffeefe..492c5f1 100644
--- a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/DetachedSignator_1_0_0.java
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/DetachedSignator_1_0_0.java
@@ -44,12 +44,12 @@ import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUPostConnection;
/**
* This signator is just for testing purposes.
- *
+ *
* <p>
* It doesn't modify the original document, but simply returns the XML signature
* response as the signed document.
* </p>
- *
+ *
* @author wprinz
*/
public class DetachedSignator_1_0_0 implements Signator
@@ -58,7 +58,7 @@ public class DetachedSignator_1_0_0 implements Signator
* The Pdf-AS ID of this Signator.
*/
public static final PdfASID MY_ID = new PdfASID(SignatorFactory.VENDOR, SignatorFactory.TYPE_TEST, SignatorFactory.VERSION_1_0_0);
-
+
/**
* @see at.knowcenter.wag.egov.egiz.framework.Signator#getMyId()
*/
@@ -90,12 +90,12 @@ public class DetachedSignator_1_0_0 implements Signator
IncrementalUpdateInformation iui = new IncrementalUpdateInformation();
iui.original_document = pdf;
iui.signature_type = signature_type;
- iui.pos = pos;
+ iui.pos = pos;
String document_text = PdfAS.extractNormalizedTextTextual(pdf);
iui.nonTextObjectInfos = PdfAS.extractNonTextualObjects(pdf);
// logger_.debug("signed_text = " + document_text);
-
+
DataSource ds = new TextDataSourceImpl(document_text);
iui.signature_data = new SignatureDataImpl(ds, MIME_TYPE, "UTF-8"); //$NON-NLS-1$ //$NON-NLS-2$
@@ -117,7 +117,6 @@ public class DetachedSignator_1_0_0 implements Signator
}
catch (UnsupportedEncodingException e)
{
- e.printStackTrace();
throw new PDFDocumentException(300, e);
}
}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/DetachedfTextualSignator_1_0_0.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/DetachedfTextualSignator_1_0_0.java
index 1559246..73e6afb 100644
--- a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/DetachedfTextualSignator_1_0_0.java
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/DetachedfTextualSignator_1_0_0.java
@@ -44,7 +44,7 @@ import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUPostConnection;
/**
* Signs a document textually.
- *
+ *
* <p>
* In prepareSign, the document text is extracted and normalized.
* </p>
@@ -52,7 +52,7 @@ import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUPostConnection;
* In finishSign, the signed SignatureObject is transformed into a Signature
* block, which is then written as an Incremental Update.
* </p>
- *
+ *
* @author wprinz
*/
public class DetachedfTextualSignator_1_0_0 implements Signator
@@ -61,12 +61,12 @@ public class DetachedfTextualSignator_1_0_0 implements Signator
* The Mime Type.
*/
public static final String MIME_TYPE = "text/xml"; //$NON-NLS-1$
-
+
/**
* The Pdf-AS ID of this Signator.
*/
public static final PdfASID MY_ID = new PdfASID(SignatorFactory.VENDOR, SignatorFactory.TYPE_DETACHED_TEXTUAL, SignatorFactory.VERSION_1_0_0);
-
+
/**
* @see at.knowcenter.wag.egov.egiz.framework.Signator#getMyId()
*/
@@ -88,7 +88,7 @@ public class DetachedfTextualSignator_1_0_0 implements Signator
* The parameter has_SIG_ID is not used by this Signator because it doesn't
* pre-format the signature block.
* </p>
- *
+ *
* @see at.knowcenter.wag.egov.egiz.framework.Signator#prepareSign(byte[],
* String, TablePos, boolean)
*/
@@ -98,12 +98,12 @@ public class DetachedfTextualSignator_1_0_0 implements Signator
IncrementalUpdateInformation iui = new IncrementalUpdateInformation();
iui.original_document = pdf;
iui.signature_type = signature_type;
- iui.pos = pos;
+ iui.pos = pos;
String document_text = PdfAS.extractNormalizedTextTextual(pdf, "cp1252");
iui.nonTextObjectInfos = PdfAS.extractNonTextualObjects(pdf);
// logger_.debug("signed_text = " + document_text);
-
+
DataSource ds = new TextDataSourceImpl(document_text);
iui.signature_data = new SignatureDataImpl(ds, MIME_TYPE, "UTF-8"); //$NON-NLS-1$ //$NON-NLS-2$
@@ -125,7 +125,6 @@ public class DetachedfTextualSignator_1_0_0 implements Signator
}
catch (UnsupportedEncodingException e)
{
- e.printStackTrace();
throw new PDFDocumentException(300, e);
}
}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/AbsoluteTextSignature.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/AbsoluteTextSignature.java
index fd59d34..7b5a968 100644
--- a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/AbsoluteTextSignature.java
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/AbsoluteTextSignature.java
@@ -73,7 +73,9 @@ public class AbsoluteTextSignature
public static List getSignatureTypesForTextAnalysis() throws SignatureTypesException
{
SignatureTypes sig_types = SignatureTypes.getInstance();
- List allSignatureTypes = sig_types.getSignatureTypeDefinitions();
+ // use only those profiles that are allowed to be used for verification
+// List allSignatureTypes = sig_types.getSignatureTypeDefinitions();
+ List<SignatureTypeDefinition> allSignatureTypes = sig_types.getSignatureTypeDefinitionsForVerification();
List textSignatureTypes = new ArrayList(allSignatureTypes.size());
Iterator it = allSignatureTypes.iterator();
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/BinarySignature.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/BinarySignature.java
index ece9525..75a64f1 100644
--- a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/BinarySignature.java
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/BinarySignature.java
@@ -40,6 +40,7 @@ import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
+import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -89,25 +90,46 @@ import com.lowagie.text.pdf.PdfStamper;
import com.lowagie.text.pdf.PdfStamperImp;
import com.lowagie.text.pdf.PdfString;
import com.lowagie.text.pdf.PdfTemplate;
+import com.lowagie.text.pdf.PdfWriter;
/**
* Contains various extension functions to digitally sign documents.
- *
+ *
* <p>
* These functions are used to replace parts of the original Egiz plain text
* signature mechanism.
* </p>
- *
+ *
* @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.
- *
+ *
* <p>
* Used to locate and identify the Egiz Dictionary in the document.
* </p>
@@ -195,7 +217,7 @@ public abstract class BinarySignature
/**
* The PDFName of the Original Document Size (ODS) field in an Egiz
* Dictionary.
- *
+ *
* <p>
* The ODS must be a positive integral number.
* </p>
@@ -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.
- *
+ *
* <p>
* 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.
- *
+ *
* <p>
* The signature text is the text of the Signature XObject.
* </p>
- *
+ *
* @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.
- *
+ *
* <p>
* 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.
* </p>
- *
+ *
* @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.
- *
+ *
* <p>
* 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.
* </p>
- *
+ *
* @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.
- *
+ *
* <p>
* This replaces the "dummy numbers" in the egiz dictionary with the correct
* values.
* </p>
- *
+ *
* @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.
* </p>
- *
+ *
* @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.
- *
+ *
* <p>
* This method collects all variable String fields in a content stream and
* orders them according to their start offset.
* </p>
- *
+ *
* @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
* <li>images</li>
* <li>tables</li>
* </ul>
- *
+ *
* @param abstractCell
* the abstract cell definition
* @return the new redererd pdf table cell
@@ -345,27 +344,8 @@ public class PDFSignatureObjectIText implements PDFSignatureObject
*/
private PdfPCell renderCell(Entry abstractCell) throws PDFDocumentException
{
- boolean pdfaValid =false;
- try
- {
- String profileid = sigObject_.getSignatureTypeDefinition().getType();
- String pdfa = SettingsReader.getInstance().getSetting("sig_obj." +profileid+".key."+SIG_PDFA1_B_VALID, "default."+SIG_PDFA1_B_VALID, "false");
- pdfaValid= "true".equalsIgnoreCase(pdfa);
-
-// exthex test
- //SubsetLocal.set(!pdfaValid);
-
-// boolean forceSubset = true; // get this from config, default to false
- //String
-
- //SubsetLocal.set(true); // exthex
-
- logger_.trace("Sign PDF/A compliant:"+pdfa);
- } catch (SettingsException e1)
- {
- logger_.error(e1);
- }
-
+ boolean pdfaValid = PDFASUtils.isPdfAEnabled(sigObject_.getSignatureTypeDefinition().getType());
+
PdfPCell pdf_cell = null;
Style cell_style = abstractCell.getStyle();
boolean isValue = true;
@@ -384,7 +364,7 @@ public class PDFSignatureObjectIText implements PDFSignatureObject
{
font_string = cell_style.getValueFont();
}
-
+
logger_.trace("using cell font: "+font_string);
Font cell_font;
@@ -402,7 +382,7 @@ public class PDFSignatureObjectIText implements PDFSignatureObject
}
// exthex
if (pdfaValid && abstractCell.getType() == Entry.TYPE_VALUE) {
- SubsetLocal.addNonSubsetFont(cell_font.getBaseFont());
+ SubsetLocal.addNonSubsetFont(cell_font.getBaseFont());
}
Phrase text_phrase = new Phrase(text, cell_font);
pdf_cell = new PdfPCell(text_phrase);
@@ -429,9 +409,9 @@ public class PDFSignatureObjectIText implements PDFSignatureObject
}
Image image = Image.getInstance(img_file.getCanonicalPath());
logger_.debug("Using image file \"" + img_file.getCanonicalPath() + "\".");
-
+
image.scaleToFit(80.0f, 80.0f);
- boolean fit = true;
+ boolean fit = true;
Style.ImageScaleToFit istf = cell_style.getImageScaleToFit();
if (istf != null)
{
@@ -490,7 +470,7 @@ public class PDFSignatureObjectIText implements PDFSignatureObject
* This method visualize an abstract table into a corresponding pdf table. The
* new pdf table is redered and get the style information from the abstract
* cell.
- *
+ *
* @param abstractTable
* the abstract table definition
* @return the new redererd pdf table cell
@@ -558,7 +538,7 @@ public class PDFSignatureObjectIText implements PDFSignatureObject
/**
* This method creates the pdf table object. It takes the abstract table
* definition from the signature object and render the abstract table.
- *
+ *
* @param sigObject
* the signature object, the base for the abstract table definition
* @return R
@@ -587,7 +567,7 @@ public class PDFSignatureObjectIText implements PDFSignatureObject
/**
* Converts the current abstract signature object in a pdf signature object
* implementation
- *
+ *
* @return the converted pdf signature object
* @see at.knowcenter.wag.egov.egiz.pdf.PDFSignatureObject#getSignatureObject()
*/
@@ -603,11 +583,11 @@ public class PDFSignatureObjectIText implements PDFSignatureObject
/**
* Converts a abstract signature object in a pdf signature object
* implementation
- *
+ *
* @param sigObject
* the abstract signatorObject to convert
* @return the converted pdf signature object
- * @throws PDFDocumentException
+ * @throws PDFDocumentException
* @see at.knowcenter.wag.egov.egiz.pdf.PDFSignatureObject#getSignatureObject(at.knowcenter.wag.egov.egiz.sig.SignatureObject)
*/
public Object getSignatureObject(SignatureObject sigObject) throws PDFDocumentException
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFUtilities.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFUtilities.java
index bdc1078..b3adb71 100644
--- a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFUtilities.java
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFUtilities.java
@@ -32,6 +32,7 @@ import java.util.List;
import at.gv.egiz.pdfas.framework.input.PdfDataSource;
import at.gv.egiz.pdfas.impl.input.ByteArrayPdfDataSourceImpl;
+import at.gv.egiz.pdfas.utils.PDFASUtils;
import org.pdfbox.pdfparser.PDFParser;
import org.pdfbox.pdmodel.PDDocument;
@@ -44,7 +45,7 @@ import com.lowagie.text.DocumentException;
/**
* Contains useful helpers for accessing PDF documents.
- *
+ *
* @author wprinz
* @author mruhmer
*/
@@ -52,12 +53,13 @@ public abstract class PDFUtilities
{
public static float calculatePageLength(final PdfDataSource pdfDataSource, int page, float effectivePageHeight, int pagerotation) throws PDFDocumentException
{
+ PDDocument pdfDocument_ = null;
try
{
//ByteArrayInputStream original_bais = new ByteArrayInputStream(pdf);
//byte [] normalized_pdf = TextualSignature.normalizePDF(original_bais);
byte [] normalized_pdf = TextualSignature.normalizePDF(pdfDataSource);
-
+
// PERF: The whole PDF normalization process is costy
ByteArrayInputStream bais = new ByteArrayInputStream(normalized_pdf);
@@ -66,9 +68,8 @@ public abstract class PDFUtilities
parser.setTempDirectory(temporary_dir);
parser.parse();
- PDDocument pdfDocument_ = parser.getPDDocument();
+ pdfDocument_ = parser.getPDDocument();
float page_length = calculatePageLength(pdfDocument_, page, effectivePageHeight, pagerotation);
- pdfDocument_.close();
return page_length;
}
catch (IOException e)
@@ -78,8 +79,10 @@ public abstract class PDFUtilities
catch (DocumentException e)
{
throw new PDFDocumentException(201, e);
+ } finally {
+ PDFASUtils.closeQuietly(pdfDocument_);
}
- }
+ }
public static float calculatePageLength(PDDocument document, int page, float effectivePageHeight, int pagerotation) throws IOException
{
//int last_page_id = document.getNumberOfPages();
@@ -87,8 +90,8 @@ public abstract class PDFUtilities
PDPage pdpage = (PDPage) allPages.get(page);
pdpage.setRotation(pagerotation);
return calculatePageLength(pdpage, effectivePageHeight);
- }
-
+ }
+
/**
* @deprecated
* @param pdf
@@ -98,12 +101,13 @@ public abstract class PDFUtilities
*/
public static float calculateLastPageLength(final byte[] pdf, float effectivePageHeight) throws PDFDocumentException
{
+ PDDocument pdfDocument_ = null;
try
{
//ByteArrayInputStream original_bais = new ByteArrayInputStream(pdf);
PdfDataSource dataSource = new ByteArrayPdfDataSourceImpl(pdf);
byte [] normalized_pdf = TextualSignature.normalizePDF(dataSource);
-
+
ByteArrayInputStream bais = new ByteArrayInputStream(normalized_pdf);
PDFParser parser = new PDFParser(bais);
@@ -111,9 +115,8 @@ public abstract class PDFUtilities
parser.setTempDirectory(temporary_dir);
parser.parse();
- PDDocument pdfDocument_ = parser.getPDDocument();
+ pdfDocument_ = parser.getPDDocument();
float last_page_length = calculateLastPageLength(pdfDocument_, effectivePageHeight);
- pdfDocument_.close();
return last_page_length;
}
@@ -124,6 +127,8 @@ public abstract class PDFUtilities
catch (DocumentException e)
{
throw new PDFDocumentException(201, e);
+ } finally {
+ PDFASUtils.closeQuietly(pdfDocument_);
}
}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/StructContentHelper.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/StructContentHelper.java
index a9c1c54..deb5fed 100644
--- a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/StructContentHelper.java
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/StructContentHelper.java
@@ -173,9 +173,8 @@ public class StructContentHelper implements StructContentWriter {
}
} catch (Exception ex) {
- logger.error("error", ex);
- throw new PresentableException(ErrorCode.CANNOT_WRITE_PDF,
- "error writing structured signature content", ex);
+ logger.warn("Unable to process structured document data. Going to write untagged signature block.", ex);
+ isTagged = false;
}
}
@@ -471,16 +470,38 @@ public class StructContentHelper implements StructContentWriter {
}
}
- private void checkTagging() {
- PdfDictionary markDict = stamper.getReader().getCatalog().getAsDict(PdfName.MARKINFO);
- if (markDict != null) {
- isTagged = markDict.getAsBoolean(PdfName.MARKED).booleanValue();
- }
- if (!isTagged) {
- logger.debug("input document is not tagged. no structure/wai information is written");
- }
- logger.debug("Input is tagged. Writing structure/WAI data.");
- }
+ private void checkTagging() {
+ PdfDictionary markDict = stamper.getReader().getCatalog().getAsDict(PdfName.MARKINFO);
+ if (markDict != null) {
+ isTagged = markDict.getAsBoolean(PdfName.MARKED).booleanValue();
+ }
+ if (!isTagged) {
+ logger.debug("Input document is not tagged. No structure data will be attached to signature block.");
+ } else {
+ logger.trace("Document claims to be tagged. Checking availability of structured tree root.");
+ PdfDictionary structTreeRoot;
+ if ((structTreeRoot = getStructTreeRoot()) == null) {
+ // document claimed to be tagged but document does not contain structural information
+ isTagged = false;
+ logger.debug("Document claims to be tagged structured tree root was not found.");
+ } else if (getParentTreeNums() == null) {
+ // document claimed to be tagged but document does not contain structural information
+ isTagged = false;
+ logger.debug("Document claims to be tagged but required information is missing.");
+ } else if (structTreeRoot.getDirectObject(PdfName.K) == null) {
+ // structured content
+ isTagged = false;
+ logger.debug("Document claims to be tagged but required information is missing.");
+ } else {
+ logger.debug("Input is tagged and required structure data seems to be available. Going to write structured signature block.");
+ }
+ if (!isTagged) {
+ logger.info("Unable to process structured document data. Going to write untagged signature block.");
+ }
+ }
+ }
+
+
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/TextualSignature.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/TextualSignature.java
index 35a0768..3ce690b 100644
--- a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/TextualSignature.java
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/TextualSignature.java
@@ -53,7 +53,7 @@ import com.lowagie.text.pdf.PdfWriter;
/**
* Contains helper function for textual signatures.
- *
+ *
* @author wprinz
*/
public class TextualSignature
@@ -62,21 +62,22 @@ public class TextualSignature
* The logger definition.
*/
private static final Logger logger_ = ConfigLogger.getLogger(TextualSignature.class);
-
+
/**
* Extracts the document text from a given pdf.
- *
+ *
* @param pdf_stream
* The pdf_input stream.
* @return Returns the extracted document text.
- * @throws PDFDocumentException
+ * @throws PDFDocumentException
* @throws TextExtractionException
* Forwarded exception.
*/
- public static String extractTextTextual(PdfDataSource pdfDataSource, String encoding) throws PDFDocumentException
+ public static String extractTextTextual(PdfDataSource pdfDataSource, String encoding) throws PDFDocumentException
{
PerformanceCounters.textExtractions.increment();
-
+ PDDocument doc = null;
+ Document document = null;
try
{
int first_page_rotation = 0;
@@ -90,12 +91,8 @@ public class TextualSignature
// byte[] bytes = normalizePDF(pdf_stream);
- //iText
-
- byte [] pdf_data = pdfDataSource.getAsByteArray();
- PdfReader reader = new PdfReader(pdf_data);
- PDFASUtils.checkReaderPermissions(reader);
- //pdf_stream.close();
+
+ PdfReader reader = PDFASUtils.createPdfReaderCheckingPermissions(pdfDataSource);
// PERF: PDF normalization needs byte array - this is costy
ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
@@ -108,7 +105,7 @@ public class TextualSignature
// this method (although it works when a Table is appended)... very
// fragile.
- Document document = new Document();
+ document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, baos);
document.open();
@@ -126,7 +123,7 @@ public class TextualSignature
first_page_rotation = new_size_withrot.getRotation();
//logger_.info("iText first_page_rotation="+new_size_withrot.getRotation());
}
- //logger_.info("iText set PageSize of page:"+page_num+" to: "+new_size_withrot);
+ //logger_.info("iText set PageSize of page:"+page_num+" to: "+new_size_withrot);
//document.setPageSize(new_size);
document.setPageSize(new_size_withrot);
document.newPage();
@@ -163,15 +160,15 @@ public class TextualSignature
//logger_.info("temporary_dir="+temporary_dir.getAbsolutePath());
parser.setTempDirectory(temporary_dir);
parser.parse();
-
- PDDocument doc = parser.getPDDocument();
+
+ doc = parser.getPDDocument();
//System.out.println("pdfBox.getNumberOfPages()"+doc.getNumberOfPages());
-
+
PDFTextStripper stripper = new PDFTextStripper();
stripper.setSortByPosition(false);
stripper.setGetFirstPageRotationFromThis(true);
stripper.setFirstPageRotation(first_page_rotation);
-
+
// stripper.setStartPage(4);
// stripper.setEndPage(4);
logger_.debug("TextualSignator extractTextTextual: Begin stripping text");
@@ -182,8 +179,7 @@ public class TextualSignature
throw new PDFDocumentException(ErrorCode.TEXT_EXTRACTION_EXCEPTION, "Unable to extract textual content.", e);
}
logger_.debug("TextualSignator extractTextTextual: Stripping text ended");
-
- doc.close();
+
//logger_.debug("TextualSignator extractTextTextual="+text);
return text;
@@ -199,39 +195,39 @@ public class TextualSignature
catch (DocumentException e)
{
throw new PDFDocumentException(ErrorCode.DOCUMENT_CANNOT_BE_READ, e);
+ } finally {
+ PDFASUtils.closeQuietly(doc);
+ PDFASUtils.closeQuietly(document);
}
}
-
+
/**
* Normalizes a given binary PDF to a version PDFbox can handle correctly.
- *
+ *
* <p>
* 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.
* </p>
- *
+ *
* <p>
* 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.
* </p>
- *
+ *
* @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 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.pdf.operator.path;
+
+import java.awt.geom.Point2D;
+
+import org.pdfbox.util.operator.OperatorProcessor;
+
+import at.knowcenter.wag.egov.egiz.pdf.PDFPage;
+
+/**
+ * Provides functions for path construction operators.
+ *
+ * @see "PDF 1.7 specification, Section 8.5.2 'Path Construction Operators'"
+ * @author Datentechnik Innovation GmbH
+ *
+ */
+public abstract class PathConstructionOperatorProcessor extends OperatorProcessor {
+
+ public PathConstructionOperatorProcessor(PDFPage context) {
+ setContext(context);
+ }
+
+ /**
+ * Transforms the given point from user space coordinates to device space coordinates based on the current
+ * transition matrix.
+ *
+ * @param x
+ * The x axis value of the user space coordinates.
+ * @param y
+ * The y axis value of the user space coordinates.
+ * @return The transformed point.
+ */
+ public Point2D transform(double x, double y) {
+ double[] position = { x, y };
+ context.getGraphicsState().getCurrentTransformationMatrix().createAffineTransform()
+ .transform(position, 0, position, 0, 1);
+ return new Point2D.Double(position[0], position[1]);
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/PathPaintingOperatorProcessor.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/PathPaintingOperatorProcessor.java
new file mode 100644
index 0000000..9a76f87
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/PathPaintingOperatorProcessor.java
@@ -0,0 +1,43 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.pdf.operator.path;
+
+import org.pdfbox.util.operator.OperatorProcessor;
+
+import at.knowcenter.wag.egov.egiz.pdf.PDFPage;
+
+/**
+ * Provides functions for path painting operators.
+ *
+ * @see "PDF 1.7 specification, Section 8.5.2 'Path Construction Operators'"
+ * @author Datentechnik Innovation GmbH
+ *
+ */
+public abstract class PathPaintingOperatorProcessor extends OperatorProcessor {
+
+ public PathPaintingOperatorProcessor(PDFPage context) {
+ setContext(context);
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/construction/ClosePath.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/construction/ClosePath.java
new file mode 100644
index 0000000..ea87887
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/construction/ClosePath.java
@@ -0,0 +1,68 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.pdf.operator.path.construction;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.pdfbox.util.PDFOperator;
+
+import at.knowcenter.wag.egov.egiz.pdf.PDFPage;
+import at.knowcenter.wag.egov.egiz.pdf.operator.path.PathConstructionOperatorProcessor;
+
+/**
+ * Close the current subpath by appending a straight line segment from the current point to the starting point of the
+ * subpath. If the current subpath is already closed, h shall donothing. This operator terminates the current subpath.
+ * Appending another segment to the current path shall begin a new subpath, even if the new segment begins at the
+ * endpoint reached by the h operation.
+ *
+ * @see "PDF 1.7 specification, Section 8.5.2 'Path Construction Operators'"
+ * @author PdfBox, modified by Datentechnik Innovation GmbH
+ */
+public class ClosePath extends PathConstructionOperatorProcessor {
+
+ private Log log = LogFactory.getLog(getClass());
+
+ public ClosePath(PDFPage context) {
+ super(context);
+ }
+
+ @Override
+ public void process(PDFOperator operator, List operands) throws IOException {
+ try {
+ PDFPage pdfPage = (PDFPage) context;
+
+ pdfPage.getCurrentPath().closePath();
+
+ if (log.isTraceEnabled()) {
+ log.trace("Closing current path.");
+ }
+ } catch (Exception e) {
+ log.warn("Error processing operator 'h'.", e);
+ }
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/construction/CurveTo.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/construction/CurveTo.java
new file mode 100644
index 0000000..a2fc8de
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/construction/CurveTo.java
@@ -0,0 +1,85 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.pdf.operator.path.construction;
+
+import java.awt.geom.Point2D;
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.pdfbox.cos.COSNumber;
+import org.pdfbox.util.PDFOperator;
+
+import at.knowcenter.wag.egov.egiz.pdf.PDFPage;
+import at.knowcenter.wag.egov.egiz.pdf.operator.path.PathConstructionOperatorProcessor;
+
+/**
+ * Append a cubic Bezier curve to the current path. The curve shall extend from the current point to the point (x3, y3),
+ * using (x1, y1) and (x2, y2) as the Bezier control points (see 8.5.2.2, "Cubic Bezier Curves"). The new current point
+ * shall be (x3, y3).
+ *
+ * @see "PDF 1.7 specification, Section 8.5.2 'Path Construction Operators'"
+ * @author PdfBox, modified by Datentechnik Innovation GmbH
+ */
+public class CurveTo extends PathConstructionOperatorProcessor {
+
+ private Log log = LogFactory.getLog(getClass());
+
+ public CurveTo(PDFPage context) {
+ super(context);
+ }
+
+ @Override
+ public void process(PDFOperator operator, List operands) throws IOException {
+ try {
+ PDFPage pdfPage = (PDFPage) context;
+
+ COSNumber x1 = (COSNumber) operands.get(0);
+ COSNumber y1 = (COSNumber) operands.get(1);
+ COSNumber x2 = (COSNumber) operands.get(2);
+ COSNumber y2 = (COSNumber) operands.get(3);
+ COSNumber x3 = (COSNumber) operands.get(4);
+ COSNumber y3 = (COSNumber) operands.get(5);
+
+ Point2D p1 = transform(x1.doubleValue(), y1.doubleValue());
+ Point2D p2 = transform(x2.doubleValue(), y2.doubleValue());
+ Point2D p3 = transform(x3.doubleValue(), y3.doubleValue());
+
+ pdfPage.getCurrentPath().curveTo(
+ (float) p1.getX(), (float) p1.getY(),
+ (float) p2.getX(), (float) p2.getY(),
+ (float) p3.getX(), (float) p3.getY()
+ );
+
+ if (log.isTraceEnabled()) {
+ log.trace("Appending cubic Bezier curve with x1:" + p1.getX() + ",y1:" + p1.getY() + ", x2:"
+ + p2.getX() + ",y2:" + p2.getY() + ", x3:" + p3.getX() + ",y3:" + p3.getY());
+ }
+ } catch (Exception e) {
+ log.warn("Error processing operator 'c'.", e);
+ }
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/construction/CurveToReplicateFinalPoint.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/construction/CurveToReplicateFinalPoint.java
new file mode 100644
index 0000000..bb5c86c
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/construction/CurveToReplicateFinalPoint.java
@@ -0,0 +1,82 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.pdf.operator.path.construction;
+
+import java.awt.geom.Point2D;
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.pdfbox.cos.COSNumber;
+import org.pdfbox.util.PDFOperator;
+
+import at.knowcenter.wag.egov.egiz.pdf.PDFPage;
+import at.knowcenter.wag.egov.egiz.pdf.operator.path.PathConstructionOperatorProcessor;
+
+/**
+ * Append a cubic Bezier curve to the current path. The curve shall extend from the current point to the point (x3, y3),
+ * using (x1, y1) and (x3, y3) as the Bezier control points (see 8.5.2.2, "Cubic Bezier Curves"). The new current point
+ * shall be (x3, y3).
+ *
+ * @see "PDF 1.7 specification, Section 8.5.2 'Path Construction Operators'"
+ * @author PdfBox, modified by Datentechnik Innovation GmbH
+ */
+public class CurveToReplicateFinalPoint extends PathConstructionOperatorProcessor {
+
+ private Log log = LogFactory.getLog(getClass());
+
+ public CurveToReplicateFinalPoint(PDFPage context) {
+ super(context);
+ }
+
+ @Override
+ public void process(PDFOperator operator, List operands) throws IOException {
+ try {
+ PDFPage pdfPage = (PDFPage) context;
+
+ COSNumber x1 = (COSNumber) operands.get(0);
+ COSNumber y1 = (COSNumber) operands.get(1);
+ COSNumber x3 = (COSNumber) operands.get(2);
+ COSNumber y3 = (COSNumber) operands.get(3);
+
+ Point2D p1 = transform(x1.doubleValue(), y1.doubleValue());
+ Point2D p3 = transform(x3.doubleValue(), y3.doubleValue());
+
+ pdfPage.getCurrentPath().curveTo(
+ (float) p1.getX(), (float) p1.getY(),
+ (float) p3.getX(), (float) p3.getY(),
+ (float) p3.getX(), (float) p3.getY()
+ );
+
+ if (log.isTraceEnabled()) {
+ log.trace("Appending cubic Bezier curve with x1:" + p1.getX() + ",y1:" + p1.getY() + ", x3:"
+ + p3.getX() + ",y3:" + p3.getY());
+ }
+ } catch (Exception e) {
+ log.warn("Error processing operator 'y'.", e);
+ }
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/construction/CurveToReplicateInitialPoint.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/construction/CurveToReplicateInitialPoint.java
new file mode 100644
index 0000000..b35bcaf
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/construction/CurveToReplicateInitialPoint.java
@@ -0,0 +1,84 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.pdf.operator.path.construction;
+
+import java.awt.geom.Point2D;
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.pdfbox.cos.COSNumber;
+import org.pdfbox.util.PDFOperator;
+
+import at.knowcenter.wag.egov.egiz.pdf.PDFPage;
+import at.knowcenter.wag.egov.egiz.pdf.operator.path.PathConstructionOperatorProcessor;
+
+/**
+ * Append a cubic Bezier curve to the current path. The curve shall extend from the current point to the point (x3, y3),
+ * using the current point and (x2, y2) as the Bezier control points (see 8.5.2.2, "Cubic Bezier Curves"). The new
+ * current point shall be (x3, y3).
+ *
+ * @see "PDF 1.7 specification, Section 8.5.2 'Path Construction Operators'"
+ * @author PdfBox, modified by Datentechnik Innovation GmbH
+ */
+public class CurveToReplicateInitialPoint extends PathConstructionOperatorProcessor {
+
+ private Log log = LogFactory.getLog(getClass());
+
+ public CurveToReplicateInitialPoint(PDFPage context) {
+ super(context);
+ }
+
+ @Override
+ public void process(PDFOperator operator, List operands) throws IOException {
+ try {
+ PDFPage pdfPage = (PDFPage) context;
+
+ COSNumber x2 = (COSNumber) operands.get(0);
+ COSNumber y2 = (COSNumber) operands.get(1);
+ COSNumber x3 = (COSNumber) operands.get(2);
+ COSNumber y3 = (COSNumber) operands.get(3);
+
+ Point2D currentPoint = pdfPage.getCurrentPath().getCurrentPoint();
+ Point2D p2 = transform(x2.doubleValue(), y2.doubleValue());
+ Point2D p3 = transform(x3.doubleValue(), y3.doubleValue());
+
+ pdfPage.getCurrentPath().curveTo(
+ (float)currentPoint.getX(), (float)currentPoint.getY(),
+ (float) p2.getX(), (float) p2.getY(),
+ (float) p3.getX(), (float) p3.getY()
+ );
+
+ if (log.isTraceEnabled()) {
+ log.trace("Appending cubic Bezier curve with x2:" + p2.getX() + ",y2:" + p2.getY() + ", x3:"
+ + p3.getX() + ",y3:" + p3.getY() + ", using current point x:" + currentPoint.getX() + ",y:"
+ + currentPoint.getY());
+ }
+ } catch (Exception e) {
+ log.warn("Error processing operator 'v'.", e);
+ }
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/construction/LineTo.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/construction/LineTo.java
new file mode 100644
index 0000000..ae5894d
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/construction/LineTo.java
@@ -0,0 +1,71 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.pdf.operator.path.construction;
+
+import java.awt.geom.Point2D;
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.pdfbox.cos.COSNumber;
+import org.pdfbox.util.PDFOperator;
+
+import at.knowcenter.wag.egov.egiz.pdf.PDFPage;
+import at.knowcenter.wag.egov.egiz.pdf.operator.path.PathConstructionOperatorProcessor;
+
+/**
+ * Append a straight line segment from the current point to the point (x, y). The new current point shall be (x, y).
+ *
+ * @see "PDF 1.7 specification, Section 8.5.2 'Path Construction Operators'"
+ * @author PdfBox, modified by Datentechnik Innovation GmbH
+ */
+public class LineTo extends PathConstructionOperatorProcessor {
+
+ private Log log = LogFactory.getLog(getClass());
+
+ public LineTo(PDFPage context) {
+ super(context);
+ }
+
+ @Override
+ public void process(PDFOperator operator, List operands) throws IOException {
+ try {
+ PDFPage pdfPage = (PDFPage) context;
+
+ COSNumber x = (COSNumber) operands.get(0);
+ COSNumber y = (COSNumber) operands.get(1);
+ Point2D p = transform(x.doubleValue(), y.doubleValue());
+
+ pdfPage.getCurrentPath().lineTo((float) p.getX(), (float) p.getY());
+
+ if (log.isTraceEnabled()) {
+ log.trace("Adding line to x:" + p.getX() + ",y:" + p.getY());
+ }
+ } catch (Exception e) {
+ log.warn("Error processing operator 'l'.", e);
+ }
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/construction/MoveTo.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/construction/MoveTo.java
new file mode 100644
index 0000000..b43de2e
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/construction/MoveTo.java
@@ -0,0 +1,73 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.pdf.operator.path.construction;
+
+import java.awt.geom.Point2D;
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.pdfbox.cos.COSNumber;
+import org.pdfbox.util.PDFOperator;
+
+import at.knowcenter.wag.egov.egiz.pdf.PDFPage;
+import at.knowcenter.wag.egov.egiz.pdf.operator.path.PathConstructionOperatorProcessor;
+
+/**
+ * Begin a new subpath by moving the current point to coordinates (x, y), omitting any connecting line segment. If the
+ * previous path construction operator in the current path was also m, the new m overrides it; no vestige of the
+ * previous m operation remains in the path.
+ *
+ * @see "PDF 1.7 specification, Section 8.5.2 'Path Construction Operators'"
+ * @author PdfBox, modified by Datentechnik Innovation GmbH
+ */
+public class MoveTo extends PathConstructionOperatorProcessor {
+
+ private Log log = LogFactory.getLog(getClass());
+
+ public MoveTo(PDFPage context) {
+ super(context);
+ }
+
+ @Override
+ public void process(PDFOperator operator, List operands) throws IOException {
+ try {
+ PDFPage pdfPage = (PDFPage) context;
+
+ COSNumber x = (COSNumber) operands.get(0);
+ COSNumber y = (COSNumber) operands.get(1);
+ Point2D p = transform(x.doubleValue(), y.doubleValue());
+
+ pdfPage.getCurrentPath().moveTo((float) p.getX(), (float) p.getY());
+
+ if (log.isTraceEnabled()) {
+ log.trace("Moving current path to x:" + p.getX() + ",y:" + p.getY());
+ }
+ } catch (Exception e) {
+ log.warn("Error processing operator 'm'.", e);
+ }
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/painting/CloseAndStrokePath.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/painting/CloseAndStrokePath.java
new file mode 100644
index 0000000..54f4af8
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/painting/CloseAndStrokePath.java
@@ -0,0 +1,59 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.pdf.operator.path.painting;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.pdfbox.util.PDFOperator;
+
+import at.knowcenter.wag.egov.egiz.pdf.PDFPage;
+import at.knowcenter.wag.egov.egiz.pdf.operator.path.PathPaintingOperatorProcessor;
+
+/**
+ * Close and stroke the path. This operator shall have the same effect as the sequence <code>h S</code>.
+ *
+ * @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 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.pdf.operator.path.painting;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.pdfbox.util.PDFOperator;
+
+import at.knowcenter.wag.egov.egiz.pdf.PDFPage;
+import at.knowcenter.wag.egov.egiz.pdf.operator.path.PathPaintingOperatorProcessor;
+
+/**
+ * Close, fill, and then stroke the path, using the even-odd rule to determine the region to fill. This operator shall
+ * have the same effect as the sequence <code>h B*</code>.
+ *
+ * @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 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.pdf.operator.path.painting;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.pdfbox.util.PDFOperator;
+
+import at.knowcenter.wag.egov.egiz.pdf.PDFPage;
+import at.knowcenter.wag.egov.egiz.pdf.operator.path.PathPaintingOperatorProcessor;
+
+/**
+ * Close, fill, and then stroke the path, using the nonzero winding number rule to determine the region to fill. This
+ * operator shall have the same effect as the sequence <code>h B</code>.
+ *
+ * @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 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.pdf.operator.path.painting;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.pdfbox.util.PDFOperator;
+
+import at.knowcenter.wag.egov.egiz.pdf.PDFPage;
+import at.knowcenter.wag.egov.egiz.pdf.operator.path.PathPaintingOperatorProcessor;
+
+/**
+ * End the path object without filling or stroking it. This operator shall be a path-painting no-op, used primarily for
+ * the side effect of changing the current clipping path.
+ *
+ * @see "PDF 1.7 specification, Section 8.5.3 'Path-Painting Operators'"
+ * @author PdfBox, modified by Datentechnik Innovation GmbH
+ */
+public class EndPath extends PathPaintingOperatorProcessor {
+
+ private Log log = LogFactory.getLog(getClass());
+
+ public EndPath(PDFPage context) {
+ super(context);
+ }
+
+ @Override
+ public void process(PDFOperator operator, List operands) throws IOException {
+ try {
+ PDFPage pdfPage = (PDFPage) context;
+
+ log.debug("Ending path " + pdfPage.getCurrentPath());
+ pdfPage.getCurrentPath().reset();
+
+ if (log.isTraceEnabled()) {
+ log.trace("End path without filling or stroking.");
+ }
+
+ } catch (Exception e) {
+ log.warn("Error processing operator 'n'.", e);
+ }
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/painting/FillEvenOddAndStrokePath.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/painting/FillEvenOddAndStrokePath.java
new file mode 100644
index 0000000..8a42dff
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/painting/FillEvenOddAndStrokePath.java
@@ -0,0 +1,72 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.pdf.operator.path.painting;
+
+import java.awt.geom.GeneralPath;
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.pdfbox.util.PDFOperator;
+
+import at.knowcenter.wag.egov.egiz.pdf.PDFPage;
+import at.knowcenter.wag.egov.egiz.pdf.operator.path.PathPaintingOperatorProcessor;
+
+/**
+ * Fill and then stroke the path, using the even-odd rule to determine the region to fill. This operator shall produce
+ * the same result as <code>B</code>, except that the path is filled as if with <code>f*</code> instead of
+ * <code>f</code>.
+ *
+ * @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 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.pdf.operator.path.painting;
+
+import java.awt.geom.GeneralPath;
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.pdfbox.util.PDFOperator;
+
+import at.knowcenter.wag.egov.egiz.pdf.PDFPage;
+import at.knowcenter.wag.egov.egiz.pdf.operator.path.PathPaintingOperatorProcessor;
+
+/**
+ * Fill and then stroke the path, using the nonzero winding number rule to determine the region to fill. This operator
+ * shall produce the same result as constructing two identical path objects, painting the first with <code>f</code> and
+ * the second with <code>S</code>.
+ *
+ * @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 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.pdf.operator.path.painting;
+
+import java.awt.Rectangle;
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.pdfbox.util.PDFOperator;
+
+import at.knowcenter.wag.egov.egiz.pdf.PDFPage;
+import at.knowcenter.wag.egov.egiz.pdf.operator.path.PathPaintingOperatorProcessor;
+
+/**
+ * Fill the path, using the even-odd rule to determine the region to fill.
+ *
+ * @see "PDF 1.7 specification, Section 8.5.3 'Path-Painting Operators'"
+ * @author PdfBox, modified by Datentechnik Innovation GmbH
+ */
+public class FillPathEvenOddRule extends PathPaintingOperatorProcessor {
+
+ private Log log = LogFactory.getLog(getClass());
+
+ public FillPathEvenOddRule(PDFPage context) {
+ super(context);
+ }
+
+ @Override
+ public void process(PDFOperator operator, List operands) throws IOException {
+ try {
+ PDFPage pdfPage = (PDFPage) context;
+
+ pdfPage.getCurrentPath().setWindingRule(java.awt.geom.GeneralPath.WIND_EVEN_ODD);
+ Rectangle bounds = pdfPage.getCurrentPath().getBounds();
+ pdfPage.getCurrentPath().reset();
+
+ if (log.isTraceEnabled()) {
+ log.trace("Filling path, using even-odd rule.");
+ }
+
+ pdfPage.registerPathBounds(bounds);
+
+ } catch (Exception e) {
+ log.warn("Error processing operator 'f*'.", e);
+ }
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/painting/FillPathNonZeroWindingNumberRule.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/painting/FillPathNonZeroWindingNumberRule.java
new file mode 100644
index 0000000..b350009
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/painting/FillPathNonZeroWindingNumberRule.java
@@ -0,0 +1,72 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.pdf.operator.path.painting;
+
+import java.awt.Rectangle;
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.pdfbox.util.PDFOperator;
+
+import at.knowcenter.wag.egov.egiz.pdf.PDFPage;
+import at.knowcenter.wag.egov.egiz.pdf.operator.path.PathPaintingOperatorProcessor;
+
+/**
+ * Fill the path, using the nonzero winding number rule to determine the region to fill. Any subpaths that are open
+ * shall be implicitly closed before being filled.
+ *
+ * @see "PDF 1.7 specification, Section 8.5.3 'Path-Painting Operators'"
+ * @author PdfBox, modified by Datentechnik Innovation GmbH
+ */
+public class FillPathNonZeroWindingNumberRule extends PathPaintingOperatorProcessor {
+
+ private Log log = LogFactory.getLog(getClass());
+
+ public FillPathNonZeroWindingNumberRule(PDFPage context) {
+ super(context);
+ }
+
+ @Override
+ public void process(PDFOperator operator, List operands) throws IOException {
+ try {
+ PDFPage pdfPage = (PDFPage) context;
+
+ pdfPage.getCurrentPath().setWindingRule(java.awt.geom.GeneralPath.WIND_NON_ZERO);
+ Rectangle bounds = pdfPage.getCurrentPath().getBounds();
+ pdfPage.getCurrentPath().reset();
+
+ if (log.isTraceEnabled()) {
+ log.trace("Filling path, using nonzero winding number rule.");
+ }
+
+ pdfPage.registerPathBounds(bounds);
+
+ } catch (Exception e) {
+ log.warn("Error processing operator 'f/F'.", e);
+ }
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/painting/StrokePath.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/painting/StrokePath.java
new file mode 100644
index 0000000..9dfce7e
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/operator/path/painting/StrokePath.java
@@ -0,0 +1,70 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.pdf.operator.path.painting;
+
+import java.awt.Rectangle;
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.pdfbox.util.PDFOperator;
+
+import at.knowcenter.wag.egov.egiz.pdf.PDFPage;
+import at.knowcenter.wag.egov.egiz.pdf.operator.path.PathPaintingOperatorProcessor;
+
+/**
+ * Strokes the path.
+ *
+ * @see "PDF 1.7 specification, Section 8.5.3 'Path-Painting Operators'"
+ * @author PdfBox, modified by Datentechnik Innovation GmbH
+ */
+public class StrokePath extends PathPaintingOperatorProcessor {
+
+ private Log log = LogFactory.getLog(getClass());
+
+ public StrokePath(PDFPage context) {
+ super(context);
+ }
+
+ @Override
+ public void process(PDFOperator operator, List operands) throws IOException {
+ try {
+ PDFPage pdfPage = (PDFPage) context;
+
+ Rectangle bounds = pdfPage.getCurrentPath().getBounds();
+ pdfPage.getCurrentPath().reset();
+
+ if (log.isTraceEnabled()) {
+ log.trace("Stroking path.");
+ }
+
+ pdfPage.registerPathBounds(bounds);
+
+ } catch (Exception e) {
+ log.warn("Error processing operator 'S'.", e);
+ }
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureObject.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureObject.java
index 9e28213..b5a05ed 100644
--- a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureObject.java
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureObject.java
@@ -77,7 +77,7 @@ import at.knowcenter.wag.egov.egiz.tools.Normalizer;
* All values that build or used by the signation creation process, call the
* external services, can read or set separately. All other values are defined
* in the settings file.
- *
+ *
* @author wlackner
* @author modified by <a href="mailto:thomas.knall@iaik.tugraz.at">Thomas Knall</a>
*/
@@ -138,7 +138,7 @@ public class SignatureObject implements Serializable
public static final String SIG_CER_DIG = "SIG_CER_DIG";
private X509Cert x509Cert_ = null;
-
+
private String timeStamp = null;
// public static final String SIG_RES = "SIG_RES";
@@ -194,7 +194,7 @@ public class SignatureObject implements Serializable
/**
* The raw xml response from the connector that was used to set the values in
* this SignatureObject.
- *
+ *
* <p>
* 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! <br>
* <b>If the key equals to <code>SIG_VALUE</code> all whitespaces are
* removed! </b> <br>
- *
+ *
* @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
* <code>SIG_NORM</code> and the value is <code>null</code> 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 <code>null</code> the key itself is
* returned as caption! If the key does not exist the method returns
* <code>null</code>.
- *
+ *
* @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
* <li>add the <code>.txt</code> extension to get the meta information of
* the certificate</li>
* </ol>
- *
+ *
* The certificate meta file is build by the base64 coded issuer string and
* the cert digest value devided by the <code>@</code> 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
* <li>add the <code>.txt</code> extension to get the meta information of
* the certificate</li>
* </ol>
- *
+ *
* The certificate meta file is build by the base64 coded issuer string and
* the cert digest value devided by the <code>@</code> 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
* <li>add the <code>.txt</code> extension to get the meta information of
* the certificate</li>
* </ol>
- *
+ *
* The certificate meta file is build by the base64 coded issuer string and
* the cert digest value devided by the <code>@</code> 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.
- *
+ *
* <p>
* This should be used by the Connector to pass the response String to the
* signer.
* </p>
- *
+ *
* @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<String> getSignatureTypesForSignature() {
+ Set<String> filteredResult = new HashSet<String>();
+ for (String signatureProfileId : (Set<String>) typeDefMap_.keySet()) {
+ if (State.fromString(settings_.getSetting(TYPES + "." + signatureProfileId, null)).canSign()) {
+ filteredResult.add(signatureProfileId);
+ }
+ }
+ return filteredResult;
+ }
+
/**
* @return a list of signature type definitions
*/
@@ -453,6 +587,23 @@ public class SignatureTypes
{
return new ArrayList(this.typeDefMap_.values());
}
+
+ /**
+ * Returns a (filtered) list of signature type definitions useable for verification. Those definitions for profiles
+ * that are not allowed to be used for verification are filtered.
+ *
+ * @return A filtered list of signature type definitions.
+ */
+ @SuppressWarnings("unchecked")
+ public List<SignatureTypeDefinition> getSignatureTypeDefinitionsForVerification() {
+ List<SignatureTypeDefinition> filteredResult = new ArrayList<SignatureTypeDefinition>(typeDefMap_.size());
+ for (String signatureProfileId : (Set<String>) typeDefMap_.keySet()) {
+ if (State.fromString(settings_.getSetting(TYPES + "." + signatureProfileId, null)).canVerify()) {
+ filteredResult.add((SignatureTypeDefinition) typeDefMap_.get(signatureProfileId));
+ }
+ }
+ return filteredResult;
+ }
/**
* This method returns the corresponding signature type definition to a given
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/X509Cert.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/X509Cert.java
index 7b4e463..e11a38c 100644
--- a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/X509Cert.java
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/X509Cert.java
@@ -99,7 +99,7 @@ public class X509Cert implements Serializable
* statement and remove all whitespaces in the string. The result string
* (base64) is used by reconstructing the certiface sign by the verification
* process.
- *
+ *
* @param certString
* the string to normalize
* @return the normalized cert string
@@ -115,7 +115,7 @@ public class X509Cert implements Serializable
/**
* This method initialzes a X509Certificate by a string value. It must be
* coded Base64 or as plain binary stream.
- *
+ *
* @param certString
* the certificate string to analyse
* @return the X509Cert object
@@ -150,7 +150,9 @@ public class X509Cert implements Serializable
String serial_num = cert.getSerialNumber().toString();
String issuer = cert.getIssuerDN().getName();
- issuer = issuer.replaceAll(", ", ",");
+ // fixed by dti: commas within issuer rdns are escapted by "\,". These escapted commas must not be replaced.
+// issuer = issuer.replaceAll(", ", ",");
+ issuer = issuer.replaceAll("[^\\\\], ", ",");
String subject_name = cert.getSubjectDN().toString();
x509_cert.setSerialNumber(serial_num);
x509_cert.setIssuerName(issuer);
@@ -174,7 +176,7 @@ public class X509Cert implements Serializable
}
return x509_cert;
}
-
+
public static X509Cert initByX509Certificate(X509Certificate cert) throws CertificateEncodingException {
X509Cert x509_cert = new X509Cert();
x509_cert.setX509Cert(cert);
@@ -182,7 +184,9 @@ public class X509Cert implements Serializable
String serial_num = cert.getSerialNumber().toString();
String issuer = cert.getIssuerDN().getName();
- issuer = issuer.replaceAll(", ", ",");
+ // fixed by dti: commas within issuer rdns are escapted by "\,". These escapted commas must not be replaced.
+// issuer = issuer.replaceAll(", ", ",");
+ issuer = issuer.replaceAll("[^\\\\], ", ",");
String subject_name = cert.getSubjectDN().toString();
x509_cert.setSerialNumber(serial_num);
x509_cert.setIssuerName(issuer);
@@ -210,7 +214,9 @@ public class X509Cert implements Serializable
String serial_num = cert.getSerialNumber().toString();
String issuer = cert.getIssuerDN().getName();
- issuer = issuer.replaceAll(", ", ",");
+ // fixed by dti: commas within issuer rdns are escapted by "\,". These escapted commas must not be replaced.
+// issuer = issuer.replaceAll(", ", ",");
+ issuer = issuer.replaceAll("[^\\\\], ", ",");
String subject_name = cert.getSubjectDN().toString();
x509_cert.setSerialNumber(serial_num);
x509_cert.setIssuerName(issuer);
@@ -226,7 +232,7 @@ public class X509Cert implements Serializable
{
// nothing to do, cause certString is not X509 conformc
logger_.error(ce.getMessage(), ce);
-
+
}
catch (IOException ioe)
{
@@ -240,7 +246,7 @@ public class X509Cert implements Serializable
/**
* This method initialzes a X509Certificate by a file path value. The file
* must be a plain binary file like .cer format.
- *
+ *
* @param filePath
* the certificate file to analyse
* @return the X509Cert object
@@ -276,7 +282,9 @@ public class X509Cert implements Serializable
String serial_num = cert.getSerialNumber().toString();
String issuer = cert.getIssuerDN().getName();
- issuer = issuer.replaceAll(", ", ",");
+ // fixed by dti: commas within issuer rdns are escapted by "\,". These escapted commas must not be replaced.
+// issuer = issuer.replaceAll(", ", ",");
+ issuer = issuer.replaceAll("[^\\\\], ", ",");
String subject_name = cert.getSubjectDN().toString();
x509_cert.setSerialNumber(serial_num);
x509_cert.setIssuerName(issuer);
@@ -300,7 +308,7 @@ public class X509Cert implements Serializable
/**
* This method initialzes a X509Certificate by a file value. The file must be
* a plain binary file like .cer format.
- *
+ *
* @param certFile
* the certificate file to analyse
* @return the X509Cert object
@@ -314,7 +322,7 @@ public class X509Cert implements Serializable
/**
* This method checks if a certificate file is X509 conform.
- *
+ *
* @return true if a certificate file is X509 conform, false otherwise
*/
public boolean isX509Cert()
@@ -480,7 +488,7 @@ public class X509Cert implements Serializable
/**
* This method checks, if a X509Certificate has a public key with the rsa
* algorithm.
- *
+ *
* @return true if the public key is produced with rsa, false otherwise
*/
public boolean isRSA()
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/BKUConnector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/BKUConnector.java
index c3b6421..e4d78c3 100644
--- a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/BKUConnector.java
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/BKUConnector.java
@@ -49,9 +49,9 @@ import at.knowcenter.wag.egov.egiz.tools.CodingHelper;
/**
* Connector for communicating with BKU.
- *
+ *
* @deprecated use the new connectors.
- *
+ *
* @author wlackner
* @author wprinz
*/
@@ -59,7 +59,7 @@ public class BKUConnector implements LocalConnector
{
/**
* ConnectorInformation that identifies this Connector to the system.
- *
+ *
* @see at.knowcenter.wag.egov.egiz.sig.ConnectorFactory
* @see ConnectorInformation
*/
@@ -85,7 +85,7 @@ public class BKUConnector implements LocalConnector
/**
* load the inital signature settings
- *
+ *
* @see SettingsReader
*/
public void loadSettings() throws SignatureException
@@ -111,7 +111,7 @@ public class BKUConnector implements LocalConnector
* SignatureObject is filled out by the parsed BKU-Response. <br>
* If an error request is send back from BKU, an error message is generated an
* an exception is thrown.
- *
+ *
* @param sigType
* the type of the SignatureObject that should be returned
* @param userName
@@ -137,7 +137,7 @@ public class BKUConnector implements LocalConnector
* This method generates the BKU verify prozess. It checks if the given
* SignatureObject is signed by MOA or BKU. The verify template string is
* filled out by the corresponding method.
- *
+ *
* @param normalizedText
* the normalized text to verify
* @param sigObject
@@ -163,7 +163,7 @@ public class BKUConnector implements LocalConnector
* 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 from the BKU sign-request
* @param sigObj
@@ -177,7 +177,7 @@ public class BKUConnector implements LocalConnector
private void parseCreateXMLResponse(Properties response_properties, SignatureObject sigObj) throws SignatureException
{
String xmlResponse = response_properties.getProperty("response_string");
-
+
Pattern sig_val_p_s = Pattern.compile("<[\\w]*:?SignatureValue>");
Pattern sig_val_p_e = Pattern.compile("</[\\w]*:?SignatureValue>");
Pattern iss_nam_p_s = Pattern.compile("<[\\w]*:?X509IssuerName>");
@@ -280,7 +280,7 @@ public class BKUConnector implements LocalConnector
ids[2] = extractId(xmlResponse, "signed-data-object-");
ids[3] = extractId(xmlResponse, "etsi-data-reference-");
ids[4] = extractId(xmlResponse, "etsi-data-object-");
-
+
//TODO hotfix - already deprecated
String final_ids =SignatureObject.formatSigIds(response_properties, ids);
//sigObj.setSignationIDs(ids);
@@ -289,7 +289,7 @@ public class BKUConnector implements 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
@@ -301,13 +301,13 @@ public class BKUConnector implements LocalConnector
String id = null;
int start_idx = text.indexOf(name) + name.length();
int end_idx = text.indexOf("\"", start_idx);
-
+
// TODO hotfix! - already deprecated
- final int quot_end_idx = end_idx;
+ final int quot_end_idx = end_idx;
final int squot_end_idx = text.indexOf("'", start_idx);
end_idx = Math.min(quot_end_idx, squot_end_idx);
// TODO hotfix end! - already deprecated
-
+
id = text.substring(start_idx, end_idx);
if (logger_.isDebugEnabled())
{
@@ -319,7 +319,7 @@ public class BKUConnector implements LocalConnector
/**
* This method reads the verify template from the file system and fills out
* the template with the SignatureObject values.
- *
+ *
* @param normalizedText
* the normalized text to veryfied
* @param sigObject
@@ -362,7 +362,7 @@ public class BKUConnector implements LocalConnector
verify_template = getConnectorValueFromProfile(sigObject.getSignationType(), "bku.verify.template2"); //"./templates/BKUVerifyTemplateB64_neueBKU.xml";
sig_prop_filename = getConnectorValueFromProfile(sigObject.getSignationType(), "bku.verify.template2.SP"); //"./templates/BKUVerifyTemplateSP_neueBKU.xml";
}
-
+
//String ver_temp_str = FileHelper.readFromFile(SettingsReader.relocateFile(verify_template));
String ver_temp_str = this.settings_.readInternalResourceAsString(verify_template);
@@ -388,13 +388,18 @@ public class BKUConnector implements LocalConnector
}
sig_prop_str = sig_prop_str.replaceFirst("SigningTimeReplace", sigObject.getSignationDate());
-
+
String issuer_name = sigObject.getSignationIssuer();
// The issuer is already unicode, so it mustn't be encoded again.
//byte[] issuer_name = CodingHelper.encodeUTF8(sigObject.getSignationIssuer());
// new String(issuer_name); // this would double encode the String, not to mention the missing encoding
- sig_prop_str = sig_prop_str.replaceFirst("X509IssuerNameReplace", issuer_name);
-
+
+ // 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.
+// sig_prop_str = sig_prop_str.replaceFirst("X509IssuerNameReplace", issuer_name);
+ sig_prop_str = sig_prop_str.replace("X509IssuerNameReplace", issuer_name);
+
sig_prop_str = sig_prop_str.replaceFirst("X509SerialNumberReplace", sigObject.getSignationSerialNumber());
sig_prop_str = sig_prop_str.replaceFirst("DigestValueX509CertificateReplace", sigObject.getX509CertificateDigest());
sig_prop_str = sig_prop_str.replaceFirst("SigIdReplace", ids[0]);
@@ -403,30 +408,30 @@ public class BKUConnector implements LocalConnector
ver_temp_str = ver_temp_str.replaceFirst("CertAlgReplace", cert_alg);
ver_temp_str = ver_temp_str.replaceFirst("TemplateQualifyingPropertiesReplace", sig_prop_str);
byte[] sig_prop_code = CodingHelper.buildDigest(sig_prop_str.getBytes("UTF-8"), "sha1");
-
+
// TODO hotfix - already deprecated
if (neue_bku)
{
final String ETSI_SIGNED_PROPERTIES_START_TAG = "<etsi:SignedProperties"; // xml name spaces follow, so this is not a complete tag...
final String ETSI_SIGNED_PROPERTIES_END_TAG = "</etsi:SignedProperties>";
-
+
final int hash_start = sig_prop_str.indexOf(ETSI_SIGNED_PROPERTIES_START_TAG);
assert hash_start >= 0;
final int hash_end = sig_prop_str.indexOf(ETSI_SIGNED_PROPERTIES_END_TAG, hash_start) + ETSI_SIGNED_PROPERTIES_END_TAG.length();
assert hash_end - ETSI_SIGNED_PROPERTIES_END_TAG.length() >= 0;
assert hash_end > hash_start;
-
+
final String string_to_be_hashed = sig_prop_str.substring(hash_start, hash_end);
logger_.debug("etsi:SignedProperties string to be hashed: " + string_to_be_hashed);
-
+
logger_.debug("\n--------------------- ETSI properties string to be hashed: start ---------------------");
logger_.debug(string_to_be_hashed);
logger_.debug("\n--------------------- ETSI properties string to be hashed: stop ---------------------");
-
+
final byte [] bytes_to_be_hashed = string_to_be_hashed.getBytes("UTF-8");
sig_prop_code = CodingHelper.buildDigest(bytes_to_be_hashed, "sha1");
}
-
+
String sig_prop_hash = CodingHelper.encodeBase64(sig_prop_code);
ver_temp_str = ver_temp_str.replaceFirst("DigestValueSignedPropertiesReplace", sig_prop_hash);
if (logger_.isDebugEnabled())
@@ -453,7 +458,7 @@ public class BKUConnector implements LocalConnector
//String raw_b64 = CodingHelper.encodeUTF8AsBase64(normalizedText);
String raw_b64 = CodingHelper.encodeBase64(data_value);
-
+
ver_temp_str = ver_temp_str.replaceFirst("Base64ContentReplace", raw_b64);
ver_temp_str = ver_temp_str.replaceFirst("DigestValueSignedDataReplace", object_data_hash);
@@ -479,7 +484,7 @@ public class BKUConnector implements LocalConnector
* 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
@@ -621,8 +626,8 @@ public class BKUConnector implements LocalConnector
return sig_res;
}
-
-
+
+
public String prepareSignRequest(String userName, String signText,
String signType) throws SignatureException
@@ -636,7 +641,7 @@ public class BKUConnector implements LocalConnector
//String sign_req_str = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename));
String sign_req_str = this.settings_.readInternalResourceAsString(sign_request_filename);
- //this.verify_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_request_filename));
+ //this.verify_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_request_filename));
if (logger_.isDebugEnabled())
{
//logger_.debug(sign_request_filename + "_signText.xml :" + signText);
@@ -660,7 +665,7 @@ public class BKUConnector implements LocalConnector
SignatureObject sigObject) throws SignatureException
{
String verify_request = getVerifyRequestTemplateFileName(sigObject.getSignationType());
-
+
//String verify_req_str = FileHelper.readFromFile(SettingsReader.relocateFile(verify_request));
String verify_req_str = this.settings_.readInternalResourceAsString(verify_request);
@@ -681,7 +686,11 @@ public class BKUConnector implements LocalConnector
// get the BKU-template
verify_template_str = getVerifyTemplate(normalizedText, sigObject);
}
- verify_req_str = verify_req_str.replaceFirst("XMLContentReplace", verify_template_str);
+ // 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_req_str = verify_req_str.replaceFirst("XMLContentReplace", verify_template_str);
+ verify_req_str = verify_req_str.replace("XMLContentReplace", verify_template_str);
if (logger_.isDebugEnabled())
{
logger_.debug("verify_req_str.xml : " + verify_req_str);
@@ -692,7 +701,7 @@ public class BKUConnector implements LocalConnector
/**
* Sends the request to the given URL.
- *
+ *
* @param url
* The URL.
* @param request_string
@@ -722,7 +731,7 @@ public class BKUConnector implements LocalConnector
// TODO hotfix - already deprecated
String response_string = response_properties.getProperty("response_string");
-
+
SignatureObject sig_obj = new SignatureObject();
sig_obj.setRawSignatureResponse(response_string);
try
@@ -783,7 +792,7 @@ public class BKUConnector implements LocalConnector
public SignatureResponse analyzeVerifyResponse(Properties response_properties) throws SignatureException
{
String response_string = response_properties.getProperty("response_string");
-
+
if (!response_string.equals(""))
{
Pattern erc_p_s = Pattern.compile("<[\\w]*:?ErrorCode>");
@@ -880,13 +889,13 @@ public class BKUConnector implements LocalConnector
/**
* Returns the type of this BKU-like connector.
- *
+ *
* <p>
* 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.
* </p>
- *
+ *
* @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.
- *
+ *
* <p>
* Just for convenience.
* </p>
@@ -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. <br>
* If an error request is send back from MOA, an error message is generated an
* an exception is thrown.
- *
+ *
* @param sigType
* the type of the SignatureObject that should be returned
* @param userName
@@ -282,7 +282,7 @@ public class MOAConnector implements Connector
* SignatureValue, X509IssuerName, SigningTime, X509SerialNumber,
* X509Certificate, CertDigest and DigestValues. If the X509Certificate is
* extracted it would be stored in the certificates directory.
- *
+ *
* @param xmlResponse
* the response string from the MOA sign-request
* @param sigObj
@@ -393,7 +393,7 @@ public class MOAConnector implements Connector
/**
* This method reads the verify template from the file system and fills out
* the template with the SignatureObject values.
- *
+ *
* @param normalizedText
* the normalized text to veryfied
* @param sigObject
@@ -453,12 +453,18 @@ public class MOAConnector implements Connector
// byte[] issuer_name =
// CodingHelper.encodeUTF8(sigObject.getSignationIssuer());
// new String(issuer_name)
- sig_prop_str = sig_prop_str.replaceFirst("X509IssuerNameReplace", sigObject.getSignationIssuer());
+
+ // 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.
+// sig_prop_str = sig_prop_str.replaceFirst("X509IssuerNameReplace", sigObject.getSignationIssuer());
+ sig_prop_str = sig_prop_str.replace("X509IssuerNameReplace", sigObject.getSignationIssuer());
sig_prop_str = sig_prop_str.replaceFirst("X509SerialNumberReplace", sigObject.getSignationSerialNumber());
sig_prop_str = sig_prop_str.replaceFirst("DigestValueX509CertificateReplace", sigObject.getX509CertificateDigest());
verify_req_str = verify_req_str.replaceFirst("CertAlgReplace", cert_alg);
- verify_req_str = verify_req_str.replaceFirst("TemplateSignedPropertiesReplace", sig_prop_str);
+// verify_req_str = verify_req_str.replaceFirst("TemplateSignedPropertiesReplace", sig_prop_str);
+ verify_req_str = verify_req_str.replace("TemplateSignedPropertiesReplace", sig_prop_str);
byte[] sig_prop_code = CodingHelper.buildDigest(sig_prop_str.getBytes("UTF-8"), "sha1"); // added
// the
// ("UTF-8")
@@ -509,7 +515,7 @@ public class MOAConnector implements Connector
* This method generates the MOA verify prozess. It checks if the given
* SignatureObject is signed by MOA or BKU. The verify template string is
* filled out by the corresponding method.
- *
+ *
* @param normalizedText
* the normalized text to verify
* @param sigObject
@@ -548,7 +554,12 @@ public class MOAConnector implements Connector
BKUConnector bku_conn = new BKUConnector();
verify_template_str = bku_conn.getVerifyTemplate(normalizedText, sigObject);
}
- verify_req_str = verify_req_str.replaceFirst("XMLContentReplace", verify_template_str);
+
+ // 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_req_str = verify_req_str.replaceFirst("XMLContentReplace", verify_template_str);
+ verify_req_str = verify_req_str.replace("XMLContentReplace", verify_template_str);
verify_req_str = verify_req_str.replaceFirst("TrustProfileIDReplace", trust_profile);
if (logger_.isDebugEnabled())
@@ -564,10 +575,6 @@ public class MOAConnector implements Connector
}
catch (WebException we)
{
- if (logger_.isDebugEnabled())
- {
- we.printStackTrace();
- }
SignatureException se = new SignatureException(we.getErrorCode(), we);
throw se;
}
@@ -616,7 +623,7 @@ public class MOAConnector implements Connector
* 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 MOA-verify request
* @return SignatureResponse object
@@ -639,7 +646,7 @@ public class MOAConnector implements Connector
Pattern cert_qualified_p = Pattern.compile("<QualifiedCertificate/>");
Matcher cert_qualified_m = cert_qualified_p.matcher(xmlResponse);
// [tknall] stop qualified certificate
-
+
Pattern sig_chk_p_s = Pattern.compile("<SignatureCheck>");
Pattern sig_chk_p_e = Pattern.compile("</SignatureCheck>");
Pattern man_chk_p_s = Pattern.compile("<SignatureManifestCheck>");
@@ -671,11 +678,11 @@ public class MOAConnector implements Connector
Matcher cert_m_e = cert_p_e.matcher(xmlResponse);
SignatureResponse sig_res = new SignatureResponse();
-
+
// [tknall] start qualified certificate
sig_res.setQualifiedCertificate(cert_qualified_m.find());
// [tknall] stop qualified certificate
-
+
// public authority
Pattern publicAuthority_p = Pattern.compile("<PublicAuthority/>");
Matcher publicAuthority_m = publicAuthority_p.matcher(xmlResponse);
@@ -821,7 +828,7 @@ public class MOAConnector implements Connector
* SOAP Message send and recieve by the AXIS module. The Response SOAP message
* of the MOA server is parsed by AXIS and the message envelope is send back
* to the calling method.
- *
+ *
* @param requestString
* the request string (XML) to send.
* @param serviceMode
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUHelper.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUHelper.java
index ee250ff..908ed57 100644
--- a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUHelper.java
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUHelper.java
@@ -60,14 +60,14 @@ import at.knowcenter.wag.egov.egiz.tools.CodingHelper;
/**
* Contains static helper methods used by the BKU Connectors.
- *
+ *
* @author wprinz
*/
public final class BKUHelper
{
private static final Pattern ALLOWED_SL_RESPONSE_PATTERN = Pattern.compile("^.*<[\\w]*:?(CreateXMLSignatureResponse|VerifyXMLSignatureResponse)[^>]*>(.*)</[\\w]*:?(CreateXMLSignatureResponse|VerifyXMLSignatureResponse)>.*$", Pattern.DOTALL);
-
+
/**
* The log.
*/
@@ -75,21 +75,21 @@ public final class BKUHelper
/**
* Encodes the given SignatureData to a valid Base64Content.
- *
+ *
* <p>
* The data is Base64 encoded. If the mime-type suggests that the data is
* binary, it is Base64 encoded for a second time.
* </p>
- *
+ *
* @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
* <p>
* This is useful for building the hash.
* </p>
- *
+ *
* @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.
- *
+ *
* <p>
* 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.
* </p>
- *
+ *
* @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("<Base64Content>"); //$NON-NLS-1$
Pattern b64_p_e = Pattern.compile("</Base64Content>"); //$NON-NLS-1$
Matcher b64_m_s = b64_p_s.matcher(hashInputData);
Matcher b64_m_e = b64_p_e.matcher(hashInputData);
boolean hashInputDataFound = b64_m_s.find() && b64_m_e.find();
-
+
String b64 = hashInputDataFound ? hashInputData.substring(b64_m_s.end(), b64_m_e.start()) : "";
sig_res.setHashInputData(b64);
@@ -623,7 +622,7 @@ public final class BKUHelper
public static String formDateTimeElement(Date verificationTime, String namespace)
{
String nsPrefix = StringUtils.isBlank(namespace) ? "" : (namespace + ":");
-
+
String dateTimeElement = "";
if (verificationTime != null)
{
@@ -633,25 +632,25 @@ public final class BKUHelper
df.setTimeZone(TimeZone.getTimeZone("UTC"));
String dateTime = df.format(verificationTime) + "Z";
log.debug("DateTime (VerificationTime in UTC) = " + dateTime);
-
+
dateTimeElement = "<" + nsPrefix + "DateTime>" + dateTime + "</" + nsPrefix + "DateTime>";
};
return dateTimeElement;
}
-
+
public static String getBKUIdentifier(Properties parsedResponseProperties) {
-
+
// http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung.response.browser
String bkuServerHeader = parsedResponseProperties.getProperty(BKUPostConnection.BKU_SERVER_HEADER_KEY);
// http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung.response.dataurl
String bkuUserAgentHeader = parsedResponseProperties.getProperty(BKUPostConnection.BKU_USER_AGENT_HEADER_KEY);
-
+
String bkuSignatureLayout = parsedResponseProperties.getProperty(BKUPostConnection.BKU_SIGNATURE_LAYOUT_HEADER_KEY);
-
+
return getBKUIdentifier(bkuServerHeader, bkuUserAgentHeader, bkuSignatureLayout);
}
-
+
public static String getBKUIdentifier(String bkuServerHeader, String bkuUserAgentHeader, String bkuSignatureLayout) {
log.debug("BKU response header \"user-agent\": " + bkuUserAgentHeader);
@@ -659,7 +658,7 @@ public final class BKUHelper
log.trace("BKU response header \"" + Constants.BKU_HEADER_SIGNATURE_LAYOUT + "\": " + bkuSignatureLayout);
String result = null;
-
+
if (bkuServerHeader != null) {
result = bkuServerHeader;
} else if (bkuUserAgentHeader != null) {
@@ -667,7 +666,7 @@ public final class BKUHelper
} else {
log.warn("Unable to find any BKU identifier (neither header value \"user-agent\" nor \"server\".)");
}
-
+
if (bkuSignatureLayout != null && result != null) {
log.debug("BKU response header \"" + Constants.BKU_HEADER_SIGNATURE_LAYOUT + "\" found.");
String signatureLayoutData = " " + Constants.BKU_HEADER_SIGNATURE_LAYOUT + "/" + bkuSignatureLayout;
@@ -678,18 +677,18 @@ public final class BKUHelper
log.debug("Signature layout already encoded in server/user-agent header.");
}
}
-
+
if (result != null) {
log.debug("Returning BKU identifier \"" + result + "\"");
} else {
log.debug("Returning null BKU identifier.");
}
-
+
return result;
}
public static String getBKUIdentifier(LocalBKUParams bkuParams) {
return getBKUIdentifier(bkuParams.getServer(), bkuParams.getUserAgent(), bkuParams.getSignatureLayout());
}
-
+
}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/DetachedBKUConnector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/DetachedBKUConnector.java
index a8de41e..6926d2b 100644
--- a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/DetachedBKUConnector.java
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/DetachedBKUConnector.java
@@ -55,11 +55,11 @@ import at.knowcenter.wag.egov.egiz.tools.CodingHelper;
/**
* Connects to the BKU using the detached multipart/formdata requests.
- *
+ *
* <p>
* This feature is available since BKU version 2.7.4.
* </p>
- *
+ *
* @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.
- *
+ *
* <p>
* If confuguration parameters are not defined on that profile, the default
* parameters defined in the configuration are used.
* </p>
- *
+ *
* @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.
- *
+ *
* <p>
* This method mainly handles communication exceptions. The actual send work
* is done by doPostRequestMultipart.
* </p>
- *
+ *
* @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.
- *
+ *
* <p>
* This strongly rebuilds the XML content as retuned from a sign request.
* </p>
- *
+ *
* @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.
- *
+ *
* <p>
* If confuguration parameters are not defined on that profile, the default
* parameters defined in the configuration are used.
* </p>
- *
+ *
* <p>
* This is the new "hotfix" base64 connector.
* </p>
- *
+ *
* @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.
- *
+ *
* <p>
* This strongly rebuilds the XML content as retuned from a sign request.
* </p>
- *
+ *
* @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.
- *
+ *
* <p>
* If confuguration parameters are not defined on that profile, the default
* parameters defined in the configuration are used.
* </p>
- *
+ *
* @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.
- *
+ *
* <p>
* If confuguration parameters are not defined on that profile, the default
* parameters defined in the configuration are used.
* </p>
- *
+ *
* @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.
- *
+ *
* <p>
* This strongly rebuilds the XML content as retuned from a sign request.
* </p>
- *
+ *
* @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 = "<ReturnHashInputData/>"; //$NON-NLS-1$
-
+
/**
* The connector parameters.
*/
@@ -85,17 +85,17 @@ public class MOASoapWithAttachmentConnector implements Connector
* other configurable elements.
*/
protected Environment environment = null;
-
-
+
+
/**
* Constructor that builds the configuration environment for this connector
* according to the given profile.
- *
+ *
* <p>
* If confuguration parameters are not defined on that profile, the default
* parameters defined in the configuration are used.
* </p>
- *
+ *
* @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 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.signaturelayout.mocca;
+
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
+import at.knowcenter.wag.egov.egiz.sig.connectors.ConnectorEnvironment;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject;
+import at.knowcenter.wag.egov.egiz.sig.connectors.mocca.MOCCAHelper;
+import at.knowcenter.wag.egov.egiz.sig.sigid.DetachedMOCIdFormatter;
+import at.knowcenter.wag.egov.egiz.sig.signaturelayout.SignatureLayoutHandler;
+
+/**
+ * Layout handler for XAdES 1.4 based signature layouts.
+ *
+ * @author Datentechnik Innovation GmbH
+ */
+public class MoccaXades14SignatureLayoutHandler implements SignatureLayoutHandler {
+
+ /**
+ * The signature parameter identifier for XAdES 1.4 signatures.
+ */
+ private final static String ALGORITHM_ID = "etsi-moc-1.2";
+
+ /**
+ * Parses the given xmlResponse with respect to the specific signature layout of mocca.
+ */
+ public SignSignatureObject parseCreateXMLSignatureResponse(String xmlResponse, ConnectorEnvironment env)
+ throws ConnectorException {
+ return MOCCAHelper.parseCreateXMLResponse(xmlResponse, new DetachedMOCIdFormatter(ALGORITHM_ID), env);
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/tools/CodingHelper.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/tools/CodingHelper.java
index 5132021..3546cd7 100644
--- a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/tools/CodingHelper.java
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/tools/CodingHelper.java
@@ -38,7 +38,7 @@ import at.gv.egiz.pdfas.impl.input.helper.DataSourceHelper;
/**
* This class provides encoding and decoding methods and other coding methods.
* All methods are static!
- *
+ *
* @author wlackner
*/
public class CodingHelper
@@ -52,7 +52,7 @@ public class CodingHelper
/**
* This method encodes a given Unicode (Java) String to UTF-8 bytes and then
* encodes these UTF-8 bytes to a Base64 US-ASCII (Java) String.
- *
+ *
* @param plain_string
* to be encoded
* @return the UTF-8 and Base64 encoded string
@@ -68,7 +68,6 @@ public class CodingHelper
}
catch (UnsupportedEncodingException e)
{
- e.printStackTrace();
throw new RuntimeException(e);
}
}
@@ -76,7 +75,7 @@ public class CodingHelper
/**
* This method decodes the UTF-8 bytes from a Base64 US-ASCII (Java) String
* and decodes the UTF-8 bytes to a unicode (Java) String.
- *
+ *
* @param encoded_string
* to be decoded
* @return the Base64 and UTF-8 decoded string
@@ -92,7 +91,6 @@ public class CodingHelper
}
catch (UnsupportedEncodingException e)
{
- e.printStackTrace();
throw new RuntimeException(e);
}
}
@@ -108,7 +106,6 @@ public class CodingHelper
// try {
// utf8 = theString.getBytes("UTF-8");
// } catch (UnsupportedEncodingException e) {
- // e.printStackTrace();
// }
// return utf8;
// }
@@ -139,20 +136,19 @@ public class CodingHelper
// try {
// the_string = new String(ba, "UTF-8");
// } catch (UnsupportedEncodingException e) {
- // e.printStackTrace();
// }
// return the_string;
// }
/**
* This method decodes a given Base64 string.
- *
+ *
* <p>
* 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.
* </p>
- *
+ *
* @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
diff --git a/pdf-as-lib/src/main/java/demo/SignatureVerificationDemo.java b/pdf-as-lib/src/main/java/demo/SignatureVerificationDemo.java
index 0ba95ff..204339a 100644
--- a/pdf-as-lib/src/main/java/demo/SignatureVerificationDemo.java
+++ b/pdf-as-lib/src/main/java/demo/SignatureVerificationDemo.java
@@ -57,7 +57,7 @@ public class SignatureVerificationDemo {
/**
* Starts a demo that verifies a document.
- *
+ *
* @param args
* The parameter(s).
*/
@@ -67,7 +67,7 @@ public class SignatureVerificationDemo {
System.err.println("Please provide path of file to be verified.");
System.exit(1);
}
-
+
File configdir = new File("./work");
// look for work folder in current directory
if (!configdir.exists()) {
@@ -75,7 +75,7 @@ public class SignatureVerificationDemo {
configdir = new File("../work");
}
File signedFile = new File(args[0]);
-
+
AnalyzeResult analyzeResult = null;
try {
@@ -108,7 +108,7 @@ public class SignatureVerificationDemo {
System.out.println("Analyzing...");
analyzeResult = pdfasAPI.analyze(analyzeParameters);
System.out.println("Successfully analyzed.");
-
+
// information on non-textual objects can be used after analysis step and/or after verification
List signatures = analyzeResult.getSignatures();
if (signatures != null && !signatures.isEmpty()) {
@@ -126,7 +126,7 @@ public class SignatureVerificationDemo {
System.out.println(" -> " + info.toString());
}
System.out.println();
-
+
} else {
System.out.println("\nNo non-textual objects detected for this signature.");
}
@@ -139,7 +139,7 @@ public class SignatureVerificationDemo {
}
System.exit(1);
}
-
+
// retrieve reconstructed signature
ReconstructXMLDsigAfterAnalysisParameters recstrParams = new ReconstructXMLDsigAfterAnalysisParameters();
recstrParams.setAnalyzeResult(analyzeResult);
@@ -166,9 +166,9 @@ public class SignatureVerificationDemo {
*/
// setup verification
-
+
// verification without intermediate step of reconstruction
- /*
+ /*
VerifyAfterAnalysisParameters vaap = new VerifyAfterAnalysisParameters();
vaap.setAnalyzeResult(analyzeResult);
vaap.setReturnHashInputData(true);
@@ -178,7 +178,7 @@ public class SignatureVerificationDemo {
// use result.isVerificationDone() in order to find out if a signatures was successfully verified
vaap.setSuppressVerifyExceptions(true);
*/
-
+
// verification with intermediate step of reconstruction
VerifyAfterReconstructXMLDsigParameters varp = new VerifyAfterReconstructXMLDsigParameters();
varp.setReconstructXMLDsigResult(recstrResult);
@@ -192,15 +192,15 @@ public class SignatureVerificationDemo {
// invoke verification
System.out.println("Verifying...");
-
+
// without intermediate step of reconstruction
/*
VerifyResults verifyResults = pdfasAPI.verify(vaap);
*/
-
+
// with intermediate step of reconstruction
VerifyResults verifyResults = pdfasAPI.verify(varp);
-
+
// retrieve results
List verifyResultList = verifyResults.getResults();
System.out.println("Verification complete.\n");
@@ -213,14 +213,14 @@ public class SignatureVerificationDemo {
counter++;
VerifyResult result = (VerifyResult) it.next();
out.println("\n------------------------ SIGNATURE #" + counter + " ------------------------\n");
-
+
// check if signature verification of the current signature was successfully completed (independent from result)
if (!result.isVerificationDone()) {
PdfAsException ex = result.getVerificationException();
out.println(ErrorCodeHelper.formErrorMessage(ex));
continue;
}
-
+
Main.formatVerifyResult(result, out);
XMLDsigData xmlDSigData = result.getReconstructedXMLDsig();
if (xmlDSigData != null) {
@@ -233,12 +233,12 @@ public class SignatureVerificationDemo {
byte[] data = result.getSignedData().getAsByteArray();
out.println("\n Signed Data: " + data.length + " bytes (" + result.getSignatureType() + ")");
}
-
+
// check if there are timestamps
if (result.getTimeStampValue() != null) {
out.println("\n TimeStamp value available for this signature");
}
-
+
// check if non textual elements have been detected for this signature
if (result.hasNonTextualObjects()) {
out.println("\n WARNING: " + result.getNonTextualObjects().size() + " non textual object(s) detected for this signature");
@@ -248,13 +248,13 @@ public class SignatureVerificationDemo {
out.println(" -> " + info.toString());
}
out.println();
-
+
} else {
out.println("\n No non-textual objects detected for this signature.");
}
}
- out.flush();
-
+ out.flush();
+
} catch (PdfAsException e) {
if (ErrorCode.DOCUMENT_NOT_SIGNED == e.getErrorCode() && analyzeResult != null && analyzeResult.hasBeenCorrected()) {
System.err.println("\nThe document could not been processed, maybe due to modification by third party tools. An attempt to correct the document was successful but no verifiable signatures could be found. This/these signature(s) - if any - might got lost.");