From 535a04fa05f739ec16dd81666e3b0f82dfbd442d Mon Sep 17 00:00:00 2001 From: tknall Date: Wed, 9 Jan 2013 15:41:29 +0000 Subject: pdf-as-lib maven project files moved to pdf-as-lib git-svn-id: https://joinup.ec.europa.eu/svn/pdf-as/pdf-as/trunk@926 7b5415b0-85f9-ee4d-85bd-d5d0c3b42d1c --- .../at/gv/egiz/pdfas/impl/api/CheckHelper.java | 284 ++++++ .../at/gv/egiz/pdfas/impl/api/PdfAsObject.java | 865 ++++++++++++++++++ .../java/at/gv/egiz/pdfas/impl/api/PosHelper.java | 99 +++ .../pdfas/impl/api/analyze/AnalyzeResultImpl.java | 116 +++ .../pdfas/impl/api/commons/DataSinkAdapter.java | 103 +++ .../impl/api/commons/DataSourceApiAdapter.java | 105 +++ .../impl/api/commons/PdfDataSourceAdapter.java | 72 ++ .../api/commons/SignatureInformationAdapter.java | 133 +++ .../impl/api/commons/SignatureProfileImpl.java | 158 ++++ .../api/commons/TextBasedDataSourceApiAdapter.java | 92 ++ .../impl/api/commons/TextDataSourceAdapter.java | 72 ++ .../impl/api/internal/PdfAsInternalObject.java | 362 ++++++++ .../api/sign/ActualSignaturePositionAdapter.java | 93 ++ .../egiz/pdfas/impl/api/sign/SignResultImpl.java | 115 +++ .../api/sign/SignatureDetailInformationImpl.java | 190 ++++ .../pdfas/impl/api/verify/SignatureCheckImpl.java | 71 ++ .../pdfas/impl/api/verify/VerifyResultAdapter.java | 205 +++++ .../pdfas/impl/api/verify/VerifyResultsImpl.java | 60 ++ .../impl/input/ByteArrayPdfDataSourceImpl.java | 85 ++ .../impl/input/CompoundPdfDataSourceImpl.java | 85 ++ .../pdfas/impl/input/DelimitedInputStream.java | 125 +++ .../pdfas/impl/input/DelimitedPdfDataSource.java | 82 ++ .../at/gv/egiz/pdfas/impl/input/FileBased.java | 40 + .../impl/input/FileBasedPdfDataSourceImpl.java | 150 ++++ .../impl/input/FileBasedTextDataSourceImpl.java | 160 ++++ .../pdfas/impl/input/IncrementalUpdateParser.java | 92 ++ .../egiz/pdfas/impl/input/TextDataSourceImpl.java | 120 +++ .../impl/input/correction/ExternalCorrector.java | 283 ++++++ .../impl/input/correction/InternalCorrector.java | 82 ++ .../pdfas/impl/input/helper/DataSourceHelper.java | 148 ++++ .../egiz/pdfas/impl/output/ByteArrayDataSink.java | 106 +++ .../egiz/pdfas/impl/output/FileBasedDataSink.java | 145 ++++ .../impl/signator/IncrementalUpdateHelper.java | 74 ++ .../impl/signator/SignatorInformationImpl.java | 40 + .../signator/binary/BinarySignatorInformation.java | 104 +++ .../impl/signator/binary/BinarySignator_1_0_0.java | 598 +++++++++++++ .../impl/signator/binary/BinarySignator_1_1_0.java | 77 ++ .../detached/DetachedTextualSignator_1_0_0.java | 150 ++++ .../textual/TextualSignatorInformation.java | 96 ++ .../signator/textual/TextualSignator_1_0_0.java | 212 +++++ .../signator/textual/TextualSignator_1_1_0.java | 53 ++ .../signator/textual/TextualSignator_1_2_0.java | 53 ++ .../binary/BinaryVerificator_1_0_0.java | 453 ++++++++++ .../binary/BinaryVerificator_1_1_0.java | 44 + .../at/gv/egiz/pdfas/impl/vfilter/Partition.java | 29 + .../pdfas/impl/vfilter/VerificationFilterImpl.java | 964 +++++++++++++++++++++ .../vfilter/VerificationFilterParametersImpl.java | 98 +++ .../helper/VerificationFilterBinaryHelper.java | 190 ++++ .../vfilter/helper/VerificationFilterHelper.java | 162 ++++ .../helper/VerificationFilterTextHelper.java | 35 + .../impl/vfilter/partition/BinaryPartition.java | 39 + .../impl/vfilter/partition/TextPartition.java | 40 + .../pdfas/impl/xmldsig/XMLDsigReconstructor.java | 76 ++ 53 files changed, 8485 insertions(+) create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/CheckHelper.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/PdfAsObject.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/PosHelper.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/analyze/AnalyzeResultImpl.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/DataSinkAdapter.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/DataSourceApiAdapter.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/PdfDataSourceAdapter.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/SignatureInformationAdapter.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/SignatureProfileImpl.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/TextBasedDataSourceApiAdapter.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/TextDataSourceAdapter.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/internal/PdfAsInternalObject.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/sign/ActualSignaturePositionAdapter.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/sign/SignResultImpl.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/sign/SignatureDetailInformationImpl.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/verify/SignatureCheckImpl.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/verify/VerifyResultAdapter.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/verify/VerifyResultsImpl.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/ByteArrayPdfDataSourceImpl.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/CompoundPdfDataSourceImpl.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/DelimitedInputStream.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/DelimitedPdfDataSource.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/FileBased.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/FileBasedPdfDataSourceImpl.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/FileBasedTextDataSourceImpl.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/IncrementalUpdateParser.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/TextDataSourceImpl.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/correction/ExternalCorrector.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/correction/InternalCorrector.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/helper/DataSourceHelper.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/output/ByteArrayDataSink.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/output/FileBasedDataSink.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/IncrementalUpdateHelper.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/SignatorInformationImpl.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/binary/BinarySignatorInformation.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/binary/BinarySignator_1_0_0.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/binary/BinarySignator_1_1_0.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/detached/DetachedTextualSignator_1_0_0.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/textual/TextualSignatorInformation.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/textual/TextualSignator_1_0_0.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/textual/TextualSignator_1_1_0.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/textual/TextualSignator_1_2_0.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/verificator/binary/BinaryVerificator_1_0_0.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/verificator/binary/BinaryVerificator_1_1_0.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/Partition.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/VerificationFilterImpl.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/VerificationFilterParametersImpl.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/helper/VerificationFilterBinaryHelper.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/helper/VerificationFilterHelper.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/helper/VerificationFilterTextHelper.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/partition/BinaryPartition.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/partition/TextPartition.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/xmldsig/XMLDsigReconstructor.java (limited to 'pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl') diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/CheckHelper.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/CheckHelper.java new file mode 100644 index 0000000..ee2166e --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/CheckHelper.java @@ -0,0 +1,284 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.api; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.pdfas.api.analyze.AnalyzeParameters; +import at.gv.egiz.pdfas.api.commons.Constants; +import at.gv.egiz.pdfas.api.io.DataSource; +import at.gv.egiz.pdfas.api.sign.SignParameters; +import at.gv.egiz.pdfas.api.sign.SignatureDetailInformation; +import at.gv.egiz.pdfas.api.sign.pos.SignaturePositioning; +import at.gv.egiz.pdfas.api.verify.VerifyAfterAnalysisParameters; +import at.gv.egiz.pdfas.api.verify.VerifyParameters; +import at.gv.egiz.pdfas.framework.signator.SignatorInformation; +import at.gv.egiz.pdfas.impl.api.sign.SignatureDetailInformationImpl; +import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException; +import at.knowcenter.wag.egov.egiz.exceptions.SignatureTypesException; +import at.knowcenter.wag.egov.egiz.sig.SignatureTypes; + +/** + * Contains check methods frequently used by the {@link PdfAsObject} to check + * input parameters. + * + * @author wprinz + * + */ +public final class CheckHelper +{ + /** + * The log. + */ + private static Log log = LogFactory.getLog(CheckHelper.class); + + /** + * Hidden default constructor. + */ + private CheckHelper() + { + // empty block + } + + /** + * Checks the SignParameters for integrity. + * This is a shortcut to {@link CheckHelper#checkSignParameters(SignParameters, false)} + * + * @param sp + * The {@link SignParameters} + */ + public static void checkSignParameters(SignParameters sp){ + checkSignParameters(sp, false); + } + + /** + * Checks the SignParameters for integrity. + * + * @param sp + * The {@link SignParameters} + * @param allowAllDevices if true, no check for non local BKUs will be done + */ + public static void checkSignParameters(SignParameters sp, boolean allowAllDevices) + { + if (sp == null) + { + throw new IllegalArgumentException("The signParameters must not be null."); + } + + checkDocument(sp.getDocument()); + if (sp.getOutput() == null) + { + throw new IllegalArgumentException("The output DataSink must not be null."); + } + checkSignatureType(sp.getSignatureType()); + if (!allowAllDevices) + checkSignatureDevice(sp.getSignatureDevice()); + if (sp.getSignatureProfileId() != null) + { + checkProfileId(sp.getSignatureProfileId()); + } + if (sp.getSignaturePositioning() != null) + { + checkSignaturePositioning(sp.getSignaturePositioning()); + } + checkSignatureKeyIdentifier(sp.getSignatureKeyIdentifier(), sp.getSignatureDevice()); + checkTimestampHandler(sp); + } + + /** + * Checks the VerifyParameters for integrity. + * + * @param vp + * The {@link VerifyParameters} + */ + public static void checkVerifyParameters(VerifyParameters vp) + { + if (vp == null) + { + throw new IllegalArgumentException("The verifyParameters must not be null."); + } + + checkDocument(vp.getDocument()); + checkVerifyMode(vp.getVerifyMode()); + checkSignatureDevice(vp.getSignatureDevice()); + if (vp.getSignatureToVerify() < Constants.VERIFY_ALL) + { + throw new IllegalArgumentException("The signatureToVerify parameter is incorrect. " + vp.getSignatureToVerify()); + } + } + + /** + * Checks the AnalyzeParameters for integrity. + * + * @param ap + * The {@link AnalyzeParameters} + */ + public static void checkAnalyzeParameters(AnalyzeParameters ap) + { + if (ap == null) + { + throw new IllegalArgumentException("The analyzeParameters must not be null."); + } + + checkDocument(ap.getDocument()); + checkVerifyMode(ap.getVerifyMode()); + } + + /** + * Checks the VerifyAfterAnalysisParameters for integrity. + * + * @param vaap + * The {@link VerifyAfterAnalysisParameters} + */ + public static void checkVerifyAfterAnalysisParameters(VerifyAfterAnalysisParameters vaap) + { + if (vaap == null) + { + throw new IllegalArgumentException("The analyzeParameters must not be null."); + } + + if (vaap.getAnalyzeResult() == null) + { + throw new IllegalArgumentException("The analyzeResult must not be null."); + } + checkSignatureDevice(vaap.getSignatureDevice()); + } + + protected static void checkDocument(DataSource document) + { + if (document == null) + { + throw new IllegalArgumentException("The document DataSource must not be null."); + } + } + + protected static void checkSignatureType(String signatureType) + { + if (signatureType == null) + { + throw new IllegalArgumentException("The signatureType must not be null."); + } + if (!(signatureType.equals(Constants.SIGNATURE_TYPE_BINARY) || signatureType.equals(Constants.SIGNATURE_TYPE_TEXTUAL) || signatureType.equals(Constants.SIGNATURE_TYPE_DETACHEDTEXTUAL))) + { + throw new IllegalArgumentException("The signatureType must be one of the Constants.SIGNATURE_TYPE_* constants. " + signatureType); + } + } + + protected static void checkTimestampHandler(SignParameters params) { + if (params.getTimeStamperImpl() != null && !Constants.SIGNATURE_TYPE_BINARY.equals(params.getSignatureType())) { + throw new IllegalArgumentException("timestamping is only allowed for binary signatures "); + } + } + + protected static void checkProfileId(String profileId) + { + if (profileId == null) + { + throw new IllegalArgumentException("The profileId must not be null."); + } + try + { + if (!SignatureTypes.getInstance().getSignatureTypes().contains(profileId)) + { + throw new IllegalArgumentException("The profileId \"" + profileId + "\" must be defined (code or configuration file.)"); + } + } + catch (SignatureTypesException e) + { + String msg = "Error while checking the profileId parameter - cannot get list of valid profiles. " + profileId; + log.error(msg, e); + throw new IllegalArgumentException(msg); + } + } + + protected static void checkSignaturePositioning(SignaturePositioning signaturePositioning) + { + if (signaturePositioning == null) + { + throw new IllegalArgumentException("The signaturePosition must not be null."); + } + try + { + PosHelper.formTablePos(signaturePositioning); + } + catch (PDFDocumentException e) + { + String msg = "The signaturePosition is not valid. Please check the provided parameters."; + log.error(msg, e); + throw new IllegalArgumentException(msg); + } + } + + protected static void checkSignatureKeyIdentifier (String signatureKeyIdentifier, String signatureDevice) + { + if (signatureKeyIdentifier != null && !Constants.SIGNATURE_DEVICE_MOA.equals(signatureDevice)) + { + log.warn("A signatureKeyIdentifier (" + signatureKeyIdentifier + ") was provided although the signatureDevice (" + signatureDevice + ") is not moa. Currently only the moa signature device evaluates the signatureKeyIdentifier parameter."); + } + } + + protected static void checkVerifyMode(String verifyMode) + { + if (verifyMode == null) + { + throw new IllegalArgumentException("The verifyMode must not be null."); + } + if (!(verifyMode.equals(Constants.VERIFY_MODE_BINARY_ONLY) || verifyMode.equals(Constants.VERIFY_MODE_SEMI_CONSERVATIVE) || verifyMode.equals(Constants.VERIFY_MODE_FULL_CONSERVATIVE))) + { + throw new IllegalArgumentException("The verifyMode must be one of the Constants.VERIFY_MODE_* constants. " + verifyMode); + } + } + + protected static void checkSignatureDevice(String signatureDevice) + { + if (signatureDevice == null) + { + throw new IllegalArgumentException("The signatureDevice must not be null."); + } + if (!(signatureDevice.equals(Constants.SIGNATURE_DEVICE_BKU) || signatureDevice.equals(Constants.SIGNATURE_DEVICE_MOA))) + { + throw new IllegalArgumentException("The signatureDevice must be one of the Constants.SIGNATURE_DEVICE_* constants. " + signatureDevice); + } + } + + protected static void checkSignParametersForSignAfterPrepare(SignParameters signParameters, boolean allowAllDevices) { + checkSignParameters(signParameters, allowAllDevices); + checkProfileId(signParameters.getSignatureProfileId()); + } + + public static void checkSignatorInformation(SignatorInformation signatorInfo) { + if (signatorInfo.getSignSignatureObject() == null) + { + throw new IllegalArgumentException("The signatorInformation.getSignSignatureObject() must not be null."); + } + } + + public static void checkSignatureDetailInformation(SignatureDetailInformation signatureDetailInformation) { + if (!(signatureDetailInformation instanceof SignatureDetailInformationImpl)){ + throw new IllegalArgumentException("SignatureDetailInformation is of unsupported type. Must be " + SignatureDetailInformationImpl.class.getName()); + } + + } +} 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 new file mode 100644 index 0000000..eda94c0 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/PdfAsObject.java @@ -0,0 +1,865 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.api; + +import java.io.File; +import java.io.UnsupportedEncodingException; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Properties; +import java.util.Vector; + +import org.apache.commons.lang.math.NumberUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.pdfas.api.PdfAs; +import at.gv.egiz.pdfas.api.analyze.AnalyzeParameters; +import at.gv.egiz.pdfas.api.analyze.AnalyzeResult; +import at.gv.egiz.pdfas.api.commons.Constants; +import at.gv.egiz.pdfas.api.commons.DynamicSignatureLifetimeEnum; +import at.gv.egiz.pdfas.api.commons.DynamicSignatureProfile; +import at.gv.egiz.pdfas.api.commons.DynamicSignatureProfileImpl; +import at.gv.egiz.pdfas.api.commons.SignatureInformation; +import at.gv.egiz.pdfas.api.exceptions.PdfAsException; +import at.gv.egiz.pdfas.api.sign.SignParameters; +import at.gv.egiz.pdfas.api.sign.SignResult; +import at.gv.egiz.pdfas.api.sign.SignatureDetailInformation; +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.verify.VerifyResult; +import at.gv.egiz.pdfas.api.verify.VerifyResults; +import at.gv.egiz.pdfas.api.xmldsig.ExtendedSignatureInformation; +import at.gv.egiz.pdfas.api.xmldsig.ReconstructXMLDsigAfterAnalysisParameters; +import at.gv.egiz.pdfas.api.xmldsig.ReconstructXMLDsigParameters; +import at.gv.egiz.pdfas.api.xmldsig.ReconstructXMLDsigResult; +import at.gv.egiz.pdfas.api.xmldsig.XMLDsigData; +import at.gv.egiz.pdfas.commandline.CommandlineConnectorChooser; +import at.gv.egiz.pdfas.exceptions.ErrorCode; +import at.gv.egiz.pdfas.exceptions.framework.PlaceholderExtractionException; +import at.gv.egiz.pdfas.framework.ConnectorParameters; +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.signator.Signator; +import at.gv.egiz.pdfas.framework.signator.SignatorInformation; +import at.gv.egiz.pdfas.framework.vfilter.VerificationFilterParameters; +import at.gv.egiz.pdfas.impl.api.analyze.AnalyzeResultImpl; +import at.gv.egiz.pdfas.impl.api.commons.DataSinkAdapter; +import at.gv.egiz.pdfas.impl.api.commons.PdfDataSourceAdapter; +import at.gv.egiz.pdfas.impl.api.commons.SignatureInformationAdapter; +import at.gv.egiz.pdfas.impl.api.commons.SignatureProfileImpl; +import at.gv.egiz.pdfas.impl.api.commons.TextDataSourceAdapter; +import at.gv.egiz.pdfas.impl.api.sign.ActualSignaturePositionAdapter; +import at.gv.egiz.pdfas.impl.api.sign.SignResultImpl; +import at.gv.egiz.pdfas.impl.api.sign.SignatureDetailInformationImpl; +import at.gv.egiz.pdfas.impl.api.verify.VerifyResultAdapter; +import at.gv.egiz.pdfas.impl.api.verify.VerifyResultsImpl; +import at.gv.egiz.pdfas.impl.input.DelimitedPdfDataSource; +import at.gv.egiz.pdfas.impl.vfilter.VerificationFilterParametersImpl; +import at.gv.egiz.pdfas.impl.xmldsig.XMLDsigReconstructor; +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.knowcenter.wag.egov.egiz.PdfAS; +import at.knowcenter.wag.egov.egiz.PdfASID; +import at.knowcenter.wag.egov.egiz.cfg.OverridePropertyHolder; +import at.knowcenter.wag.egov.egiz.cfg.SettingsReader; +import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException; +import at.knowcenter.wag.egov.egiz.exceptions.OutOfMemoryException; +import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException; +import at.knowcenter.wag.egov.egiz.exceptions.PresentableException; +import at.knowcenter.wag.egov.egiz.exceptions.SettingsException; +import at.knowcenter.wag.egov.egiz.exceptions.SignatorFactoryException; +import at.knowcenter.wag.egov.egiz.exceptions.SignatureException; +import at.knowcenter.wag.egov.egiz.framework.SignatorFactory; +import at.knowcenter.wag.egov.egiz.pdf.AdobeSignatureHelper; +import at.knowcenter.wag.egov.egiz.pdf.BinarySignatureHolder; +import at.knowcenter.wag.egov.egiz.pdf.NoSignatureHolder; +import at.knowcenter.wag.egov.egiz.pdf.ObjectExtractor; +import at.knowcenter.wag.egov.egiz.pdf.SignatureHolder; +import at.knowcenter.wag.egov.egiz.pdf.TablePos; +import at.knowcenter.wag.egov.egiz.pdf.TextualSignatureHolder; +import at.knowcenter.wag.egov.egiz.sig.SignatureData; +import at.knowcenter.wag.egov.egiz.sig.SignatureDataImpl; +import at.knowcenter.wag.egov.egiz.sig.SignatureResponse; +import at.knowcenter.wag.egov.egiz.sig.SignatureTypeDefinition; +import at.knowcenter.wag.egov.egiz.sig.SignatureTypes; +import at.knowcenter.wag.egov.egiz.sig.connectors.Connector; +import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject; + +/** + * Implementation of the {@link PdfAs} interface. + * + * @author wprinz + */ +public class PdfAsObject implements PdfAs +{ +//23.11.2010 changed by exthex - added methods for reconstructXMLDsig + + /** + * The log. + */ + private static Log log = LogFactory.getLog(PdfAsObject.class); + + 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 + * Thrown, if the configuration cannot be processed. + */ + public PdfAsObject(File workDirectory) throws PdfAsException + { + 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 true: automatically registers IAIK JCE and ECC Provider; + * false: providers will NOT be automatically registered, providers + * needed have to be registered by the API user + * @throws PdfAsException + * Thrown, if the configuration cannot be processed. + */ + public PdfAsObject(File workDirectory, boolean registerProvider) throws PdfAsException + { + String path = workDirectory != null ? workDirectory.getPath() : null; + 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. + */ + public PdfAsObject() throws PdfAsException + { + this(null); + } + + /** + * @see at.gv.egiz.pdfas.api.PdfAs#reloadConfig() + */ + public void reloadConfig() throws PdfAsException + { + ConfigUtils.initializeLogger(); + SettingsReader.createInstance(); + SignatureTypes.createInstance(); + } + + /** + * @param registerProvider true: automatically registers IAIK JCE and ECC Provider; + * false: providers will NOT be automatically registered, providers + * needed have to be registered by the API user + * @see at.gv.egiz.pdfas.api.PdfAs#reloadConfig() + */ + private void reloadConfig(boolean registerProvider) throws PdfAsException + { + ConfigUtils.initializeLogger(); + SettingsReader.createInstance(registerProvider); + SignatureTypes.createInstance(); + } + + /** + * @see at.gv.egiz.pdfas.api.PdfAs#getProfileInformation() + */ + public List getProfileInformation() throws PdfAsException + { + log.debug("Collecting profile information."); + final String MOA_SIGN_KEY_IDENTIFIER_KEY = "moa.sign.KeyIdentifier"; + + SettingsReader settings = SettingsReader.getInstance(); + final String defaultMoaKeyIdentifiert = settings.getSetting(MOA_SIGN_KEY_IDENTIFIER_KEY, null); + + SignatureTypes types = SignatureTypes.getInstance(); + List profiles = types.getSignatureTypeDefinitions(); + + List profileInformation = new ArrayList(profiles.size()); + + String default_type = settings.getValueFromKey(SignatureTypes.DEFAULT_TYPE); + + Iterator it = profiles.iterator(); + while (it.hasNext()) + { + SignatureTypeDefinition profile = (SignatureTypeDefinition) it.next(); + + final String profileId = profile.getType(); + log.debug("Processing profile \"" + profileId + "\"."); + final String moaKeyIdentifier = settings.getSetting("sig_obj." + profileId + "." + MOA_SIGN_KEY_IDENTIFIER_KEY, defaultMoaKeyIdentifiert); + final String profileDescription = settings.getSetting("sig_obj." + profileId + "." + SignatureTypes.SIG_DESCR, null); + + boolean isDefault = (default_type != null && default_type.equals(profileId)); + // modified by tknall + SignatureProfileImpl signatureProfile = new SignatureProfileImpl(profileId, 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 + "\"."); + Vector keysVector = settings.getSettingKeys(parentPropertyKey); + if (keysVector != null) { + Iterator keyIt = keysVector.iterator(); + while (keyIt.hasNext()) { + String subKey = (String) keyIt.next(); + if (subKey != null && subKey.length() > 0) { + String fullKey = parentPropertyKey + "." + subKey; + String value = settings.getValueFromKey(fullKey); + int lastIndex = fullKey.lastIndexOf("."); + if (lastIndex != -1) { + String endsWith = fullKey.substring(lastIndex + 1); + if (value != null && value.length() > 0) { + if (NumberUtils.isDigits(endsWith)) { + signatureEntries.setProperty(fullKey, value); + } else { + log.debug("Ignoring table entry \"" + fullKey + "\" because it does not end with a digit. Therefore it is not relevant for the seach algorithm."); + } + } else { + log.warn("Problem detected with key \"" + fullKey + "\". The value is empty."); + } + } + } + } + } + + // search for table entries + parentPropertyKey = "sig_obj." + profileId + ".key"; + log.debug("Looking for subkeys of \"" + parentPropertyKey + "\"."); + keysVector = settings.getSettingKeys(parentPropertyKey); + if (keysVector != null) { + Iterator keyIt = keysVector.iterator(); + while (keyIt.hasNext()) { + String subKey = (String) keyIt.next(); + if (subKey != null && subKey.length() > 0) { + String fullKey = parentPropertyKey + "." + subKey; + String value = settings.getValueFromKey(fullKey); + if (value != null && value.length() > 0) { + signatureEntries.setProperty(fullKey, value); + } else { + log.warn("Problem detected with key \"" + fullKey + "\". The value is empty."); + } + } + } + } + + // 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 + { + CheckHelper.checkSignParameters(signParameters, false); + + try { + SignatureDetailInformation signatorInfo = prepareSign(signParameters); + + return sign(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 + { + CheckHelper.checkVerifyParameters(verifyParameters); + + AnalyzeParameters ap = new AnalyzeParameters(); + fillAnalyzeParametersWithVerifyParameters(ap, verifyParameters); + AnalyzeResult analyzeResult = analyze(ap); + + if (verifyParameters.getSignatureToVerify() != Constants.VERIFY_ALL) + { + if (verifyParameters.getSignatureToVerify() >= analyzeResult.getSignatures().size()) + { + throw new SignatureException(312, "The selected signature to be verified doesn't exist. " + verifyParameters.getSignatureToVerify()); + } + + Object stv = analyzeResult.getSignatures().get(verifyParameters.getSignatureToVerify()); + List selectedSignature = new ArrayList(1); + selectedSignature.add(stv); + analyzeResult = new AnalyzeResultImpl(selectedSignature); + } + + VerifyAfterAnalysisParameters vaap = new VerifyAfterAnalysisParameters(); + vaap.setAnalyzeResult(analyzeResult); + fillVerifyAfterAnalysisParametersWithVerifyParameters(vaap, verifyParameters); + VerifyResults res = verify(vaap); + + return res; + + } + + + /** + * Copies all adequate parameters from the {@link VerifyParameters} to the + * {@link AnalyzeParameters}. + * + * @param ap + * The {@link AnalyzeParameters}. + * @param vp + * The {@link VerifyParameters}. + */ + protected void fillAnalyzeParametersWithVerifyParameters(AnalyzeParameters ap, VerifyParameters vp) + { + ap.setDocument(vp.getDocument()); + ap.setVerifyMode(vp.getVerifyMode()); + ap.setReturnNonTextualObjects(vp.isReturnNonTextualObjects()); + } + + protected void fillAnalyzeParametersWithReconstructXMLDsigParameters(AnalyzeParameters ap, ReconstructXMLDsigParameters rxp) + { + ap.setDocument(rxp.getDocument()); + ap.setVerifyMode(rxp.getVerifyMode()); + ap.setReturnNonTextualObjects(rxp.isReturnNonTextualObjects()); + } + + /** + * Copies all adequate parameters from the {@link VerifyParameters} to the + * {@link VerifyAfterAnalysisParameters}. + * + * @param vaap + * The {@link VerifyAfterAnalysisParameters}. + * @param vp + * The {@link VerifyParameters}. + */ + protected void fillVerifyAfterAnalysisParametersWithVerifyParameters(VerifyAfterAnalysisParameters vaap, VerifyParameters vp) + { + vaap.setSignatureDevice(vp.getSignatureDevice()); + vaap.setVerificationTime(vp.getVerificationTime()); + vaap.setReturnHashInputData(vp.isReturnHashInputData()); + } + + + protected void fillReconstructXMLDsigAfterAnalysisParametersWithVerifyAfterAnalysisParameters( + ReconstructXMLDsigAfterAnalysisParameters reconstructParams, + VerifyAfterAnalysisParameters verifyAfterAnalysisParameters) { + reconstructParams.setAnalyzeResult(verifyAfterAnalysisParameters.getAnalyzeResult()); + 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 + { + CheckHelper.checkAnalyzeParameters(analyzeParameters); + + VerificationFilterParameters parametersConfig = SettingsHelper.readVerificationFilterParametersFromSettings(); + boolean binaryOnly = parametersConfig.extractBinarySignaturesOnly(); + if (analyzeParameters.getVerifyMode().equals(Constants.VERIFY_MODE_BINARY_ONLY)) + { + binaryOnly = true; + } + boolean assumeOnlySB = parametersConfig.assumeOnlySignatureUpdateBlocks(); + if (analyzeParameters.getVerifyMode().equals(Constants.VERIFY_MODE_SEMI_CONSERVATIVE)) + { + assumeOnlySB = true; + } + if (analyzeParameters.getVerifyMode().equals(Constants.VERIFY_MODE_FULL_CONSERVATIVE)) + { + 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")) + { + inputDataSource = new PdfDataSourceAdapter(analyzeParameters.getDocument()); + } + else + { + try + { + inputDataSource = new TextDataSourceAdapter(analyzeParameters.getDocument()); + } + catch (UnsupportedEncodingException e) + { + throw new PresentableException(ErrorCode.DOCUMENT_CANNOT_BE_READ, "The characterEncoding is not supported." + analyzeParameters.getDocument().getCharacterEncoding(), e); + } + } + 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(); + Iterator it = signature_holders.iterator(); + 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())); + } + + } + } + 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) { + if (sh == null) return null; + if (sh instanceof BinarySignatureHolder) { + BinarySignatureHolder bsh = (BinarySignatureHolder)sh; + return ObjectExtractor.extractNonTextInfo(bsh.getSignedPdf()); + } else if (sh instanceof TextualSignatureHolder) { + TextualSignatureHolder tsh = (TextualSignatureHolder)sh; + if (tsh.getUiBlockEndPos() == 0) { + log.warn("uiblockendpos not available. Extract objects from final pdf document"); + return ObjectExtractor.extractNonTextInfo(pdfDataSource); + } + DelimitedPdfDataSource dpds = new DelimitedPdfDataSource(pdfDataSource, tsh.getUiBlockEndPos()); + return ObjectExtractor.extractNonTextInfo(dpds); + } else { + return null; + } + } + +/** + * @see at.gv.egiz.pdfas.api.PdfAs#verify(at.gv.egiz.pdfas.api.verify.VerifyAfterAnalysisParameters) + */ + public VerifyResults verify(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); + + VerifyAfterReconstructXMLDsigParameters varxp = new VerifyAfterReconstructXMLDsigParameters(); + fillVerifyAfterReconstructXMLDsigParametersWithVerifyAfterAnalysisParameters(varxp, verifyAfterAnalysisParameters); + varxp.setReconstructXMLDsigResult(reconstructResult); + + return verify(varxp); + + } + + protected void fillVerifyAfterReconstructXMLDsigParametersWithVerifyAfterAnalysisParameters( + VerifyAfterReconstructXMLDsigParameters varxp, + VerifyAfterAnalysisParameters verifyAfterAnalysisParameters) { + varxp.setReturnHashInputData(verifyAfterAnalysisParameters.isReturnHashInputData()); + varxp.setSignatureDevice(verifyAfterAnalysisParameters.getSignatureDevice()); + varxp.setVerificationTime(verifyAfterAnalysisParameters.getVerificationTime()); + varxp.setVerifySignatureIndex(verifyAfterAnalysisParameters.getVerifySignatureIndex()); + } + + /** + * @see PdfAs#reconstructXMLDSIG(ReconstructXMLDsigParameters) + */ + public ReconstructXMLDsigResult reconstructXMLDSIG( + ReconstructXMLDsigParameters reconstructXMLDsigParameters) + throws PdfAsException { + + AnalyzeParameters analyzeParameters = new AnalyzeParameters(); + fillAnalyzeParametersWithReconstructXMLDsigParameters(analyzeParameters, reconstructXMLDsigParameters); + AnalyzeResult ar = analyze(analyzeParameters); + + ReconstructXMLDsigAfterAnalysisParameters rxaap = new ReconstructXMLDsigAfterAnalysisParameters(); + rxaap.setSignatureDevice(reconstructXMLDsigParameters.getSignatureDevice()); + rxaap.setAnalyzeResult(ar); + + return reconstructXMLDSIG(rxaap); + } + + /** + * @see PdfAs#reconstructXMLDSIG(ReconstructXMLDsigAfterAnalysisParameters) + */ + public ReconstructXMLDsigResult reconstructXMLDSIG( + ReconstructXMLDsigAfterAnalysisParameters reconstructXMLDsigParameters) + throws PdfAsException { + + AnalyzeResult ar = reconstructXMLDsigParameters.getAnalyzeResult(); + List extendedSignatureInfos = new Vector(); + for (int i = 0; i < ar.getSignatures().size(); i++) + { + SignatureInformation si = (SignatureInformation)ar.getSignatures().get(i); + XMLDsigData dsigData; + try { + dsigData = XMLDsigReconstructor.reconstruct(si, reconstructXMLDsigParameters.getSignatureDevice()); + extendedSignatureInfos.add(new ExtendedSignatureInformation(si, dsigData)); + } catch (ConnectorException e) { + // 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()); + } + + /** + * @see PdfAs#verify(VerifyAfterReconstructXMLDsigParameters) + */ + public VerifyResults verify( + 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(), + verifyAfterReconstructXMLDsigParameters.getVerificationTime(), verifyAfterReconstructXMLDsigParameters.getVerifySignatureIndex()); + + List vrs = new ArrayList(results.size()); + + int verifySignatureIndex = verifyAfterReconstructXMLDsigParameters.getVerifySignatureIndex(); + if (verifySignatureIndex < 0) + { + for (int i = 0; i < extSignatures.size(); i++) + { + 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) { + throw new OutOfMemoryException(ErrorCode.OUT_OF_MEMORY_ERROR, "Insufficient memory allocated to virtual machine. Start Java with parameters \"-Xms128m -Xmx786m -XX:MaxPermSize=256m\".", e); + } + } + + public DynamicSignatureProfile createDynamicSignatureProfile(String parentProfile, DynamicSignatureLifetimeEnum mode) { + return DynamicSignatureProfileImpl.createFromParent(null, parentProfile, mode); + } + + public DynamicSignatureProfile createEmptyDynamicSignatureProfile(DynamicSignatureLifetimeEnum mode) { + return DynamicSignatureProfileImpl.createEmptyProfile(null, mode); + } + + public DynamicSignatureProfile loadDynamicSignatureProfile(String name) { + return DynamicSignatureProfileImpl.loadProfile(name); + } + + public DynamicSignatureProfile createDynamicSignatureProfile(String myUniqueName, + String parentProfile, DynamicSignatureLifetimeEnum mode) { + return DynamicSignatureProfileImpl.createFromParent(myUniqueName, parentProfile, mode); + } + + public DynamicSignatureProfile createEmptyDynamicSignatureProfile(String myUniqueName, + DynamicSignatureLifetimeEnum mode) { + return DynamicSignatureProfileImpl.createEmptyProfile(myUniqueName, mode); + } + + /** + * @see PdfAs#prepareSign(SignParameters) + */ + public SignatureDetailInformation prepareSign(SignParameters signParameters) throws PdfAsException { + CheckHelper.checkSignParameters(signParameters, true); + + if (signParameters.getProfileOverrideProperties() != null) { + OverridePropertyHolder.setOverrideProps(signParameters.getProfileOverrideProperties()); + } + + signParameters.setDocument(PdfAS.applyStrictMode(signParameters.getDocument())); + + SettingsReader settings = SettingsReader.getInstance(); + String defaultProfile = settings.getValueFromKey(SignatureTypes.DEFAULT_TYPE); + + SignaturePlaceholderData spd = getSignaturePlaceholder(signParameters, defaultProfile); + if (spd != null){ + if (spd.getProfile() != null) + signParameters.setSignatureProfileId(spd.getProfile()); + if (spd.getType() != null) + signParameters.setSignatureType(spd.getType()); + if (spd.getKey() != null) + signParameters.setSignatureKeyIdentifier(spd.getKey()); + // check again, we might have destroyed something + CheckHelper.checkSignParameters(signParameters, true); + } + + if (signParameters.getSignatureProfileId() == null) + { + signParameters.setSignatureProfileId(defaultProfile); + } + + boolean fromPlaceholder = false; + boolean fromSignParameters = false; + boolean fromConfig = false; + TablePos pos = null; + if (spd != null && spd.getTablePos() != null){ + // position and width is determined by placeholder image + fromPlaceholder = true; + pos = spd.getTablePos(); + } else { + // position and width is determined by api sign parameters + pos = PosHelper.formTablePos(signParameters.getSignaturePositioning()); + if (pos != null) { + fromSignParameters = true; + } + } + + TablePos effectivePos = pos; + if (effectivePos == null) { + String pos_string = settings.getSetting(SignatureTypes.SIG_OBJ + signParameters.getSignatureProfileId() + ".pos", null); + if (pos_string != null) { + // position and width is determined by profile configuration + effectivePos = PdfAS.parsePositionFromPosString(pos_string); + fromConfig = true; + } + } + if (effectivePos != null) { + // check if width is lower than the smallest meaningful width + String thresholdString = AdobeSignatureHelper.getDefaultableConfigProperty(signParameters.getSignatureProfileId(), SIGNATURE_BLOCK_WIDTH_THRESHOLD_FOR_WARNING_KEY, String.valueOf(DEFAULT_SIGNATURE_BLOCK_WIDTH_THRESHOLD)); + float threshold = DEFAULT_SIGNATURE_BLOCK_WIDTH_THRESHOLD; + try { + threshold = Float.parseFloat(thresholdString); + } catch (NumberFormatException e) { + if (log.isDebugEnabled()) { + log.debug("Unable to parse threshold value (\"" + thresholdString + "\") of configuration value \"" + SIGNATURE_BLOCK_WIDTH_THRESHOLD_FOR_WARNING_KEY + "\". Using default value: " + DEFAULT_SIGNATURE_BLOCK_WIDTH_THRESHOLD); + } + } + if (!effectivePos.isWauto() && effectivePos.getWidth() < threshold) { + String msg = "The {0} for the signature block is very small ({1}). The signature block might not get placed correcty."; + String[] arguments = new String[]{ "given width", "" + effectivePos.getWidth()}; + // very small, warn user + if (fromPlaceholder) { + arguments[0] = "width given by the placeholder image"; + } else if (fromSignParameters) { + arguments[0] = "width defined by the sign parameters"; + } else if (fromConfig) { + arguments[0] = "width defined by the profile " + signParameters.getSignatureProfileId(); + } + log.warn(MessageFormat.format(msg, arguments)); + } + } + + Signator signator = createSignator(signParameters.getSignatureType()); + + SignatorInformation signatorInfo = signator.prepareSign( + 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 + String profile = signParameters.getSignatureProfileId(); + if (profile == null) + profile = defaultProfile; + String key = SignatureTypes.SIG_OBJ + profile + "." + ENABLE_PLACEHOLDER_SEARCH_KEY; + String configFileActivedString = settings.getValueFromKey(key); + + if (configFileActivedString == null){ + // 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(); + } else { + if (configFileActived != null) + enableSearch = configFileActived.booleanValue(); + else + enableSearch = false; + } + + if (enableSearch) + { + spd = SignaturePlaceholderExtractor.extract( + signParameters.getDocument().createInputStream(), + signParameters.getPlaceholderId(), + signParameters.getPlaceholderMatchMode()); + } + return spd; + } + + private Signator createSignator(String signatureType) throws SignatorFactoryException { + PdfASID signatorId = null; + if (signatureType.equals(Constants.SIGNATURE_TYPE_BINARY)) + { + signatorId = SignatorFactory.MOST_RECENT_BINARY_SIGNATOR_ID; + } + if (signatureType.equals(Constants.SIGNATURE_TYPE_TEXTUAL)) + { + signatorId = SignatorFactory.MOST_RECENT_TEXTUAL_SIGNATOR_ID; + } + if (signatureType.equals(Constants.SIGNATURE_TYPE_DETACHEDTEXTUAL)) + { + signatorId = SignatorFactory.MOST_RECENT_DETACHEDTEXT_SIGNATOR_ID; + } + + return at.gv.egiz.pdfas.framework.SignatorFactory.createSignator(signatorId); + + } + + public SignResult sign(SignParameters signParameters, SignatureDetailInformation signatorInfo) + throws PdfAsException { + CheckHelper.checkSignParametersForSignAfterPrepare(signParameters, false); + + if (signParameters.getProfileOverrideProperties() != null) { + OverridePropertyHolder.setOverrideProps(signParameters.getProfileOverrideProperties()); + } + + String connectorId = CommandlineConnectorChooser.chooseCommandlineConnectorForSign(signParameters.getSignatureDevice()); + + ConnectorParameters cp = new ConnectorParameters(); + cp.setProfileId(signParameters.getSignatureProfileId()); + cp.setSignatureKeyIdentifier(signParameters.getSignatureKeyIdentifier()); + Connector c = at.gv.egiz.pdfas.framework.ConnectorFactory.createConnector(connectorId, cp); + + 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) + 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(), + signatorInfo.getSignSignatureObject().getX509Certificate(), + 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/PosHelper.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/PosHelper.java new file mode 100644 index 0000000..cfb811e --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/PosHelper.java @@ -0,0 +1,99 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.api; + +import at.gv.egiz.pdfas.api.sign.pos.SignaturePositioning; +import at.gv.egiz.pdfas.api.sign.pos.axis.AbsoluteAxisAlgorithm; +import at.gv.egiz.pdfas.api.sign.pos.axis.AutoAxisAlgorithm; +import at.gv.egiz.pdfas.api.sign.pos.axis.AxisAlgorithm; +import at.gv.egiz.pdfas.api.sign.pos.page.AbsolutePageAlgorithm; +import at.gv.egiz.pdfas.api.sign.pos.page.AutoPageAlgorithm; +import at.gv.egiz.pdfas.api.sign.pos.page.NewPageAlgorithm; +import at.gv.egiz.pdfas.api.sign.pos.page.PageAlgorithm; +import at.knowcenter.wag.egov.egiz.PdfAS; +import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException; +import at.knowcenter.wag.egov.egiz.pdf.TablePos; + +/** + * @author wprinz + * + */ +public final class PosHelper +{ + /** + * Hidden default constructor. + */ + private PosHelper() + { + // empty block + } + + public static TablePos formTablePos(SignaturePositioning signaturePositioning) throws PDFDocumentException + { + if (signaturePositioning == null) + { + return null; + } + + String positioningString = formPositioningString(signaturePositioning); + TablePos pos = PdfAS.parsePositionFromPosString(positioningString); + + return pos; + } + + protected static String formPositioningString(SignaturePositioning sp) + { + String x_algo = formAxisAlgoString(sp.getXAlgorithm()); + String y_algo = formAxisAlgoString(sp.getYAlgorithm()); + String w_algo = formAxisAlgoString(sp.getWidthAlgorithm()); + String p_algo = formPageAlgoString(sp.getPageAlgorithm()); + String positioning = "x:" + x_algo + ";y:" + y_algo + ";w:" + w_algo + ";p:" + p_algo + ";f:" + sp.getFooterLine(); + return positioning; + } + + protected static String formAxisAlgoString(AxisAlgorithm algorithm) + { + if (algorithm instanceof AutoAxisAlgorithm) + { + return "auto"; + } + AbsoluteAxisAlgorithm aaa = (AbsoluteAxisAlgorithm) algorithm; + return Float.toString(aaa.getAbsoluteValue()); + } + + protected static String formPageAlgoString(PageAlgorithm algorithm) + { + if (algorithm instanceof AutoPageAlgorithm) + { + return "auto"; + } + if (algorithm instanceof NewPageAlgorithm) + { + return "new"; + } + AbsolutePageAlgorithm apa = (AbsolutePageAlgorithm) algorithm; + return Integer.toString(apa.getPage()); + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/analyze/AnalyzeResultImpl.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/analyze/AnalyzeResultImpl.java new file mode 100644 index 0000000..5e25ced --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/analyze/AnalyzeResultImpl.java @@ -0,0 +1,116 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.api.analyze; + +import java.util.List; + +import at.gv.egiz.pdfas.api.analyze.AnalyzeResult; +import at.gv.egiz.pdfas.api.exceptions.PdfAsException; + +/** + * Holds the result of an analyzation. + * + * @author wprinz + */ +public class AnalyzeResultImpl implements AnalyzeResult +{ + /** + * The found signatures. + */ + protected List signatures = null; + + /** + * The found non-signature update blocks. + */ + protected List noSignatures = null; + + protected boolean hasBeenCorrected = false; + + + /** + * Constructor. + * + * @param signatures + * The found signatures. + * @param noSignatures + * The found non-signature update blocks. + */ + public AnalyzeResultImpl(List signatures, List noSignatures, boolean hasBeenCorrected) + { + if (signatures == null) + { + throw new IllegalArgumentException("The list of found signatures must not be null."); + } + + this.signatures = signatures; + this.noSignatures = noSignatures; + this.hasBeenCorrected = hasBeenCorrected; + } + + + /** + * Constructor. + * + * @param signatures + * The found signatures. + */ + public AnalyzeResultImpl(List signatures) + { + if (signatures == null) + { + throw new IllegalArgumentException("The list of found signatures must not be null."); + } + + this.signatures = signatures; + } + + /** + * @see at.gv.egiz.pdfas.api.analyze.AnalyzeResult#getSignatures() + */ + public List getSignatures() throws PdfAsException + { + return this.signatures; + } + + public List getNoSignatures() { + + return this.noSignatures; + } + + /** + * Tells if the document has been corrected before verification. The correction maybe done + * after a first failing parse to repair a document (if enabled in the configuration + * correct_document_on_verify_if_necessary). The correction can only work for textual + * signatures. Binary signatures are lost anyhow. + * @return + */ + public boolean hasBeenCorrected() { + return hasBeenCorrected; + } + + public void setHasBeenCorrected(boolean hasBeenCorrected) { + this.hasBeenCorrected = hasBeenCorrected; + } + +} 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 new file mode 100644 index 0000000..2aee44f --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/DataSinkAdapter.java @@ -0,0 +1,103 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.api.commons; + +import java.io.IOException; +import java.io.OutputStream; + +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 +{ + /** + * The API DataSink to be adapted to a framework DataSink. + */ + protected at.gv.egiz.pdfas.api.io.DataSink apiDataSink = null; + + /** + * Constructor. + * + * @param apiDataSink + * The API DataSink to be adapted to a framework DataSink. + */ + public DataSinkAdapter(DataSink apiDataSink) + { + this.apiDataSink = apiDataSink; + } + + /** + * @see at.gv.egiz.pdfas.framework.output.DataSink#createOutputStream(java.lang.String) + */ + public OutputStream createOutputStream(String mimeType) + { + try + { + return this.apiDataSink.createOutputStream(mimeType); + } + catch (IOException e) + { + e.printStackTrace(); + throw new RuntimeException(e); + } + } + + /** + * @see at.gv.egiz.pdfas.framework.output.DataSink#createOutputStream(java.lang.String, + * java.lang.String) + */ + public OutputStream createOutputStream(String mimeType, String characterEncoding) + { + try + { + return this.apiDataSink.createOutputStream(mimeType, characterEncoding); + } + catch (IOException e) + { + e.printStackTrace(); + throw new RuntimeException(e); + } + } + + /** + * @see at.gv.egiz.pdfas.framework.output.DataSink#getCharacterEncoding() + */ + public String getCharacterEncoding() + { + return this.apiDataSink.getCharacterEncoding(); + } + + /** + * @see at.gv.egiz.pdfas.framework.output.DataSink#getMimeType() + */ + public String getMimeType() + { + return this.apiDataSink.getMimeType(); + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/DataSourceApiAdapter.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/DataSourceApiAdapter.java new file mode 100644 index 0000000..8db3fcf --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/DataSourceApiAdapter.java @@ -0,0 +1,105 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.api.commons; + +import java.io.InputStream; + +import at.gv.egiz.pdfas.framework.input.PdfDataSource; +import at.gv.egiz.pdfas.framework.input.TextDataSource; + +/** + * Adapter that converts a framework DataSource to an API PdfDataSource. + * + * @author wprinz + */ +public class DataSourceApiAdapter implements at.gv.egiz.pdfas.api.io.DataSource +{ + /** + * The framework DataSource to be adapted to an API DataSource. + */ + protected at.gv.egiz.pdfas.framework.input.DataSource frameworkDataSource = null; + + /** + * Constructor. + * + * @param frameworkDataSource + * The framework DataSource to be adapted to an API DataSource. + */ + public DataSourceApiAdapter(at.gv.egiz.pdfas.framework.input.DataSource frameworkDataSource) + { + this.frameworkDataSource = frameworkDataSource; + } + + /** + * @see at.gv.egiz.pdfas.api.io.DataSource#createInputStream() + */ + public InputStream createInputStream() + { + return this.frameworkDataSource.createInputStream(); + } + + /** + * @see at.gv.egiz.pdfas.api.io.DataSource#getAsByteArray() + */ + public byte[] getAsByteArray() + { + return this.frameworkDataSource.getAsByteArray(); + } + + /** + * @see at.gv.egiz.pdfas.api.io.DataSource#getLength() + */ + public int getLength() + { + return this.frameworkDataSource.getLength(); + } + + public String getCharacterEncoding() + { + if (this.frameworkDataSource instanceof PdfDataSource) + { + return null; + } + if (this.frameworkDataSource instanceof TextDataSource) + { + return "UTF-8"; + } + return null; + } + + public String getMimeType() + { + if (this.frameworkDataSource instanceof PdfDataSource) + { + return "application/pdf"; + } + if (this.frameworkDataSource instanceof TextDataSource) + { + return "text/plain"; + } + + return null; + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/PdfDataSourceAdapter.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/PdfDataSourceAdapter.java new file mode 100644 index 0000000..6336071 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/PdfDataSourceAdapter.java @@ -0,0 +1,72 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.api.commons; + +import java.io.InputStream; + +/** + * Adapter that converts an API DataSource to a framework PdfDataSource. + * + * @author wprinz + */ +public class PdfDataSourceAdapter implements at.gv.egiz.pdfas.framework.input.PdfDataSource +{ + /** + * The API DataSource to be adapted to a framework PdfDataSource. + */ + protected at.gv.egiz.pdfas.api.io.DataSource apiDataSource = null; + + /** + * Constructor. + * @param apiDataSource The API DataSource to be adapted to a framework PdfDataSource. + */ + public PdfDataSourceAdapter(at.gv.egiz.pdfas.api.io.DataSource apiDataSource) + { + this.apiDataSource = apiDataSource; + } + + /** + * @see at.gv.egiz.pdfas.framework.input.DataSource#createInputStream() + */ + public InputStream createInputStream() + { + return this.apiDataSource.createInputStream(); + } + + /** + * @see at.gv.egiz.pdfas.framework.input.DataSource#getAsByteArray() + */ + public byte[] getAsByteArray() + { + return this.apiDataSource.getAsByteArray(); + } + + /** + * @see at.gv.egiz.pdfas.framework.input.DataSource#getLength() + */ + public int getLength() + { + return this.apiDataSource.getLength(); + } +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/SignatureInformationAdapter.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/SignatureInformationAdapter.java new file mode 100644 index 0000000..34c706b --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/SignatureInformationAdapter.java @@ -0,0 +1,133 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.api.commons; + +import java.security.cert.X509Certificate; +import java.util.Date; +import java.util.List; + +import at.gv.egiz.pdfas.api.commons.Constants; +import at.gv.egiz.pdfas.api.commons.SignatureInformation; +import at.gv.egiz.pdfas.api.io.DataSource; +import at.knowcenter.wag.egov.egiz.pdf.BinarySignatureHolder; +import at.knowcenter.wag.egov.egiz.pdf.EGIZDate; +import at.knowcenter.wag.egov.egiz.pdf.SignatureHolder; + +/** + * Adapter that converts a framework SignatureHolder to an API + * SignatureInformation. + * + * @author wprinz + */ +public class SignatureInformationAdapter implements SignatureInformation +{ + /** + * The framework SignatureHolder to be adapted to an API SignatureInformation. + */ + protected SignatureHolder signatureHolder = null; + + protected String timeStamp = null; + + protected List nonTextualObjects = null; + + /** + * Constructor. + * + * @param signatureHolder + * The framework SignatureHolder to be adapted to an API + * SignatureInformation. + */ + public SignatureInformationAdapter(SignatureHolder signatureHolder) + { + this.signatureHolder = signatureHolder; + if (signatureHolder instanceof BinarySignatureHolder) { + this.timeStamp = ((BinarySignatureHolder)signatureHolder).getSignatureObject().getTimeStamp(); + } + } + + /** + * @see at.gv.egiz.pdfas.api.commons.SignatureInformation#getSignedData() + */ + public DataSource getSignedData() + { + return new DataSourceApiAdapter(this.signatureHolder.getDataSource()); + } + + /** + * @see at.gv.egiz.pdfas.api.commons.SignatureInformation#getInternalSignatureInformation() + */ + public Object getInternalSignatureInformation() + { + return this.signatureHolder; + } + + /** + * @see at.gv.egiz.pdfas.api.commons.SignatureInformation#getSignatureType() + */ + public String getSignatureType() + { + if (this.signatureHolder.getSignatureObject().isBinary()) + { + return Constants.SIGNATURE_TYPE_BINARY; + } + return Constants.SIGNATURE_TYPE_TEXTUAL; + } + + + /** + * @see at.gv.egiz.pdfas.api.commons.SignatureInformation#getSignerCertificate() + */ + public X509Certificate getSignerCertificate() + { + return this.signatureHolder.getSignatureObject().getX509Cert().getX509Certificate(); + } + + /** + * @see at.gv.egiz.pdfas.api.commons.SignatureInformation#getSigningTime() + */ + public Date getSigningTime() + { + String date_value = this.signatureHolder.getSignatureObject().getSignationDate(); + Date date = EGIZDate.parseDateFromString(date_value); + return date; + } + + public String getTimeStampValue() { + return this.timeStamp; + } + + public List getNonTextualObjects() { + return this.nonTextualObjects; + } + + public boolean hasNonTextualObjects() { + return this.nonTextualObjects != null && this.nonTextualObjects.size() > 0; + } + + public void setNonTextualObjects(List nonTextualObjects) { + this.nonTextualObjects = nonTextualObjects; + } + + +} 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 new file mode 100644 index 0000000..35d8c17 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/SignatureProfileImpl.java @@ -0,0 +1,158 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.api.commons; + +import java.util.Properties; + +import org.apache.commons.lang.builder.ToStringBuilder; + +import at.gv.egiz.pdfas.api.commons.SignatureProfile; + +/** + * Holds the data of a signature profile. + * + * @author wprinz + */ +public class SignatureProfileImpl implements SignatureProfile { + + /** + * The profile identifier. + */ + protected String profileId = null; + + /** + * The MOA key identifiert of this profile. + */ + protected String moaKeyIdentifier = null; + + /** + * Properties containing the layout settings relevant to the search algorithm + * for signature blocks. + */ + protected Properties signatureBlockEntries; + + /** + * Short description of the profile. + */ + protected String profileDescription; + + /** + * true if this is the default profile, false otherwise. + */ + protected boolean defaultProfile = false; + + /** + * Constructor. + * + * @param profileId + * The profile identifier. + * @param moaKeyIdentifier + * The MOA key identifier of this profile. + */ + public SignatureProfileImpl(String profileId, String moaKeyIdentifier) { + this.profileId = profileId; + this.moaKeyIdentifier = moaKeyIdentifier; + this.signatureBlockEntries = new Properties(); + } + + /** + * Constructor. + * + * @param profileId + * The profile identifier. + * @param profileDescription + * The profile description. + * @param moaKeyIdentifier + * The MOA key identifier of this profile. + * @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; + } + + /** + * @see at.gv.egiz.pdfas.api.commons.SignatureProfile#getProfileId() + */ + public String getProfileId() { + return this.profileId; + } + + /** + * @see at.gv.egiz.pdfas.api.commons.SignatureProfile#getMOAKeyIdentifier() + */ + public String getMOAKeyIdentifier() { + return this.moaKeyIdentifier; + } + + /** + * @see at.gv.egiz.pdfas.api.commons.SignatureProfile#getSignatureBlockEntries() + */ + public Properties getSignatureBlockEntries() { + return this.signatureBlockEntries; + } + + /** + * Sets the entries relevant to the search algorithm for signature blocks.
+ * e.g. properties starting with sig_obj.PROFILE.key. and + * properties of the form sig_obj.PROFILE.table.TABLENAME.NUMBER + * where PROFILE is the name of the current profile, + * TABLENAME is the name of a table and NUMBER + * is the number of the specific row within the table TABLENAME. + * + * @param signatureBlockEntries + * The entries relevant to the signature block search algorithm as + * Java properties. + */ + public void setSignatureBlockEntries(Properties signatureBlockEntries) { + this.signatureBlockEntries = signatureBlockEntries; + } + + /** + * Returns the profile description. + * @return The profile description. + */ + public String getProfileDescription() { + return this.profileDescription; + } + + public String toString() { + return new ToStringBuilder(this) + .append("profileId", this.profileId) + .append("profileDescription", this.profileDescription) + .append("moaKeyIdentifier", this.moaKeyIdentifier) + .toString(); + } + + /** + * + */ + public boolean isDefault() { + return this.defaultProfile; + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/TextBasedDataSourceApiAdapter.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/TextBasedDataSourceApiAdapter.java new file mode 100644 index 0000000..5685490 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/TextBasedDataSourceApiAdapter.java @@ -0,0 +1,92 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.api.commons; + +import java.io.InputStream; + +import at.gv.egiz.pdfas.api.io.TextBased; +import at.gv.egiz.pdfas.framework.input.TextDataSource; + +/** + * Adapter that converts a framework DataSource to an API PdfDataSource. + * + * @author wprinz + */ +public class TextBasedDataSourceApiAdapter implements at.gv.egiz.pdfas.api.io.DataSource, TextBased +{ + /** + * The framework DataSource to be adapted to an API DataSource. + */ + protected TextDataSource frameworkDataSource = null; + + /** + * Constructor. + * + * @param frameworkDataSource + * The framework DataSource to be adapted to an API DataSource. + */ + public TextBasedDataSourceApiAdapter(TextDataSource frameworkDataSource) + { + this.frameworkDataSource = frameworkDataSource; + } + + /** + * @see at.gv.egiz.pdfas.api.io.DataSource#createInputStream() + */ + public InputStream createInputStream() + { + return this.frameworkDataSource.createInputStream(); + } + + /** + * @see at.gv.egiz.pdfas.api.io.DataSource#getAsByteArray() + */ + public byte[] getAsByteArray() + { + return this.frameworkDataSource.getAsByteArray(); + } + + /** + * @see at.gv.egiz.pdfas.api.io.DataSource#getLength() + */ + public int getLength() + { + return this.frameworkDataSource.getLength(); + } + + public String getCharacterEncoding() + { + return "UTF-8"; + } + + public String getMimeType() + { + return "text/plain"; + } + + public String getText() { + return this.frameworkDataSource.getText(); + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/TextDataSourceAdapter.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/TextDataSourceAdapter.java new file mode 100644 index 0000000..39f88e2 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/TextDataSourceAdapter.java @@ -0,0 +1,72 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.api.commons; + +import java.io.UnsupportedEncodingException; + +import at.gv.egiz.pdfas.api.io.TextBased; +import at.gv.egiz.pdfas.impl.input.TextDataSourceImpl; + +/** + * Adapter that converts an API DataSource to a framework TextDataSource. + * + * @author wprinz + */ +public class TextDataSourceAdapter extends TextDataSourceImpl +{ + /** + * The API DataSource to be adapted to a framework TextDataSource. + */ + protected at.gv.egiz.pdfas.api.io.DataSource apiDataSource = null; + + /** + * Constructor. + * + * @param apiDataSource + * The API DataSource to be adapted to a framework TextDataSource. + * @throws UnsupportedEncodingException + */ + public TextDataSourceAdapter(at.gv.egiz.pdfas.api.io.DataSource apiDataSource) throws UnsupportedEncodingException + { + super(null); + this.apiDataSource = apiDataSource; + + if (this.apiDataSource instanceof TextBased) + { + TextBased tb = (TextBased) this.apiDataSource; + this.text = tb.getText(); + } + else + { + byte[] data = this.apiDataSource.getAsByteArray(); + String characterEncoding = this.apiDataSource.getCharacterEncoding(); + if (characterEncoding == null) + { + throw new UnsupportedEncodingException("The characterEncoding must not be null. Specify a correct encoding."); + } + this.text = new String(data, characterEncoding); + } + assert this.text != null; + } +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/internal/PdfAsInternalObject.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/internal/PdfAsInternalObject.java new file mode 100644 index 0000000..b817ea9 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/internal/PdfAsInternalObject.java @@ -0,0 +1,362 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.api.internal; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Vector; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.pdfas.api.PdfAs; +import at.gv.egiz.pdfas.api.analyze.AnalyzeResult; +import at.gv.egiz.pdfas.api.commons.Constants; +import at.gv.egiz.pdfas.api.commons.SignatureInformation; +import at.gv.egiz.pdfas.api.exceptions.PdfAsException; +import at.gv.egiz.pdfas.api.internal.LocalBKUParams; +import at.gv.egiz.pdfas.api.internal.PdfAsInternal; +import at.gv.egiz.pdfas.api.internal.SignatureEntry; +import at.gv.egiz.pdfas.api.sign.SignParameters; +import at.gv.egiz.pdfas.api.sign.SignResult; +import at.gv.egiz.pdfas.api.sign.SignatureDetailInformation; +import at.gv.egiz.pdfas.api.verify.VerifyResult; +import at.gv.egiz.pdfas.exceptions.ErrorCode; +import at.gv.egiz.pdfas.framework.ConnectorParameters; +import at.gv.egiz.pdfas.framework.input.TextDataSource; +import at.gv.egiz.pdfas.impl.api.CheckHelper; +import at.gv.egiz.pdfas.impl.api.analyze.AnalyzeResultImpl; +import at.gv.egiz.pdfas.impl.api.commons.PdfDataSourceAdapter; +import at.gv.egiz.pdfas.impl.api.commons.SignatureInformationAdapter; +import at.gv.egiz.pdfas.impl.api.sign.SignatureDetailInformationImpl; +import at.gv.egiz.pdfas.impl.api.verify.VerifyResultAdapter; +import at.gv.egiz.pdfas.impl.input.TextDataSourceImpl; +import at.knowcenter.wag.egov.egiz.PdfAS; +import at.knowcenter.wag.egov.egiz.PdfASID; +import at.knowcenter.wag.egov.egiz.cfg.SettingsReader; +import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException; +import at.knowcenter.wag.egov.egiz.exceptions.ConnectorFactoryException; +import at.knowcenter.wag.egov.egiz.exceptions.NormalizeException; +import at.knowcenter.wag.egov.egiz.exceptions.SettingsException; +import at.knowcenter.wag.egov.egiz.exceptions.SignatureException; +import at.knowcenter.wag.egov.egiz.exceptions.SignatureTypesException; +import at.knowcenter.wag.egov.egiz.framework.SignatorFactory; +import at.knowcenter.wag.egov.egiz.pdf.SignatureHolder; +import at.knowcenter.wag.egov.egiz.pdf.TextualSignatureHolder; +import at.knowcenter.wag.egov.egiz.sig.ConnectorFactory; +import at.knowcenter.wag.egov.egiz.sig.ConnectorInformation; +import at.knowcenter.wag.egov.egiz.sig.SignatureData; +import at.knowcenter.wag.egov.egiz.sig.SignatureDataImpl; +import at.knowcenter.wag.egov.egiz.sig.SignatureObject; +import at.knowcenter.wag.egov.egiz.sig.SignatureResponse; +import at.knowcenter.wag.egov.egiz.sig.SignatureTypes; +import at.knowcenter.wag.egov.egiz.sig.connectors.LocalConnector; +import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUHelper; +import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUPostConnection; +import at.knowcenter.wag.egov.egiz.sig.connectors.bku.EnvelopedBase64BKUConnector; +import at.knowcenter.wag.egov.egiz.sig.connectors.bku.LocRefDetachedBKUConnector; +import at.knowcenter.wag.egov.egiz.sig.connectors.bku.MultipartDetachedBKUConnector; +import at.knowcenter.wag.egov.egiz.sig.connectors.bku.OldEnvelopingBase64BKUConnector; +import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject; +import at.knowcenter.wag.egov.egiz.sig.connectors.mocca.LocRefDetachedMOCCAConnector; +import at.knowcenter.wag.egov.egiz.sig.sigid.HotfixIdFormatter; +import at.knowcenter.wag.egov.egiz.sig.signaturelayout.SignatureLayoutHandlerFactory; +import at.knowcenter.wag.egov.egiz.sig.signatureobject.SignatureObjectHelper; + +/** + * @see PdfAsInternal + * + * @author exthex + * + */ +public class PdfAsInternalObject implements PdfAsInternal { + /** + * The log. + */ + private static Log log = LogFactory.getLog(CheckHelper.class); + + /** + * @see PdfAsInternal#verifyBKUSupport(LocalBKUParams) + */ + public void verifyBKUSupport(LocalBKUParams bkuParams) throws ConnectorException, SettingsException { + String bkuIdentifier = BKUHelper.getBKUIdentifier(bkuParams); + SignatureLayoutHandlerFactory.verifyBKUSupport(bkuIdentifier); + } + + /** + * @see PdfAsInternal#finishLocalSign(PdfAs, SignParameters, SignatureDetailInformation, LocalBKUParams, String) + */ + public SignResult finishLocalSign(PdfAs pdfAs, SignParameters signParameters, SignatureDetailInformation sdi, LocalBKUParams bkuParams, boolean multipart, String xmlResponse) throws PdfAsException { + LocalConnector c = chooseLocalConnectorForSign(signParameters.getSignatureDevice(), signParameters.getSignatureProfileId(), "not needed", multipart); + SignSignatureObject sso = c.analyzeSignResponse(buildResponseProperties(bkuParams, xmlResponse)); + ((SignatureDetailInformationImpl)sdi).setSignSignatureObject(sso); + + return pdfAs.finishSign(signParameters, sdi); + } + + private Properties buildResponseProperties(LocalBKUParams bkuParams, String xmlResponse) { + Properties ret = new Properties(); + if (bkuParams.getServer() != null) + ret.setProperty(BKUPostConnection.BKU_SERVER_HEADER_KEY, bkuParams.getServer()); + if (bkuParams.getUserAgent() != null) + ret.setProperty(BKUPostConnection.BKU_USER_AGENT_HEADER_KEY, bkuParams.getUserAgent()); + if (bkuParams.getSignatureLayout() != null) + ret.setProperty(BKUPostConnection.BKU_SIGNATURE_LAYOUT_HEADER_KEY, bkuParams.getSignatureLayout()); + ret.setProperty(BKUPostConnection.RESPONSE_STRING_KEY, xmlResponse); + return ret; + } + + private LocalConnector chooseLocalConnectorForSign(String device, String profile, String loc_ref_url, boolean multipart) throws ConnectorException{ + ConnectorParameters cp = new ConnectorParameters(); + cp.setProfileId(profile); + + if (Constants.SIGNATURE_DEVICE_MOC.equals(device)) { + if (!multipart) { + return new LocRefDetachedMOCCAConnector(cp, loc_ref_url); + } + } else if (Constants.SIGNATURE_DEVICE_BKU.equals(device)){ + if (multipart) { + return new MultipartDetachedBKUConnector(cp); + } else { + return new LocRefDetachedBKUConnector(cp, loc_ref_url); + } + } else if (Constants.SIGNATURE_DEVICE_MOBILE.equals(device)){ + if (multipart) { + return new MultipartDetachedBKUConnector(cp); + } else { + return new LocRefDetachedBKUConnector(cp, loc_ref_url); + } + } else if (Constants.SIGNATURE_DEVICE_MOBILETEST.equals(device)){ + if (multipart) { + return new MultipartDetachedBKUConnector(cp); + } else { + return new LocRefDetachedBKUConnector(cp, loc_ref_url); + } + } + + + log.error("Currently only the BKU connector is fully implemented."); + return new LocRefDetachedBKUConnector(cp, loc_ref_url); + } + + private LocalConnector chooseLocalConnectorForVerify(String connector, + PdfASID sig_kz, String sig_id, String profile, String loc_ref_url) throws ConnectorException + { + log.debug("Choosing LocalConnector for verification..."); + + log.debug("connector type = " + connector); + log.debug("sig_kz = " + sig_kz); + log.debug("sig_id = " + sig_id); + + if (!connector.equals("bku")) + { + log.error("Currently only the BKU connector is fully implemented."); + } + + if (sig_kz == null) + { + log.debug("sig_kz is null -> must be old signature -> choosing old Base64 connector."); + + return new OldEnvelopingBase64BKUConnector(profile); + } + + log.debug("sig_kz is not null -> must be one of the newer ... base64, base64 hotfix, or detached"); + + if (sig_kz.getVersion().equals(SignatorFactory.VERSION_1_0_0)) + { + log.debug("sig_kz version is 1.0.0 -> choosing base64 (old or hotfix)"); + + if (sig_id == null) + { + log.debug("sig_id is null, which means that it is a MOA signature -> choose a hotfix base64 connector (thus it is moa - it doesn't matter)."); + + return new EnvelopedBase64BKUConnector(profile); + } + + String[] sig_id_parts = sig_id.split("@"); + if (sig_id_parts.length == 2) + { + log.debug("sig_id has 2 @-separated parts -> choosing old base64 connector"); + + return new OldEnvelopingBase64BKUConnector(profile); + } + if (sig_id_parts[0].equals(HotfixIdFormatter.SIG_ID_PREFIX)) + { + log.debug("sig_id prefix is hotfix -> choosing hotfix base64 connector"); + + return new EnvelopedBase64BKUConnector(profile); + } + + throw new ConnectorException(300, "The SIG_KZ version is 1.0.0, but SIG_ID is neither MOA nor Old base64 nor Hotfix base64 ???'"); + } + if (sig_kz.getVersion().equals(SignatorFactory.VERSION_1_1_0) || sig_kz.getVersion().equals(SignatorFactory.VERSION_1_2_0)) + { + log.debug("sig_kz version is 1.1.0/1.2.0 -> choosing detached (loc ref) connector."); + + ConnectorParameters cp = new ConnectorParameters(); + cp.setProfileId(profile); + return new LocRefDetachedBKUConnector(cp, loc_ref_url); + } + + throw new ConnectorException(ErrorCode.UNSUPPORTED_SIGNATURE, "The SIG_KZ version '" + sig_kz.getVersion() + "' is unknown."); + } + + /** + * @see PdfAsInternal#getLocalServiceAddress(String, String) + */ + public String getLocalServiceAddress(String profile, String device) throws SettingsException { + SettingsReader settings = SettingsReader.getInstance(); + + String key = device + ".sign.url"; + String value = settings.getValueFromKey("sig_obj." + profile + "." + key); //$NON-NLS-1$//$NON-NLS-2$ + if (value == null) + { + value = settings.getValueFromKey(key); + } + return value; + } + + /** + * @see PdfAsInternal#prepareLocalSignRequest(SignParameters, String, SignatureDetailInformation) + */ + public String prepareLocalSignRequest(SignParameters signParameters, boolean multipart, String loc_ref_url, + SignatureDetailInformation sdi) throws ConnectorException { + LocalConnector c = chooseLocalConnectorForSign(signParameters.getSignatureDevice(), signParameters.getSignatureProfileId(), loc_ref_url, multipart); + SignatureData sd = new SignatureDataImpl(new PdfDataSourceAdapter(sdi.getSignatureData()), sdi.getSignatureData().getMimeType(), sdi.getSignatureData().getCharacterEncoding()); + String sign_request = c.prepareSignRequest(sd); + return sign_request; + } + + /** + * @see PdfAsInternal#analyzeFromRawText(String, Map) + */ + public AnalyzeResult analyzeFromRawText(String rawText, Map sigValues) throws SignatureException, SettingsException, SignatureTypesException, NormalizeException { + String normalizedText = PdfAS.normalizeText(rawText); + + SignatureObject signature_object = new SignatureObject(); + + String default_type = SettingsReader.getInstance().getValueFromKey(SignatureTypes.DEFAULT_TYPE); + signature_object.setSigType(default_type); + signature_object.initByType(); + + Iterator sigKeys = sigValues.keySet().iterator(); + while (sigKeys.hasNext()){ + String key = (String)sigKeys.next(); + signature_object.setSigValue(key, (String)sigValues.get(key)); + } + + TextDataSource tds = new TextDataSourceImpl(normalizedText); + SignatureHolder new_holder = new TextualSignatureHolder(tds, signature_object); + + SignatureInformation si = new SignatureInformationAdapter(new_holder); + List signatures = new Vector(); + signatures.add(si); + AnalyzeResult ret = new AnalyzeResultImpl(signatures); + return ret; + } + + /** + * @see PdfAsInternal#prepareLocalVerifyRequest(SignatureInformation, String, String, String) + */ + public String prepareLocalVerifyRequest(SignatureInformation sigInfo, String connector, String profile, String loc_ref_url) throws SignatureException, ConnectorException { + + SignatureHolder holder = (SignatureHolder)sigInfo.getInternalSignatureInformation(); + SignatureObject s = holder.getSignatureObject(); + + SignatureData sd = PdfAS.convertSignatureHolderToSignatureData(holder); + + SignSignatureObject so = SignatureObjectHelper.convertSignatureObjectToSignSignatureObject(s); + + LocalConnector local_conn = chooseLocalConnectorForVerify(connector, s.getKZ(), so.id, profile, loc_ref_url); + + String request_string = local_conn.prepareVerifyRequest(sd, so, null); + return request_string; + } + + /** + * @see PdfAsInternal#finishLocalVerify(SignatureInformation, String, String, String, String) + */ + public VerifyResult finishLocalVerify(SignatureInformation sigInfo, String connector, String profile, String loc_ref_url, String xmlResponse) throws SignatureException, ConnectorException { + SignatureHolder holder = (SignatureHolder)sigInfo.getInternalSignatureInformation(); + SignatureObject s = holder.getSignatureObject(); + + SignSignatureObject so = SignatureObjectHelper.convertSignatureObjectToSignSignatureObject(s); + + LocalConnector local_conn = chooseLocalConnectorForVerify(connector, s.getKZ(), so.id, profile, loc_ref_url); + + Properties props = new Properties(); + props.setProperty(BKUPostConnection.RESPONSE_STRING_KEY, xmlResponse); + SignatureResponse sigResponse = local_conn.analyzeVerifyResponse(props); + return new VerifyResultAdapter(sigResponse, holder, null, null); // timestamp and xmldsig not needed here + } + + /** + * @see PdfAsInternal#getSignatureEntryFromSignatureInformation(String, SignatureInformation) + */ + public SignatureEntry getSignatureEntryFromSignatureInformation(String key, + SignatureInformation sigInfo) { + + SignatureHolder holder = (SignatureHolder)sigInfo.getInternalSignatureInformation(); + SignatureObject s = holder.getSignatureObject(); + at.knowcenter.wag.egov.egiz.sig.SignatureEntry internalEntry = s.getSigEntry(key); + if (internalEntry == null) + return null; + SignatureEntry ret = new SignatureEntry(key); + ret.setCaption(internalEntry.getCaption()); + ret.setValue(internalEntry.getValue()); + return ret; + } + + /** + * @see PdfAsInternal#getSignedText(SignatureInformation) + */ + public String getSignedText(SignatureInformation sigInfo) { + SignatureHolder holder = (SignatureHolder)sigInfo.getInternalSignatureInformation(); + if (holder instanceof TextualSignatureHolder) + return ((TextualSignatureHolder)holder).getSignedText(); + return null; + } + + /** + * @see PdfAsInternal#getConnectorsAvailableForWeb() + */ + public Map getConnectorsAvailableForWeb() throws ConnectorFactoryException { + ConnectorInformation ci[] = ConnectorFactory.getConnectorInformationArray(); + + Map ret = new HashMap(); + for (int i = 0; i < ci.length; i++) + { + String id = ci[i].getIdentifier(); + if (ConnectorFactory.isAvailableForWeb(id)) + { + ret.put(id, ci[i].getDescription()); + } + } + return ret; + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/sign/ActualSignaturePositionAdapter.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/sign/ActualSignaturePositionAdapter.java new file mode 100644 index 0000000..1cc5699 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/sign/ActualSignaturePositionAdapter.java @@ -0,0 +1,93 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.api.sign; + +import at.gv.egiz.pdfas.api.sign.pos.SignaturePosition; +import at.knowcenter.wag.egov.egiz.pdf.ActualTablePos; + +/** + * Adapter that converts from a framework ActualTablePos to an API + * ActualSignaturePosition. + * + * @author wprinz + * + */ +public class ActualSignaturePositionAdapter implements SignaturePosition +{ + /** + * The framework ActualTablePos. + */ + protected ActualTablePos atp = null; + + /** + * Constructor. + * + * @param actualTablePos + * The framework ActualTablePos. + */ + public ActualSignaturePositionAdapter(ActualTablePos actualTablePos) + { + this.atp = actualTablePos; + } + + /** + * @see at.gv.egiz.pdfas.api.sign.pos.SignaturePosition#getPage() + */ + public int getPage() + { + return this.atp.page; + } + + /** + * @see at.gv.egiz.pdfas.api.sign.pos.SignaturePosition#getX() + */ + public float getX() + { + return this.atp.x; + } + + /** + * @see at.gv.egiz.pdfas.api.sign.pos.SignaturePosition#getY() + */ + public float getY() + { + return this.atp.y; + } + + /** + * @see at.gv.egiz.pdfas.api.sign.pos.SignaturePosition#getWidth() + */ + public float getWidth() + { + return this.atp.width; + } + + /** + * @see at.gv.egiz.pdfas.api.sign.pos.SignaturePosition#getHeight() + */ + public float getHeight() + { + return this.atp.height; + } +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/sign/SignResultImpl.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/sign/SignResultImpl.java new file mode 100644 index 0000000..163d1d2 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/sign/SignResultImpl.java @@ -0,0 +1,115 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.api.sign; + +import java.security.cert.X509Certificate; +import java.util.List; + +import at.gv.egiz.pdfas.api.analyze.NonTextObjectInfo; +import at.gv.egiz.pdfas.api.io.DataSink; +import at.gv.egiz.pdfas.api.sign.SignResult; +import at.gv.egiz.pdfas.api.sign.pos.SignaturePosition; + +/** + * Implementation of the SignResult interface. + * + * @author wprinz + */ +public class SignResultImpl implements SignResult +{ + /** + * The filled output DataSink. + */ + protected DataSink outputDocument = null; + + /** + * The signer certificate. + */ + protected X509Certificate signerCertificate = null; + + /** + * The signature position. + */ + protected SignaturePosition signaturePosition = null; + + /** + * List {@link NonTextObjectInfo} + */ + protected List nonTextObjects; + + /** + * Constructor. + * + * @param outputDocument + * The filled output DataSink. + * @param signerCertificate + * The signer certificate. + * @param signaturePosition + * The signature position. + */ + public SignResultImpl(DataSink outputDocument, X509Certificate signerCertificate, SignaturePosition signaturePosition, List nonTextObjects) + { + this.outputDocument = outputDocument; + this.signerCertificate = signerCertificate; + this.signaturePosition = signaturePosition; + this.nonTextObjects = nonTextObjects; + } + + /** + * @see at.gv.egiz.pdfas.api.sign.SignResult#getOutputDocument() + */ + public DataSink getOutputDocument() + { + return this.outputDocument; + } + + /** + * @see at.gv.egiz.pdfas.api.sign.SignResult#getSignaturePosition() + */ + public SignaturePosition getSignaturePosition() + { + return this.signaturePosition; + } + + /** + * @see at.gv.egiz.pdfas.api.sign.SignResult#getSignerCertificate() + */ + public X509Certificate getSignerCertificate() + { + return this.signerCertificate; + } + + + /** + * List {@link NonTextObjectInfo} + */ + public List getNonTextualObjects() { + return this.nonTextObjects; + } + + public boolean hasNonTextualObjects() { + return this.nonTextObjects != null && this.nonTextObjects.size() > 0; + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/sign/SignatureDetailInformationImpl.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/sign/SignatureDetailInformationImpl.java new file mode 100644 index 0000000..18b88ed --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/sign/SignatureDetailInformationImpl.java @@ -0,0 +1,190 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.api.sign; + +import java.security.cert.X509Certificate; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import at.gv.egiz.pdfas.api.io.DataSource; +import at.gv.egiz.pdfas.api.sign.SignatureDetailInformation; +import at.gv.egiz.pdfas.api.sign.pos.SignaturePosition; +import at.gv.egiz.pdfas.framework.input.TextDataSource; +import at.gv.egiz.pdfas.framework.signator.SignatorInformation; +import at.gv.egiz.pdfas.impl.api.commons.DataSourceApiAdapter; +import at.gv.egiz.pdfas.impl.api.commons.TextBasedDataSourceApiAdapter; +import at.knowcenter.wag.egov.egiz.pdf.EGIZDate; +import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject; + +/** + * + * @author exthex + * + */ +public class SignatureDetailInformationImpl implements SignatureDetailInformation { + + private DataSource signatureData; + private SignaturePosition signaturePosition; + private List nonTextualObjects; + private String dateString; + private Date signDate; + private String issuer; + private Map issuerDNMap; + private String name; + private String serialNumber; + private String sigAlgorithm; + private String sigID; + private String sigKZ; + private String signatureValue; + private String sigTimeStamp; + private Map subjectDNMap; + private X509Certificate x509Certificate; + private boolean textual; + private Properties responseProperties; + private SignatorInformation signatorInfo; + + public DataSource getSignatureData() { + return this.signatureData; + } + + public SignaturePosition getSignaturePosition() { + return this.signaturePosition; + } + + public List getNonTextualObjects() { + return this.nonTextualObjects; + } + + public Date getSignDate() { + return this.signDate; + } + + public String getIssuer() { + return this.issuer; + } + + public Map getIssuerDNMap() { + return this.issuerDNMap; + } + + public String getSubjectName() { + return this.name; + } + + public String getSerialNumber() { + return this.serialNumber; + } + + public String getSigAlgorithm() { + return this.sigAlgorithm; + } + + public String getSigID() { + return this.sigID; + } + + public String getSigKZ() { + return this.sigKZ; + } + + public String getSignatureValue() { + return this.signatureValue; + } + + public String getSigTimeStamp() { + return this.sigTimeStamp; + } + + public Map getSubjectDNMap() { + return this.subjectDNMap; + } + + public X509Certificate getX509Certificate() { + return this.x509Certificate; + } + + public boolean isTextual() { + return textual; + } + + public boolean isBinary() { + return !textual; + } + + public void setSignSignatureObject(SignSignatureObject sso) { + this.dateString = sso.getDate(); + if (this.dateString != null){ + this.signDate = EGIZDate.parseDateFromString(this.dateString); + } + this.issuer = sso.getIssuer(); + this.issuerDNMap = sso.getIssuerDNMap(); + this.name = sso.getName(); //extracted from x509Certificate + this.serialNumber = sso.getSerialNumber(); //extracted from x509Certificate + this.sigAlgorithm = sso.getSigAlgorithm(); + this.sigID = sso.getSigID(); + this.sigKZ = sso.getSigKZ(); + this.signatureValue = sso.getSignatureValue(); + this.sigTimeStamp = sso.getSigTimeStamp(); + this.subjectDNMap = sso.getSubjectDNMap(); + this.x509Certificate = sso.getX509Certificate(); + this.responseProperties = sso.response_properties; + if (this.signatorInfo != null){ + this.signatorInfo.setSignSignatureObject(sso); + } + } + + public SignSignatureObject getSignSignatureObject() { + SignSignatureObject ret = new SignSignatureObject(); + ret.date = this.dateString; + ret.id = this.sigID; + ret.issuer = this.issuer; + ret.issuerDNMap = this.issuerDNMap; + ret.kz = this.sigKZ; + ret.response_properties = this.responseProperties; + ret.sigAlgorithm = this.sigAlgorithm; + ret.signatureValue = this.signatureValue; + ret.sigTimeStamp = this.sigTimeStamp; + ret.subjectDNMap = this.subjectDNMap; + ret.x509Certificate = this.x509Certificate; + + return ret; + } + + public SignatorInformation getSignatorInfo() { + return this.signatorInfo; + } + + public void setSignatorInformation(SignatorInformation signatorInformation){ + this.signatorInfo = signatorInformation; + this.signaturePosition = new ActualSignaturePositionAdapter(signatorInformation.getActualTablePos()); + this.nonTextualObjects = signatorInformation.getNonTextualObjects(); + at.gv.egiz.pdfas.framework.input.DataSource dataSource = signatorInformation.getSignatureData().getDataSource(); + if (dataSource instanceof TextDataSource) + this.signatureData = new TextBasedDataSourceApiAdapter((TextDataSource)dataSource); + else + this.signatureData = new DataSourceApiAdapter(dataSource); + } +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/verify/SignatureCheckImpl.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/verify/SignatureCheckImpl.java new file mode 100644 index 0000000..84df2a5 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/verify/SignatureCheckImpl.java @@ -0,0 +1,71 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.api.verify; + +import at.gv.egiz.pdfas.api.verify.SignatureCheck; + +/** + * @author wprinz + */ +public class SignatureCheckImpl implements SignatureCheck +{ + /** + * The check code. + */ + protected int code = -1; + + /** + * The check code message. + */ + protected String message = null; + + + + /** + * @param code The check code. + * @param message The check code message. + */ + public SignatureCheckImpl(int code, String message) + { + this.code = code; + this.message = message; + } + + /** + * @see at.gv.egiz.pdfas.api.verify.SignatureCheck#getCode() + */ + public int getCode() + { + return this.code; + } + + /** + * @see at.gv.egiz.pdfas.api.verify.SignatureCheck#getMessage() + */ + public String getMessage() + { + return this.message; + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/verify/VerifyResultAdapter.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/verify/VerifyResultAdapter.java new file mode 100644 index 0000000..09d247d --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/verify/VerifyResultAdapter.java @@ -0,0 +1,205 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.api.verify; + +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.pdfas.api.exceptions.PdfAsException; +import at.gv.egiz.pdfas.api.verify.SignatureCheck; +import at.gv.egiz.pdfas.api.verify.VerifyResult; +import at.gv.egiz.pdfas.api.xmldsig.XMLDsigData; +import at.gv.egiz.pdfas.impl.api.commons.SignatureInformationAdapter; +import at.knowcenter.wag.egov.egiz.exceptions.SettingNotFoundException; +import at.knowcenter.wag.egov.egiz.pdf.BinarySignatureHolder; +import at.knowcenter.wag.egov.egiz.pdf.SignatureHolder; +import at.knowcenter.wag.egov.egiz.sig.SignatureResponse; + + +/** + * Implements the VerifyResult interface. + * + * @author wprinz + */ +public class VerifyResultAdapter extends SignatureInformationAdapter implements VerifyResult +{ + protected SignatureResponse sigRes = null; + + /** + * The log. + */ + private static final Log logger_ = LogFactory.getLog(VerifyResultAdapter.class); + + protected Date vTime = null; + + private String timestamp; + + private XMLDsigData xmlDsigData; + + + /** + * Constructor. + * + * @param sigRes + * The SignatureResponse. + * @param sh + * The SignatureHolder. + * @param verificationTime + * The time of verification. This is directly returned by {@link #getVerificationTime()} + * @param xmlDsigData + */ + public VerifyResultAdapter(SignatureResponse sigRes, SignatureHolder sh, Date verificationTime, XMLDsigData xmlDsigData) + { + super(sh); + this.sigRes = sigRes; + this.vTime = verificationTime; + this.xmlDsigData = xmlDsigData; + if (sh instanceof BinarySignatureHolder) { + this.timestamp = ((BinarySignatureHolder)sh).getSignatureObject().getTimeStamp(); + } + // [tknall] start: missing time of verification fixed + if (this.vTime == null) { + // verification time not been set (= null) therefore signingtime equals verificationtime + this.vTime = super.getSigningTime(); + } + // [tknall] stop: missing time of verification fixed + } + + /** + * @see at.gv.egiz.pdfas.api.verify.VerifyResult#getCertificateCheck() + */ + public SignatureCheck getCertificateCheck() + { + return new SignatureCheckImpl(Integer.parseInt(this.sigRes.getCertificateCheckCode()), this.sigRes.getCertificateCheckInfo()); + } + + /** + * @see at.gv.egiz.pdfas.api.verify.VerifyResult#getManifestCheckCode() + */ + public SignatureCheck getManifestCheckCode() + { + return new SignatureCheckImpl(Integer.parseInt(this.sigRes.getSignatureManifestCheckCode()), this.sigRes.getSignatureManifestCheckInfo()); + } + + /** + * @see at.gv.egiz.pdfas.api.verify.VerifyResult#getValueCheckCode() + */ + public SignatureCheck getValueCheckCode() + { + return new SignatureCheckImpl(Integer.parseInt(this.sigRes.getSignatureCheckCode()), this.sigRes.getSignatureCheckInfo()); + } + + /** + * @see at.gv.egiz.pdfas.api.verify.VerifyResult#getVerificationTime() + */ + public Date getVerificationTime() + { + return this.vTime; + } + + /** + * @see at.gv.egiz.pdfas.api.verify.VerifyResult#isQualifiedCertificate() + */ + public boolean isQualifiedCertificate() + { + return this.sigRes.isQualifiedCertificate(); + } + + /** + * @see at.gv.egiz.pdfas.api.verify.VerifyResult#getPublicProperties() + */ + public List getPublicProperties() + { + try + { + return this.sigRes.getPublicProperties(); + } + catch (SettingNotFoundException e) + { + logger_.error(e.getMessage(), e); + return new ArrayList(); + } + } + + /** + * @see at.gv.egiz.pdfas.api.commons.SignatureInformation#getInternalSignatureInformation() + */ + public Object getInternalSignatureInformation() + { + return null; + } + + /** + * @see at.gv.egiz.pdfas.api.commons.SignatureInformation#getSignerCertificate() + */ + public X509Certificate getSignerCertificate() + { + // TODO this should be the same as the signature holder's cert. + return this.sigRes.getCertificate().getX509Certificate(); + } + + /** + * @see at.gv.egiz.pdfas.api.verify.VerifyResult#getHashInputData() + */ + public String getHashInputData() + { + return this.sigRes.getHashInputData(); + } + + + /** + * @see at.gv.egiz.pdfas.api.verify.VerifyResult#getPublicAuthorityCode() + */ + public String getPublicAuthorityCode() { + return this.sigRes.getPublicAuthorityCode(); + } + + /** + * @see at.gv.egiz.pdfas.api.verify.VerifyResult#isPublicAuthority() + */ + public boolean isPublicAuthority() { + return this.sigRes.isPublicAuthority(); + } + + public PdfAsException getVerificationException() { + return this.sigRes.getVerificationImpossibleEx(); + } + + public boolean isVerificationDone() { + return this.sigRes.getVerificationImpossibleEx() == null; + } + + /** + * @see VerifyResult#getReconstructedXMLDsig() + */ + public XMLDsigData getReconstructedXMLDsig() { + return this.xmlDsigData; + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/verify/VerifyResultsImpl.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/verify/VerifyResultsImpl.java new file mode 100644 index 0000000..c5ce3ba --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/verify/VerifyResultsImpl.java @@ -0,0 +1,60 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.api.verify; + +import java.util.List; + +import at.gv.egiz.pdfas.api.verify.VerifyResults; + +/** + * @author wprinz + */ +public class VerifyResultsImpl implements VerifyResults +{ + /** + * The results. + */ + protected List results = null; + + /** + * Constructor. + * + * @param results + * The results. + */ + public VerifyResultsImpl(List results) + { + this.results = results; + } + + /** + * @see at.gv.egiz.pdfas.api.verify.VerifyResults#getResults() + */ + public List getResults() + { + return this.results; + } + + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/ByteArrayPdfDataSourceImpl.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/ByteArrayPdfDataSourceImpl.java new file mode 100644 index 0000000..edcb1d4 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/ByteArrayPdfDataSourceImpl.java @@ -0,0 +1,85 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.input; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +import at.gv.egiz.pdfas.performance.PerformanceCounters; +import at.gv.egiz.pdfas.framework.input.PdfDataSource; + +/** + * Implements a PdfDataSource that holds the whole PDF document in a byte array. + * + *

+ * Note that holding the data in a byte array is very memory consuming for large + * documents. + *

+ * + * @author wprinz + */ +public class ByteArrayPdfDataSourceImpl implements PdfDataSource +{ + protected byte[] pdf = null; + + public ByteArrayPdfDataSourceImpl(byte[] pdf) + { + PerformanceCounters.byteArrays.increment(); + + this.pdf = pdf; + } + + public ByteArrayPdfDataSourceImpl(byte[] pdf, int length) + { + PerformanceCounters.byteArrays.increment(); + + if (pdf.length == length) + { + this.pdf = pdf; + } + else + { + this.pdf = new byte [length]; + System.arraycopy(pdf, 0, this.pdf, 0, length); + } + } + + + public InputStream createInputStream() + { + ByteArrayInputStream bais = new ByteArrayInputStream(this.pdf); + return bais; + } + + public int getLength() + { + return this.pdf.length; + } + + public byte[] getAsByteArray() + { + return this.pdf; + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/CompoundPdfDataSourceImpl.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/CompoundPdfDataSourceImpl.java new file mode 100644 index 0000000..f5e9b76 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/CompoundPdfDataSourceImpl.java @@ -0,0 +1,85 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.input; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.SequenceInputStream; + +import at.gv.egiz.pdfas.framework.input.DataSource; +import at.gv.egiz.pdfas.framework.input.PdfDataSource; + +/** + * @author wprinz + * + */ +public class CompoundPdfDataSourceImpl implements PdfDataSource +{ + protected DataSource originalDataSource = null; + + protected byte[] appendix = null; + + public CompoundPdfDataSourceImpl (PdfDataSource original, byte [] appendix) + { + this.originalDataSource = original; + this.appendix = appendix; + } + + /** + * @see at.gv.egiz.pdfas.framework.input.DataSource#createInputStream() + */ + public InputStream createInputStream() + { + ByteArrayInputStream bais = new ByteArrayInputStream(this.appendix); + SequenceInputStream sis = new SequenceInputStream(this.originalDataSource.createInputStream(), bais); + return sis; + } + + /** + * @see at.gv.egiz.pdfas.framework.input.DataSource#getLength() + */ + public int getLength() + { + return this.originalDataSource.getLength() + this.appendix.length; + } + + byte [] cache = null; + + /** + * @see at.gv.egiz.pdfas.framework.input.DataSource#getAsByteArray() + */ + public byte[] getAsByteArray() + { + if (cache != null) + { + return cache; + } + + cache = new byte [getLength()]; + System.arraycopy(originalDataSource.getAsByteArray(), 0, cache, 0, originalDataSource.getLength()); + System.arraycopy(appendix, 0, cache, originalDataSource.getLength(), appendix.length); + + return cache; + } +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/DelimitedInputStream.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/DelimitedInputStream.java new file mode 100644 index 0000000..f10b546 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/DelimitedInputStream.java @@ -0,0 +1,125 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.input; + +import java.io.IOException; +import java.io.InputStream; + +/** + * An input stream that has a delimited length. + * + * @author wprinz + */ +public class DelimitedInputStream extends InputStream +{ + /** + * The underlying InputStream. + */ + protected InputStream is = null; + + /** + * The number of bytes that can be read from the stream. + */ + protected int bytes_to_read = -1; + + /** + * Constructs the DelimitedInputStream from which a maximum of length bytes + * can be read. + */ + public DelimitedInputStream(InputStream is, int length) + { + this.is = is; + this.bytes_to_read = length; + } + + /** + * @see java.io.InputStream#read() + */ + public int read() throws IOException + { + if (this.bytes_to_read <= 0) + { + return -1; + } + int read = this.is.read(); + if (read > 0) + { + this.bytes_to_read--; + } + return read; + } + + /** + * @see java.io.InputStream#read(byte[], int, int) + */ + public int read(byte[] b, int off, int len) throws IOException + { + int btr = Math.min(len, this.bytes_to_read); + int read = this.is.read(b, off, btr); + if (read > 0) + { + this.bytes_to_read -= read; + } + return read; + } + + /** + * @see java.io.InputStream#read(byte[]) + */ + public int read(byte[] b) throws IOException + { + return read(b, 0, b.length); + } + + /** + * @see java.io.InputStream#skip(long) + */ + public long skip(long n) throws IOException + { + long bts = Math.min(n, this.bytes_to_read); + long skipped = this.is.skip(bts); + if (skipped > 0) + { + this.bytes_to_read -= skipped; + } + return skipped; + } + + /** + * @see java.io.InputStream#close() + */ + public void close() throws IOException + { + this.is.close(); + } + + /** + * @see java.io.InputStream#available() + */ + public int available() throws IOException + { + int avail = this.is.available(); + return Math.min(this.bytes_to_read, avail); + } +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/DelimitedPdfDataSource.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/DelimitedPdfDataSource.java new file mode 100644 index 0000000..ca73f37 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/DelimitedPdfDataSource.java @@ -0,0 +1,82 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.input; + +import java.io.InputStream; + +import at.gv.egiz.pdfas.framework.input.PdfDataSource; + +/** + * @author wprinz + * + */ +public class DelimitedPdfDataSource implements PdfDataSource +{ + + protected PdfDataSource dataSource = null; + protected int len = -1; + + public DelimitedPdfDataSource (PdfDataSource original, int length) + { + this.dataSource = original; + this.len = length; + } + + /** + * @see at.gv.egiz.pdfas.framework.input.DataSource#createInputStream() + */ + public InputStream createInputStream() + { + InputStream originalIS = this.dataSource.createInputStream(); + DelimitedInputStream dis = new DelimitedInputStream(originalIS, this.len); + return dis; + } + + /** + * @see at.gv.egiz.pdfas.framework.input.DataSource#getLength() + */ + public int getLength() + { + return this.len; + } + + byte [] cache = null; + + /** + * @see at.gv.egiz.pdfas.framework.input.DataSource#getAsByteArray() + */ + public byte[] getAsByteArray() + { + if (cache != null) + { + return cache; + } + + cache = new byte [getLength()]; + System.arraycopy(dataSource.getAsByteArray(), 0, cache, 0, getLength()); + + return cache; + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/FileBased.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/FileBased.java new file mode 100644 index 0000000..65ee416 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/FileBased.java @@ -0,0 +1,40 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.input; + +import java.io.File; + +/** + * Interface that reveals the underlying data file. + * + * @author wprinz + */ +public interface FileBased +{ + /** + * Returns the underlying data file. + * @return Returns the underlying data file. + */ + public File getFile(); +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/FileBasedPdfDataSourceImpl.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/FileBasedPdfDataSourceImpl.java new file mode 100644 index 0000000..a710c3c --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/FileBasedPdfDataSourceImpl.java @@ -0,0 +1,150 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.input; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.pdfas.framework.input.PdfDataSource; +import at.gv.egiz.pdfas.impl.input.helper.DataSourceHelper; + +/** + * @author wprinz + * + */ +public class FileBasedPdfDataSourceImpl implements PdfDataSource, FileBased +{ + /** + * The log. + */ + private static final Log log = LogFactory.getLog(FileBasedPdfDataSourceImpl.class); + + /** + * The underlying file. + */ + protected File inputFile = null; + + protected int length = -1; + + /** + * Constructor that creates this PdfDataSource backed by a file in the file + * system. + * + * @param file + * The input File. + * @param length + * The length of the InputStream. The is the maximum number of bytes + * that can be read from the stream. + * @throws IOException + * Thrown if the file cannot be read properly. + */ + public FileBasedPdfDataSourceImpl(File file, int length) throws IOException + { + + if (!file.exists()) + { + throw new FileNotFoundException("The file '" + file + "' does not exist."); + } + // for some reason the isFile is not always correct... + // if (file.isFile()) + // { + // throw new IOException("The file '" + file + "' is not a normal file."); + // } + if (!file.canRead()) + { + throw new IOException("The file '" + file + "' cannot be read."); + } + + this.inputFile = file; + this.length = length; + } + + /** + * @see at.gv.egiz.pdfas.impl.input.FileBased#getFile() + */ + public File getFile() + { + return this.inputFile; + } + + /** + * @see at.gv.egiz.pdfas.framework.input.PdfDataSource#createInputStream() + */ + public InputStream createInputStream() + { + if (cache == null) + { + getAsByteArray(); + } + return new ByteArrayInputStream(cache); + } + + protected InputStream createFileInputStream() + { + try + { + FileInputStream fis = new FileInputStream(getFile()); + DelimitedInputStream dis = new DelimitedInputStream(fis, getLength()); + return dis; + } + catch (IOException e) + { + log.error("Couldn't create InputStream for file " + getFile() + ". Returning null.", e); + + return null; + } + } + /** + * @see at.gv.egiz.pdfas.framework.input.PdfDataSource#getLength() + */ + public int getLength() + { + return this.length; + } + + byte [] cache = null; + + /** + * @see at.gv.egiz.pdfas.framework.input.DataSource#getAsByteArray() + */ + public byte[] getAsByteArray() + { + if (cache != null) + { + return cache; + } + + cache = DataSourceHelper.convertInputStreamToByteArray(createFileInputStream()); + + return cache; + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/FileBasedTextDataSourceImpl.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/FileBasedTextDataSourceImpl.java new file mode 100644 index 0000000..5a84ce2 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/FileBasedTextDataSourceImpl.java @@ -0,0 +1,160 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.input; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.pdfas.framework.input.TextDataSource; +import at.gv.egiz.pdfas.impl.input.helper.DataSourceHelper; + +/** + * @author wprinz + * + */ +public class FileBasedTextDataSourceImpl implements TextDataSource, FileBased +{ + /** + * The log. + */ + private static final Log log = LogFactory.getLog(FileBasedTextDataSourceImpl.class); + + protected File file = null; + + protected String characterEncoding = null; + + public FileBasedTextDataSourceImpl(File file, String characterEncoding) throws IOException + { + if (!file.exists()) + { + throw new FileNotFoundException("The file '" + file + "' does not exist."); + } + if (!file.canRead()) + { + throw new IOException("The file '" + file + "' cannot be read."); + } + + this.file = file; + this.characterEncoding = characterEncoding; + } + + /** + * @see at.gv.egiz.pdfas.impl.input.FileBased#getFile() + */ + public File getFile() + { + return this.file; + } + + /** + * Returns the character encoding. + * + * @return Returns the character encoding. + */ + public String getCharacterEncoding() + { + return this.characterEncoding; + } + + /** + * @see at.gv.egiz.pdfas.framework.input.TextDataSource#getText() + */ + public String getText() + { + try + { + InputStream is = createInputStream(); + byte[] data = new byte[getLength()]; + int read = 0; + int n = 0; + while ((n = is.read(data, read, data.length - read)) > 0) + { + read += n; + } + is.close(); + + String text = new String(data, getCharacterEncoding()); + + data = null; + + return text; + } + catch (IOException e) + { + log.error("Couldn't read text for file " + getFile() + ". Returning null.", e); + + return null; + } + } + + /** + * @see at.gv.egiz.pdfas.framework.input.DataSource#createInputStream() + */ + public InputStream createInputStream() + { + try + { + FileInputStream fis = new FileInputStream(getFile()); + return fis; + } + catch (IOException e) + { + log.error("Couldn't create InputStream for file " + getFile() + ". Returning null.", e); + + return null; + } + } + + /** + * @see at.gv.egiz.pdfas.framework.input.DataSource#getLength() + */ + public int getLength() + { + return (int) getFile().length(); + } + + byte [] cache = null; + + /** + * @see at.gv.egiz.pdfas.framework.input.DataSource#getAsByteArray() + */ + public byte[] getAsByteArray() + { + if (cache != null) + { + return cache; + } + + cache = DataSourceHelper.convertInputStreamToByteArray(createInputStream()); + + return cache; + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/IncrementalUpdateParser.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/IncrementalUpdateParser.java new file mode 100644 index 0000000..c1dcc03 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/IncrementalUpdateParser.java @@ -0,0 +1,92 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.input; + +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.pdfas.exceptions.ErrorCode; +import at.gv.egiz.pdfas.framework.input.PdfDataSource; +import at.gv.egiz.pdfas.framework.input.PdfDataSourceHolder; +import at.gv.egiz.pdfas.framework.input.correction.Corrector; +import at.gv.egiz.pdfas.framework.input.correction.CorrectorFactory; +import at.gv.egiz.pdfas.impl.input.helper.DataSourceHelper; +import at.knowcenter.wag.egov.egiz.cfg.SettingsReader; +import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException; +import at.knowcenter.wag.exactparser.ParseDocument; + +/** + * Parses the given PDF document into a list of Incremental Update blocks. + * @author wprinz + */ +public class IncrementalUpdateParser +{ + /** + * The log. + */ + private static final Log log = LogFactory.getLog(IncrementalUpdateParser.class); + + public static List parsePdfIntoIUBlocks (PdfDataSourceHolder pdfDataSource) throws PDFDocumentException + { + log.trace("parsePdfIntoIUBlocks:"); + + List blocks = null; + try + { + byte [] pdf = DataSourceHelper.convertDataSourceToByteArray(pdfDataSource.getDataSource()); + blocks = ParseDocument.parseDocument(pdf); + } + catch (Exception e) { + try { + log.debug("Error while parsing Document.", e); + boolean tryToCorrect = SettingsReader.getInstance().getSetting("correct_document_on_verify_if_necessary", "false").equals("true"); + if (tryToCorrect) { + log.info("Correcting document..."); + Corrector cor = CorrectorFactory.createCorrector(); + PdfDataSource correctedDS = cor.correctDocument(pdfDataSource.getDataSource()); + log.info("Correction finished."); + byte [] pdf = DataSourceHelper.convertDataSourceToByteArray(correctedDS); + blocks = ParseDocument.parseDocument(pdf); + pdfDataSource.setDataSource(correctedDS); + } else { + makeError(e); + } + + } catch (Exception e1) { + makeError(e); + } + } + + log.trace("parsePdfIntoIUBlocks finished."); + return blocks; + } + + private static void makeError(Exception e) throws PDFDocumentException { + log.error("Error while parsing Document into IU blocks.", e); + throw new PDFDocumentException(ErrorCode.DOCUMENT_CANNOT_BE_READ, e); + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/TextDataSourceImpl.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/TextDataSourceImpl.java new file mode 100644 index 0000000..fa5ab04 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/TextDataSourceImpl.java @@ -0,0 +1,120 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.input; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; + +import at.gv.egiz.pdfas.framework.input.TextDataSource; + +/** + * A TextDataSource that keeps the text in memory. + * + *

+ * Keeping the text in memory is fast as long as the text is short, but may + * result in bad memory performance when the text is longer. Use a FileBased + * TextDataSource instead if memory is an issue. + *

+ * + * @author wprinz + */ +public class TextDataSourceImpl implements TextDataSource +{ + /** + * The text. + */ + protected String text = null; + + private final static String CHARSET = "UTF-8"; + + /** + * Constructor that sets the text. + * + * @param text + * The text. + */ + public TextDataSourceImpl(String text) + { + this.text = text; + } + + /** + * @see at.gv.egiz.pdfas.framework.input.TextDataSource#getText() + */ + public String getText() + { + return this.text; + } + + /** + * @see at.gv.egiz.pdfas.framework.input.DataSource#createInputStream() + */ + public InputStream createInputStream() + { + try + { + byte[] data = getText().getBytes(CHARSET); + // PERF: if memory is an issue (e.g. in web), use a FileBased TextDataSource instead. + return new ByteArrayInputStream(data); + } + catch (UnsupportedEncodingException e) + { + throw new RuntimeException(e); + } + } + + /** + * @see at.gv.egiz.pdfas.framework.input.DataSource#getLength() + */ + public int getLength() + { + try + { + byte[] data = getText().getBytes(CHARSET); + return data.length; + } + catch (UnsupportedEncodingException e) + { + throw new RuntimeException(e); + } + } + + /** + * @see at.gv.egiz.pdfas.framework.input.DataSource#getAsByteArray() + */ + public byte[] getAsByteArray() + { + try + { + byte[] data = getText().getBytes(CHARSET); + return data; + } + catch (UnsupportedEncodingException e) + { + throw new RuntimeException(e); + } + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/correction/ExternalCorrector.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/correction/ExternalCorrector.java new file mode 100644 index 0000000..efd094a --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/correction/ExternalCorrector.java @@ -0,0 +1,283 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.input.correction; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.pdfas.exceptions.ErrorCode; +import at.gv.egiz.pdfas.exceptions.framework.CorrectorException; +import at.gv.egiz.pdfas.framework.input.PdfDataSource; +import at.gv.egiz.pdfas.framework.input.correction.Corrector; +import at.gv.egiz.pdfas.impl.input.FileBased; +import at.gv.egiz.pdfas.impl.input.FileBasedPdfDataSourceImpl; +import at.gv.egiz.pdfas.utils.TempDirHelper; +import at.knowcenter.wag.egov.egiz.cfg.SettingsReader; +import at.knowcenter.wag.egov.egiz.exceptions.SettingNotFoundException; +import at.knowcenter.wag.egov.egiz.exceptions.SettingsException; + +/** + * Corrects the document using an extrenal commandline tool. + * + *

+ * Process.destroy after a certain timeout does not work if the executable is a + * Windows batch file. + *

+ * + * @author wprinz + */ +public class ExternalCorrector implements Corrector +{ + public static final String INPUT_DOCUMENT_REPLACE = "##input_document##"; + + public static final String OUTPUT_DOCUMENT_REPLACE = "##output_document##"; + + public static final String COMMANDLINE_KEY = "external_corrector_commandline"; + + public static final String TIMEOUT_KEY = "external_corrector_timeout"; + + protected static final int DEFAULT_TIMEOUT = 1000; + + /** + * The log. + */ + private static final Log log = LogFactory.getLog(ExternalCorrector.class); + + /** + * @see at.gv.egiz.pdfas.framework.input.correction.Corrector#correctDocument(at.gv.egiz.pdfas.framework.input.PdfDataSource) + */ + public PdfDataSource correctDocument(PdfDataSource document) throws CorrectorException + { + + try + { + String outName = null; + File in = null; + if (document instanceof FileBased) + { + FileBased fb = (FileBased) document; + in = fb.getFile(); + outName = in.getName() + "_correction_outfile.pdf"; + } + else + { + in = TempDirHelper.placeInputIntoTempDirFile(document.createInputStream(), "correction_infile.pdf"); + outName = "correction_outfile.pdf"; + } + + File out = TempDirHelper.formTempFile(outName); + + String commandline = SettingsReader.getInstance().getSetting(COMMANDLINE_KEY); + long timeout = SettingsReader.getInstance().getIntSetting(TIMEOUT_KEY, DEFAULT_TIMEOUT); + + String inF = in.getAbsolutePath(); + commandline = commandline.replaceFirst(INPUT_DOCUMENT_REPLACE, inF.replaceAll("\\\\", "\\\\\\\\")); + String outF = out.getAbsolutePath(); + commandline = commandline.replaceFirst(OUTPUT_DOCUMENT_REPLACE, outF.replaceAll("\\\\", "\\\\\\\\")); + + log.info(commandline); + + Process p = Runtime.getRuntime().exec(commandline); + + Thread outT = null; + Thread errT = null; + TimeoutThread tt = null; + BufferedReader outReader = null; + BufferedReader errReader = null; + + try + { + outReader = new BufferedReader(new InputStreamReader(p.getInputStream())); + errReader = new BufferedReader(new InputStreamReader(p.getErrorStream())); + + outT = new Thread(new ReaderPrinter(outReader, "STDOUT")); + errT = new Thread(new ReaderPrinter(errReader, "STDERR")); + + tt = new TimeoutThread(p, timeout, new Thread[] { outT, errT }); + + tt.start(); + outT.start(); + errT.start(); + + log.trace("Joining the STDOUT thread..."); + outT.join(); + log.trace("STDOUT thread joined."); + log.trace("Joining the STDERR thread..."); + errT.join(); + log.trace("STDERR thread joined."); + + log.trace("Waiting for process to end..."); + p.waitFor(); + log.trace("process has ended."); + + log.trace("Interrupting timeout thread..."); + tt.interrupt(); + log.trace("timeout thread has been interrupted."); + + int exitValue = p.exitValue(); + log.info("External Corrector exited with: " + exitValue); + + if (tt.isTimedOut()) + { + throw new CorrectorException(ErrorCode.EXTERNAL_CORRECTOR_TIMEOUT_REACHED, "The external corrector process timed out. timeout = " + timeout); + } + + PdfDataSource ds = new FileBasedPdfDataSourceImpl(out, (int) out.length()); + return ds; + } + finally + { + if (outT != null) + { + outT.interrupt(); + } + if (errT != null) + { + errT.interrupt(); + } + if (tt != null) + { + tt.interrupt(); + } + if (outReader != null) + { + outReader.close(); + } + if (errReader != null) + { + errReader.close(); + } + } + + } + catch (IOException e) + { + throw new CorrectorException(ErrorCode.CORRECTOR_EXCEPTION, e); + } + catch (InterruptedException e) + { + throw new CorrectorException(ErrorCode.CORRECTOR_EXCEPTION, e); + } + catch (SettingNotFoundException e) + { + throw new CorrectorException(ErrorCode.CORRECTOR_EXCEPTION, e); + } + catch (SettingsException e) + { + throw new CorrectorException(ErrorCode.CORRECTOR_EXCEPTION, e); + } + } + + protected static class ReaderPrinter implements Runnable + { + protected BufferedReader reader = null; + + protected String streamName = null; + + public ReaderPrinter(BufferedReader reader, String streamName) + { + this.reader = reader; + this.streamName = streamName; + } + + public void run() + { + try + { + String line = null; + + while ((line = this.reader.readLine()) != null) + { + if (line != null) + { + log.info(streamName + ": " + line); + } + } + } + catch (IOException e) + { + log.error(e.getMessage(), e); + } + } + } + + protected static class TimeoutThread extends Thread + { + protected Process proc = null; + + protected long timeout = -1; + + protected boolean ranIntoTimeout = false; + + protected Thread[] threads; + + protected BufferedReader errReader; + + public TimeoutThread(Process proc, long timeout, Thread[] threadsToInterrupt) + { + this.proc = proc; + this.timeout = timeout; + this.threads = threadsToInterrupt; + } + + public void run() + { + try + { + Thread.sleep(this.timeout); + log.info("The timeout was reached. Destroying the process."); + proc.destroy(); + ranIntoTimeout = true; + log.trace("destroy has been called."); + log.trace("Interrupting threads..."); + for (int i = 0; i < this.threads.length; i++) + { + this.threads[i].interrupt(); + } + log.trace("threads have been interrupted."); + } + catch (InterruptedException e) + { + log.debug("Timeout thread interrupted. This means that the process finished successfully."); + } + } + + /** + * Tells, if the process ran into the timeout. + * + * @return Returns true if the timeout was reached. Returns false if the + * timeout was not reached. + */ + public boolean isTimedOut() + { + return this.ranIntoTimeout; + } + } + +} 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 new file mode 100644 index 0000000..eaa6b7f --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/correction/InternalCorrector.java @@ -0,0 +1,82 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.input.correction; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import at.gv.egiz.pdfas.exceptions.ErrorCode; +import at.gv.egiz.pdfas.exceptions.framework.CorrectorException; +import at.gv.egiz.pdfas.framework.input.PdfDataSource; +import at.gv.egiz.pdfas.framework.input.correction.Corrector; +import at.gv.egiz.pdfas.impl.input.ByteArrayPdfDataSourceImpl; +import at.gv.egiz.pdfas.utils.PDFASUtils; +import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException; + +import com.lowagie.text.DocumentException; +import com.lowagie.text.pdf.PdfReader; +import com.lowagie.text.pdf.PdfStamper; + +/** + * Corrects a document using iText. + * + * @author wprinz + */ +public class InternalCorrector implements Corrector +{ + + /** + * @see at.gv.egiz.pdfas.framework.input.correction.Corrector#correctDocument(at.gv.egiz.pdfas.framework.input.PdfDataSource) + */ + public PdfDataSource correctDocument(PdfDataSource document) throws CorrectorException + { + try + { + byte[] pdf = document.getAsByteArray(); + PdfReader reader = new PdfReader(pdf); + PDFASUtils.checkReaderPermissions(reader); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(pdf.length); + + PdfStamper stamper = new PdfStamper(reader, baos, '\0', false); + stamper.close(); + + baos.close(); + byte[] corrected_pdf = baos.toByteArray(); + + return new ByteArrayPdfDataSourceImpl(corrected_pdf); + } + catch (DocumentException e) + { + throw new CorrectorException(ErrorCode.CORRECTOR_EXCEPTION, e); + } + catch (IOException e) + { + throw new CorrectorException(ErrorCode.CORRECTOR_EXCEPTION, e); + } catch (PDFDocumentException e) { + throw new CorrectorException(e.getErrorCode(), e); + } + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/helper/DataSourceHelper.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/helper/DataSourceHelper.java new file mode 100644 index 0000000..76a5f99 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/helper/DataSourceHelper.java @@ -0,0 +1,148 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.input.helper; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import at.gv.egiz.pdfas.performance.PerformanceCounters; +import at.gv.egiz.pdfas.framework.input.DataSource; +import at.gv.egiz.pdfas.framework.input.PdfDataSource; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * @author wprinz + * + */ +public class DataSourceHelper +{ + /** + * The log. + */ + private static final Log log = LogFactory.getLog(DataSourceHelper.class); + + /** + * Converts a PdfDataSource to a byte array. + * + *

+ * Note that this function is very memory intensive. Use the Streams whereever + * possible. + *

+ * + * @deprecated + * + * @param pdfDataSource + * @return + * @throws IOException + */ + public static byte[] convertDataSourceToByteArray(DataSource pdfDataSource) + { + return pdfDataSource.getAsByteArray(); +// try +// { +// PerformanceCounters.byteArrays.increment(); +// +// byte[] data = new byte[pdfDataSource.getLength()]; +// +// int bytes_written = 0; +// +// InputStream is = pdfDataSource.createInputStream(); +// int n = 0; +// while ((n = is.read(data, bytes_written, data.length - bytes_written)) > 0) +// { +// bytes_written += n; +// } +// is.close(); +// +// assert bytes_written == data.length; +// +// return data; +// } +// catch (IOException e) +// { +// log.error(e); +// throw new RuntimeException(e); +// } + } + + public static byte [] convertInputStreamToByteArray(InputStream inputStream) + { + try + { + return convertInputStreamToByteArrayIOEx(inputStream); + } + catch (IOException e) + { + log.error(e); + throw new RuntimeException(e); + } + } + + public static byte [] convertInputStreamToByteArrayIOEx(InputStream inputStream) throws IOException + { + PerformanceCounters.byteArrays.increment(); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(4096); + + byte[] temp = new byte[4096]; + + int n = 0; + while ((n = inputStream.read(temp)) > 0) + { + baos.write(temp, 0, n); + } + inputStream.close(); + + baos.close(); + byte [] data = baos.toByteArray(); + + return data; + } + + public static void debugDataSourceToFile(DataSource dataSource, File file) + { + try + { + InputStream is = dataSource.createInputStream(); + FileOutputStream fos = new FileOutputStream(file); + byte[] data = new byte[2048]; + int n = -1; + while ((n = is.read(data)) > 0) + { + fos.write(data, 0, n); + } + is.close(); + fos.close(); + } + catch (IOException e) + { + log.error(e); + } + } +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/output/ByteArrayDataSink.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/output/ByteArrayDataSink.java new file mode 100644 index 0000000..d1de405 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/output/ByteArrayDataSink.java @@ -0,0 +1,106 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.output; + +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.pdfas.framework.output.DataSink; +import at.gv.egiz.pdfas.performance.PerformanceCounters; + +/** + * @author wprinz + * + */ +public class ByteArrayDataSink implements DataSink +{ + /** + * The log. + */ + private static final Log log = LogFactory.getLog(ByteArrayDataSink.class); + + protected String mimeType = null; + protected String characterEncoding = null; + + protected ByteArrayOutputStream baos = null; + + + public ByteArrayDataSink() + { + PerformanceCounters.byteArrays.increment(); + } + + /** + * @see at.gv.egiz.pdfas.framework.output.DataSink#createOutputStream(java.lang.String) + */ + public OutputStream createOutputStream(String mimeType) + { + return createOutputStream(mimeType, null); + } + + /** + * @see at.gv.egiz.pdfas.framework.output.DataSink#createOutputStream(java.lang.String, java.lang.String) + */ + public OutputStream createOutputStream(String mimeType, String characterEncoding) + { + this.mimeType = mimeType; + this.characterEncoding = characterEncoding; + + if (this.baos != null) + { + log.warn("An output stream is created twice. The old one will be rendered useless."); + } + this.baos = new ByteArrayOutputStream(4096); + return this.baos; + } + + /** + * Returns the byte array. + * @return Returns the byte array. + */ + public byte [] getByteArray () + { + return this.baos.toByteArray(); + } + + /** + * @return the mimeType + */ + public String getMimeType() + { + return this.mimeType; + } + + /** + * @return the characterEncoding + */ + public String getCharacterEncoding() + { + return this.characterEncoding; + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/output/FileBasedDataSink.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/output/FileBasedDataSink.java new file mode 100644 index 0000000..0880af0 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/output/FileBasedDataSink.java @@ -0,0 +1,145 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.output; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import at.gv.egiz.pdfas.framework.output.DataSink; +import at.gv.egiz.pdfas.impl.input.FileBased; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * @author wprinz + * + */ +public class FileBasedDataSink implements DataSink, FileBased +{ + /** + * The log. + */ + private static final Log log = LogFactory.getLog(FileBasedDataSink.class); + + protected String mimeType = null; + protected String characterEncoding = null; + + /** + * The output file. + */ + protected File outputFile = null; + + /** + * Creates a file based PdfDataSink. + * + * @param file + * The file. + * @throws IOException + * F.e. + */ + public FileBasedDataSink(File file) throws IOException + { + if (!file.exists()) + { + file.createNewFile(); + } + if (!file.isFile()) + { + throw new IOException("The file '" + file + "' is not a normal file."); + } + if (!file.canWrite()) + { + throw new IOException("The file '" + file + "' cannot be written."); + } + + this.outputFile = file; + } + + /** + * @see at.gv.egiz.pdfas.impl.input.FileBased#getFile() + */ + public File getFile() + { + return this.outputFile; + } + + + + protected OutputStream createOutputStream() + { + try + { + FileOutputStream fos = new FileOutputStream(getFile()); + return fos; + } + catch (IOException e) + { + log.error("Couldn't create OutputStream for file " + getFile() + ". Returning null.", e); + + return null; + + } + } + + /** + * @see at.gv.egiz.pdfas.framework.output.DataSink#createOutputStream(java.lang.String) + */ + public OutputStream createOutputStream(String mimeType) + { + return createOutputStream(mimeType, null); + } + + /** + * @see at.gv.egiz.pdfas.framework.output.DataSink#createOutputStream(java.lang.String, java.lang.String) + */ + public OutputStream createOutputStream(String mimeType, String characterEncoding) + { + this.mimeType = mimeType; + this.characterEncoding = characterEncoding; + + return createOutputStream(); + } + + /** + * @return the mimeType + */ + public String getMimeType() + { + return mimeType; + } + + /** + * @return the characterEncoding + */ + public String getCharacterEncoding() + { + return characterEncoding; + } + + + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/IncrementalUpdateHelper.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/IncrementalUpdateHelper.java new file mode 100644 index 0000000..53ee2db --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/IncrementalUpdateHelper.java @@ -0,0 +1,74 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.signator; + +import java.util.List; + +import at.gv.egiz.pdfas.api.timestamp.TimeStamper; +import at.gv.egiz.pdfas.framework.input.PdfDataSource; +import at.gv.egiz.pdfas.framework.output.DataSink; +import at.gv.egiz.pdfas.framework.signator.SignatorInformation; +import at.gv.egiz.pdfas.impl.output.ByteArrayDataSink; +import at.knowcenter.wag.egov.egiz.exceptions.PresentableException; +import at.knowcenter.wag.egov.egiz.pdf.BinarySignature; +import at.knowcenter.wag.egov.egiz.pdf.IncrementalUpdateInformation; +import at.knowcenter.wag.egov.egiz.pdf.PositioningInstruction; +import at.knowcenter.wag.egov.egiz.sig.SignatureObject; + +import com.lowagie.text.pdf.PdfPTable; + +/** + * @author wprinz + */ +public final class IncrementalUpdateHelper +{ + public static IncrementalUpdateInformation writeIncrementalUpdate(PdfDataSource pdfDataSource, PdfPTable pdf_table, String profile, PositioningInstruction pi, List variable_field_definitions, + List all_field_definitions, TimeStamper timeStamper, SignatorInformation si, SignatureObject so) throws PresentableException + { + return writeIncrementalUpdate(pdfDataSource, pdf_table, profile, pi, variable_field_definitions, all_field_definitions, null, null, timeStamper, si, so); + } + + public static IncrementalUpdateInformation writeIncrementalUpdate(PdfDataSource pdfDataSource, PdfPTable pdf_table, String profile, PositioningInstruction pi, List variable_field_definitions, + List all_field_definitions, List invisible_field_definitions, String invisibleKZString, TimeStamper timeStamper, SignatorInformation si, SignatureObject so) throws PresentableException + { + // PERF: binary sig needs the signed_pdf as byte array + ByteArrayDataSink bads = new ByteArrayDataSink(); + IncrementalUpdateInformation iui = BinarySignature.writeIncrementalUpdate(pdfDataSource, bads, pdf_table, profile, pi, variable_field_definitions, all_field_definitions, invisible_field_definitions, invisibleKZString, timeStamper, si, so); + iui.signed_pdf = bads.getByteArray(); + bads = null; + + return iui; + } + + public static IncrementalUpdateInformation writeIncrementalUpdateToDataSink(PdfDataSource pdfDataSource, DataSink dataSink, PdfPTable pdf_table, String profile, PositioningInstruction pi, TimeStamper timeStamper, SignatorInformation si, SignatureObject so) throws PresentableException + { + return writeIncrementalUpdateToDataSink(pdfDataSource, dataSink, pdf_table, profile, pi, null, null, null, null, timeStamper, si, so); + } + + public static IncrementalUpdateInformation writeIncrementalUpdateToDataSink(PdfDataSource pdfDataSource, DataSink dataSink, PdfPTable pdf_table, String profile, PositioningInstruction pi, List variable_field_definitions, + List all_field_definitions, List invisible_field_definitions, String invisibleKZString, TimeStamper timeStamper, SignatorInformation si, SignatureObject so) throws PresentableException + { + return BinarySignature.writeIncrementalUpdate(pdfDataSource, dataSink, pdf_table, profile, pi, variable_field_definitions, all_field_definitions, invisible_field_definitions, invisibleKZString, timeStamper, si, so); + } +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/SignatorInformationImpl.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/SignatorInformationImpl.java new file mode 100644 index 0000000..0bc3039 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/SignatorInformationImpl.java @@ -0,0 +1,40 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.signator; + +import at.knowcenter.wag.egov.egiz.sig.SignatureData; +import at.gv.egiz.pdfas.framework.signator.SignatorInformation; + +/** + * @author wprinz + */ +public abstract class SignatorInformationImpl implements SignatorInformation +{ + + /** + * @see at.gv.egiz.pdfas.framework.signator.SignatorInformation#getSignatureData() + */ + public abstract SignatureData getSignatureData(); + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/binary/BinarySignatorInformation.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/binary/BinarySignatorInformation.java new file mode 100644 index 0000000..746d8e8 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/binary/BinarySignatorInformation.java @@ -0,0 +1,104 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.signator.binary; + +import java.util.List; + +import at.knowcenter.wag.egov.egiz.pdf.ActualTablePos; +import at.knowcenter.wag.egov.egiz.sig.SignatureData; +import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject; +import at.gv.egiz.pdfas.framework.input.PdfDataSource; +import at.gv.egiz.pdfas.framework.signator.SignatorInformation; + +/** + * @author wprinz + * + */ +public class BinarySignatorInformation implements SignatorInformation +{ + protected PdfDataSource originalDocument = null; + + protected byte [] incrementalUpdateBlock = null; + + protected SignatureData signatureData = null; + + protected List replaces = null; + + protected int cert_start = -1; + protected int cert_length = -1; + + protected int timestamp_start = -1; + protected int timestamp_length = -1; + + protected int enc_start = -1; + protected int enc_length = -1; + + protected SignSignatureObject signSignatureObject = null; + + protected ActualTablePos atp = null; + + protected String signProfile = null; + + /** + * @see at.gv.egiz.pdfas.framework.signator.SignatorInformation#getSignatureData() + */ + public SignatureData getSignatureData() + { + return this.signatureData; + } + + /** + * @see at.gv.egiz.pdfas.framework.signator.SignatorInformation#setSignSignatureObject(at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject) + */ + public void setSignSignatureObject(SignSignatureObject signSignatureObject) + { + this.signSignatureObject = signSignatureObject; + } + + /** + * @see at.gv.egiz.pdfas.framework.signator.SignatorInformation#getSignSignatureObject() + */ + public SignSignatureObject getSignSignatureObject() + { + return this.signSignatureObject; + } + + /** + * @see at.gv.egiz.pdfas.framework.signator.SignatorInformation#getActualTablePos() + */ + public ActualTablePos getActualTablePos() + { + return this.atp; + } + + public List getNonTextualObjects() { + // not available for binary signature + return null; + } + + public void setNonTextualObjects(List nonTextObjects) { + // not available for binary signature + } + +} 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 new file mode 100644 index 0000000..7f18f0a --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/binary/BinarySignator_1_0_0.java @@ -0,0 +1,598 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a + * joint initiative of the Federal Chancellery Austria and Graz University of + * Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + * + * $Id: BinarySignator_1_0_0.java,v 1.1 2006/08/25 17:07:35 wprinz Exp $ + */ +package at.gv.egiz.pdfas.impl.signator.binary; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.lang.ArrayUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.pdfas.api.timestamp.TimeStamper; +import at.gv.egiz.pdfas.exceptions.ErrorCode; +import at.gv.egiz.pdfas.exceptions.framework.SignatorException; +import at.gv.egiz.pdfas.framework.input.DataSource; +import at.gv.egiz.pdfas.framework.input.PdfDataSource; +import at.gv.egiz.pdfas.framework.output.DataSink; +import at.gv.egiz.pdfas.framework.signator.Signator; +import at.gv.egiz.pdfas.framework.signator.SignatorInformation; +import at.gv.egiz.pdfas.impl.input.CompoundPdfDataSourceImpl; +import at.gv.egiz.pdfas.impl.signator.IncrementalUpdateHelper; +import at.gv.egiz.pdfas.utils.OgnlUtil; +import at.knowcenter.wag.egov.egiz.PdfAS; +import at.knowcenter.wag.egov.egiz.PdfASID; +import at.knowcenter.wag.egov.egiz.cfg.OverridePropertyHolder; +import at.knowcenter.wag.egov.egiz.cfg.SettingsReader; +import at.knowcenter.wag.egov.egiz.exceptions.NormalizeException; +import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException; +import at.knowcenter.wag.egov.egiz.exceptions.PresentableException; +import at.knowcenter.wag.egov.egiz.exceptions.SignatureException; +import at.knowcenter.wag.egov.egiz.framework.SignatorFactory; +import at.knowcenter.wag.egov.egiz.pdf.BinarySignature; +import at.knowcenter.wag.egov.egiz.pdf.IncrementalUpdateInformation; +import at.knowcenter.wag.egov.egiz.pdf.PositioningInstruction; +import at.knowcenter.wag.egov.egiz.pdf.ReplaceInfo; +import at.knowcenter.wag.egov.egiz.pdf.StringInfo; +import at.knowcenter.wag.egov.egiz.pdf.TablePos; +import at.knowcenter.wag.egov.egiz.sig.SignatureData; +import at.knowcenter.wag.egov.egiz.sig.SignatureDataImpl; +import at.knowcenter.wag.egov.egiz.sig.SignatureFieldDefinition; +import at.knowcenter.wag.egov.egiz.sig.SignatureObject; +import at.knowcenter.wag.egov.egiz.sig.SignatureTypes; +import at.knowcenter.wag.egov.egiz.sig.signatureobject.SignatureObjectHelper; +import at.knowcenter.wag.egov.egiz.tools.Normalizer; +import at.knowcenter.wag.exactparser.ByteArrayUtils; + +import com.lowagie.text.pdf.PdfPTable; + +/** + * Signs the document binary. + * + *

+ * 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 + * fields (all holes in the byte ranges) are replaced with 0. This document is + * then base64 encoded and signed. + *

+ *

+ * In finishSign, the variable fields (values, /Cert) are replaced with the + * values according to the encoding. + *

+ * + * @author wprinz + */ +public class BinarySignator_1_0_0 implements Signator { + // 04.11.2010 changed by exthex - fillReplacesWithValue no longer removes + // multiple newlines from values + + private static Log log = LogFactory.getLog(BinarySignator_1_0_0.class); + + /** + * Settings key for baik enables signatures + */ + public static final String SIG_BAIK_ENABLED = "SIG_BAIK_ENABLED"; + + /** + * The Pdf-AS ID of this Signator. + */ + public static final PdfASID MY_ID = new PdfASID(SignatorFactory.VENDOR, + SignatorFactory.TYPE_BINARY, SignatorFactory.VERSION_1_0_0); + + private Normalizer normalizer; + + /** + * @see at.knowcenter.wag.egov.egiz.framework.Signator#getMyId() + */ + public PdfASID getMyId() { + return MY_ID; + } + + /** + * Default constructor. + */ + public BinarySignator_1_0_0() { + try { + this.normalizer = new Normalizer(); + } catch (NormalizeException e) { + String msg = "Normalizer can not be initialized"; + throw new RuntimeException(msg, new SignatureException(400, msg, e)); + } + } + + /** + * @see at.gv.egiz.pdfas.framework.signator.Signator#prepareSign(PdfDataSource, + * String, TablePos, TimeStamper) + */ + public SignatorInformation prepareSign(PdfDataSource pdfDataSource, + String profile, TablePos pos, TimeStamper timeStamper) + throws SignatorException { + try { + // dferbas: has to be true everytime + boolean has_SIG_ID = true; + + String baikStr = SettingsReader.getInstance().getSetting( + "sig_obj." + profile + ".key." + SIG_BAIK_ENABLED, + "default." + SIG_BAIK_ENABLED, "false"); + boolean baikEnabled = "true".equalsIgnoreCase(baikStr); + + if (baikEnabled) { + log.debug("BAIK enabled signature"); + } + + SignatureObject signature_object = PdfAS + .createSignatureObjectFromType(profile); + signature_object.fillValues( + (char) BinarySignature.LAYOUT_PLACEHOLDER, has_SIG_ID, + baikEnabled); + + signature_object.setKZ(getMyId()); + + PdfPTable pdf_table = PdfAS + .createPdfPTableFromSignatureObject(signature_object); + + PositioningInstruction pi = PdfAS.determineTablePositioning(pos, + profile, pdfDataSource, pdf_table); + + List all_field_definitions = signature_object + .getSignatureTypeDefinition().getFieldDefinitions(); + List variable_field_definitions = new ArrayList(); + for (int i = 0; i < all_field_definitions.size(); i++) { + SignatureFieldDefinition sfd = (SignatureFieldDefinition) all_field_definitions + .get(i); + if (sfd.placeholder_length > 0) { + if (sfd.field_name.equals(SignatureTypes.SIG_ID) + && has_SIG_ID == false) { + continue; + } + + if (sfd.field_name.equals(SignatureTypes.SIG_ALG) + && baikEnabled == false) { + continue; + } + + variable_field_definitions.add(sfd); + } + } + + List all_invisible_field_definitions = signature_object + .getSignatureTypeDefinition() + .getInvisibleFieldDefinitions(); + List invisible_field_definitions = new ArrayList(); + boolean isKZInvisible = false; + String invKZString = null; + + for (int i = 0; i < all_invisible_field_definitions.size(); i++) { + SignatureFieldDefinition sfd = (SignatureFieldDefinition) all_invisible_field_definitions + .get(i); + if (sfd.field_name.equals(SignatureTypes.SIG_KZ)) { + isKZInvisible = true; + invKZString = signature_object.getKZ().toString(); + continue; + } + if (sfd.field_name.equals(SignatureTypes.SIG_ID) + && has_SIG_ID == false) { + continue; + } + + if (sfd.field_name.equals(SignatureTypes.SIG_ALG) + && baikEnabled == false) { + continue; + } + invisible_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(pdfDataSource, pdf_table, profile, + pi, variable_field_definitions, + all_field_definitions, invisible_field_definitions, + invKZString, timeStamper, null, signature_object); + + iui.invisible_field_definitions = invisible_field_definitions; + + iui.invisibleKZString = invKZString; + + String temp_string = iui.temp_ir_number + + " " + iui.temp_ir_generation + " obj"; //$NON-NLS-1$//$NON-NLS-2$ + byte[] temp_bytes = ArrayUtils.add( + temp_string.getBytes("US-ASCII"), 0, (byte) 0x0A); + int temp_start = ByteArrayUtils.lastIndexOf(iui.signed_pdf, + temp_bytes); + byte[] stream_bytes = new byte[] { '>', '>', 's', 't', 'r', 'e', + 'a', 'm', 0x0A }; + int stream_start = ByteArrayUtils.indexOf(iui.signed_pdf, + temp_start, stream_bytes); + iui.content_stream_start = stream_start + stream_bytes.length; + + // update the stream indices + Iterator it = iui.replaces.iterator(); + while (it.hasNext()) { + ReplaceInfo ri = (ReplaceInfo) it.next(); + + Iterator sit = ri.replaces.iterator(); + while (sit.hasNext()) { + StringInfo si = (StringInfo) sit.next(); + si.string_start += iui.content_stream_start; + } + } + // update KZ list indices: + if (!isKZInvisible) { + it = iui.kz_list.iterator(); + while (it.hasNext()) { + StringInfo si = (StringInfo) it.next(); + si.string_start += iui.content_stream_start; + } + } + + BinarySignature.markByteRanges(iui); + + // byte [] old_signed_pdf = iui.signed_pdf; + iui.signed_pdf = BinarySignature.prepareDataToSign(iui.signed_pdf, + iui.byte_ranges); + + BinarySignatorInformation bsi = compressIUI(iui); + return bsi; + + } catch (UnsupportedEncodingException e) { + throw new SignatorException(201, e); + } catch (PDFDocumentException e) { + throw new SignatorException(e.getErrorCode(), e); + } catch (PresentableException e) { + throw new SignatorException(201, e); + } + } + + /** + * @see at.gv.egiz.pdfas.framework.signator.Signator#finishSign(at.gv.egiz.pdfas.framework.signator.SignatorInformation, + * at.gv.egiz.pdfas.framework.output.DataSink) + */ + public void finishSign(SignatorInformation signatorInformation, + DataSink dataSink) throws SignatorException { + try { + IncrementalUpdateInformation iui = uncompressIUI((BinarySignatorInformation) signatorInformation); + + // PERF: need to keep the whole pdf in mem for processing + + // PdfAS.prefixID(iui.signed_signature_object, PdfAS.BINARY_ID); + fillReplacesWithValues(iui); + + // This is needed so that certificates are stored + try { + iui.signed_signature_object.kz = getMyId().toString(); + SignatureObjectHelper + .convertSignSignatureObjectToSignatureObject( + iui.signed_signature_object, iui.signProfile); + } catch (PresentableException e) { + throw new SignatorException(e); + } + + BinarySignature.replaceCertificate(iui); + BinarySignature.replaceTimestamp(iui); + BinarySignature.replacePlaceholders(iui); + // dferbas: alternative sign attrib creation + // PdfReader reader = new PdfReader(iui.signed_pdf); + // + // OutputStream os = + // dataSink.createOutputStream(PdfAS.PDF_MIME_TYPE); + // + // try { + // PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0', + // null, true); + // + // BinarySignature.createAdobeSigAttrib(stamper, + // signatorInformation, signatorInformation.getActualTablePos()); + // + // } catch (DocumentException e) { + // log.error("pdf error", e); + // throw new SignatorException(ErrorCode.CANNOT_WRITE_PDF, e); + // } + + OutputStream os = dataSink.createOutputStream(PdfAS.PDF_MIME_TYPE); + os.write(iui.signed_pdf); + os.close(); + } catch (PDFDocumentException e) { + throw new SignatorException(e.getErrorCode(), e); + } catch (IOException e) { + throw new SignatorException(ErrorCode.DOCUMENT_CANNOT_BE_READ, e); + } + } + + /** + * Reads the signature values from the signed signature object and fills the + * corresponding value in the Replaces array. + * + * @param iui + * The IncrementalUpdateInformation. + */ + protected void fillReplacesWithValues(final IncrementalUpdateInformation iui) { + try { + Iterator it = iui.replaces.iterator(); + HashMap ognlCtx = new HashMap(); + ognlCtx.put("iui", iui); + ognlCtx.put("sso", iui.signed_signature_object); + ognlCtx.put("issuer", iui.signed_signature_object.getIssuerDNMap()); + ognlCtx.put("subject", + iui.signed_signature_object.getSubjectDNMap()); + OgnlUtil ognl = new OgnlUtil(ognlCtx); + + OverridePropertyHolder.setOgnlUtil(ognl); + while (it.hasNext()) { + ReplaceInfo ri = (ReplaceInfo) it.next(); + String overrideVal = OverridePropertyHolder + .getProperty(ri.sfd.field_name); + if (overrideVal != null) { + ri.sfd.value = overrideVal; + ri.value = overrideVal; + } else if (ognl.containsExpression(ri.sfd.value)) { // dferbas + // evaluate expression + String res = ognl.compileMessage(ri.sfd.value); + ri.value = this.normalizer.normalize(res, true); + // Workaround added by rpiazzi + // a-trust wrongly encodes since July 2011, therefore some + // special characters (e.g. Umlaute) have + // to replaced by their right character + /*if ((ri.value.contains("ü") + || ri.value.contains("ä") + || ri.value.contains("ö") + || ri.value.contains("á") + || ri.value.contains("ß") + || ri.value.contains("Ö") + || ri.value.contains("à") + || ri.value.contains("é") + || ri.value.contains("ú") || ri.value + .contains("ç")) + && (ri.sfd.field_name + .equals(SignatureTypes.SIG_SUBJECT))) { + if (ri.value.contains("ü")) { + ri.sfd.value = ri.sfd.value.replace("ü", "�"); + ri.value = ri.value.replace("ü", "�"); + } + if (ri.value.contains("ä")) { + ri.sfd.value = ri.sfd.value.replace("ä", "�"); + ri.value = ri.value.replace("ä", "�"); + } + if (ri.value.contains("ö")) { + ri.sfd.value = ri.sfd.value.replace("ö", "�"); + ri.value = ri.value.replace("ö", "�"); + } + if (ri.value.contains("á")) { + ri.sfd.value = ri.sfd.value.replace("á", "�"); + ri.value = ri.value.replace("á", "�"); + } + if (ri.value.contains("ß")) { + ri.sfd.value = ri.sfd.value.replace("ß", "�"); + ri.value = ri.value.replace("ß", "�"); + } + if (ri.value.contains("Ö")) { + ri.sfd.value = ri.sfd.value.replace("Ö", "�"); + ri.value = ri.value.replace("Ö", "�"); + } + if (ri.value.contains("à")) { + ri.sfd.value = ri.sfd.value.replace("à", "�"); + ri.value = ri.value.replace("à", "�"); + } + if (ri.value.contains("é")) { + ri.sfd.value = ri.sfd.value.replace("é", "�"); + ri.value = ri.value.replace("é", "�"); + } + if (ri.value.contains("ú")) { + ri.sfd.value = ri.sfd.value.replace("ú", "�"); + ri.value = ri.value.replace("ú", "�"); + } + if (ri.value.contains("ç")) { + ri.sfd.value = ri.sfd.value.replace("ç", "�"); + ri.value = ri.value.replace("ç", "�"); + } + }*/ + FixHandyAnsiEncoding(ri); + // end added + } else if (overrideVal == null) { + // If SUBJECT is not overridden and and also isn't an + // expression + // check whether a set value for subject exists. + // In this case take the value from the config file. + // Added by rpiazzi to make a static signator possible + // without having + // to override it any time + if (ri.sfd.field_name.equals(SignatureTypes.SIG_SUBJECT)) { + if (ri.sfd.value.length() != 0) { + ri.value = ri.sfd.value; + } else { + ri.value = iui.signed_signature_object + .retrieveStringValue(ri.sfd.field_name); + } + } else { + ri.value = iui.signed_signature_object + .retrieveStringValue(ri.sfd.field_name); + } + } + } + } finally { + OverridePropertyHolder.removeOgnlUtil(); + } + } + + private void FixHandyAnsiEncoding(ReplaceInfo ri) { + Pattern p = Pattern.compile("&#([0-9]+);"); + Matcher m = p.matcher(ri.value); + + int value = -1; + + while (m.find()) { + value = Integer.parseInt(m.group(1)); + + if (value > 0 && value < 256) { + + log.debug("Replacing Encoding &#" + m.group(1) + ";"); + + byte[] buffer = new byte[1]; + + buffer[0] = (byte) value; + + ByteBuffer bb = ByteBuffer.wrap(buffer); + + CharBuffer cb = Charset.forName("CP1252").decode(bb); + + String str = cb.toString(); + + ri.value = ri.value.replace("&#" + m.group(1) + ";", str); + } + } + } + + /** + * Forms the SignatureData to be used for signing. + * + * @param iui + * The IncrementalUpdateInformation. + * @return Returns the SignatureData to be used for signing. + */ + protected SignatureData formSignatureData(IncrementalUpdateInformation iui) { + // String document_text = + // BinarySignature.retrieveSignableTextFromData(iui.signed_pdf, + // iui.signed_pdf.length); // signed_pdf.length); + // + // byte[] data; + // try + // { + // data = document_text.getBytes("UTF-8"); //$NON-NLS-1$ + // } + // catch (UnsupportedEncodingException e) + // { + // throw new RuntimeException("Very strange: UTF-8 character encoding + // not + // supported.", e); //$NON-NLS-1$ + // } + DataSource ds = new CompoundPdfDataSourceImpl(iui.original_document, + iui.sign_iui_block); + SignatureData signature_data = new SignatureDataImpl(ds, + PdfAS.PDF_MIME_TYPE); + + return signature_data; + } + + protected BinarySignatorInformation compressIUI( + IncrementalUpdateInformation iui) { + iui.sign_iui_block = new byte[iui.signed_pdf.length + - iui.original_document.getLength()]; + System.arraycopy(iui.signed_pdf, iui.original_document.getLength(), + iui.sign_iui_block, 0, iui.sign_iui_block.length); + + iui.signature_data = formSignatureData(iui); + + // remove the signed pdf from memory + iui.signed_pdf = null; + + BinarySignatorInformation bsi = new BinarySignatorInformation(); + bsi.originalDocument = iui.original_document; + bsi.incrementalUpdateBlock = iui.sign_iui_block; + bsi.signatureData = iui.signature_data; + bsi.replaces = iui.replaces; + bsi.cert_start = iui.cert_start; + bsi.cert_length = iui.cert_length; + bsi.enc_start = iui.enc_start; + bsi.enc_length = iui.enc_length; + bsi.atp = iui.actualTablePos; + bsi.signProfile = iui.signProfile; + bsi.timestamp_length = iui.timestamp_length; + bsi.timestamp_start = iui.timestamp_start; + + return bsi; + } + + protected IncrementalUpdateInformation uncompressIUI( + BinarySignatorInformation bsi) { + IncrementalUpdateInformation iui = new IncrementalUpdateInformation(); + + iui.original_document = bsi.originalDocument; + iui.sign_iui_block = bsi.incrementalUpdateBlock; + iui.signature_data = bsi.signatureData; + iui.replaces = bsi.replaces; + iui.cert_start = bsi.cert_start; + iui.cert_length = bsi.cert_length; + iui.enc_start = bsi.enc_start; + iui.enc_length = bsi.enc_length; + iui.actualTablePos = bsi.atp; + iui.signProfile = bsi.signProfile; + iui.timestamp_length = bsi.timestamp_length; + iui.timestamp_start = bsi.timestamp_start; + + iui.signed_signature_object = bsi.signSignatureObject; + + restoreSignedPdf(iui); + + return iui; + } + + protected void restoreSignedPdf(IncrementalUpdateInformation iui) { + iui.signed_pdf = new byte[iui.original_document.getLength() + + iui.sign_iui_block.length]; + + try { + InputStream is = iui.original_document.createInputStream(); + is.read(iui.signed_pdf, 0, iui.original_document.getLength()); + is.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + + System.arraycopy(iui.sign_iui_block, 0, iui.signed_pdf, + iui.original_document.getLength(), iui.sign_iui_block.length); + } + + public String getEncoding() { + // not used for binary signature + return "utf-8"; + + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/binary/BinarySignator_1_1_0.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/binary/BinarySignator_1_1_0.java new file mode 100644 index 0000000..acbc15e --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/binary/BinarySignator_1_1_0.java @@ -0,0 +1,77 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a + * joint initiative of the Federal Chancellery Austria and Graz University of + * Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + * + * $Id: BinarySignator_1_0_0.java,v 1.1 2006/08/25 17:07:35 wprinz Exp $ + */ +package at.gv.egiz.pdfas.impl.signator.binary; + +import at.gv.egiz.pdfas.impl.input.CompoundPdfDataSourceImpl; +import at.gv.egiz.pdfas.framework.input.DataSource; +import at.knowcenter.wag.egov.egiz.PdfAS; +import at.knowcenter.wag.egov.egiz.PdfASID; +import at.knowcenter.wag.egov.egiz.framework.SignatorFactory; +import at.knowcenter.wag.egov.egiz.pdf.IncrementalUpdateInformation; +import at.knowcenter.wag.egov.egiz.sig.SignatureData; +import at.knowcenter.wag.egov.egiz.sig.SignatureDataImpl; + +/** + * Signs the document binary. + * + *

+ * This just differs from version 1.0.0 in the fact that the signature data is + * the actual binary PDF instead of a Base64 encoding. + *

+ * + * @see BinarySignator_1_0_0 + * + * @author wprinz + */ +public class BinarySignator_1_1_0 extends BinarySignator_1_0_0 +{ + /** + * The Pdf-AS ID of this Signator. + */ + public static final PdfASID MY_ID = new PdfASID(SignatorFactory.VENDOR, SignatorFactory.TYPE_BINARY, SignatorFactory.VERSION_1_1_0); + + /** + * @see at.knowcenter.wag.egov.egiz.framework.Signator#getMyId() + */ + public PdfASID getMyId() + { + return MY_ID; + } + + /** + * Overrides the SignatureData generation of the BinarySignator 1.0.0 so that + * the SignatureData is the actual binary PDF instead of a Base64 encoding. + * + * @see BinarySignator_1_0_0#formSignatureData(IncrementalUpdateInformation) + */ + protected SignatureData formSignatureData(IncrementalUpdateInformation iui) + { + DataSource ds = new CompoundPdfDataSourceImpl(iui.original_document, iui.sign_iui_block); + SignatureData signature_data = new SignatureDataImpl(ds, PdfAS.PDF_MIME_TYPE); + + return signature_data; + } +} 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 new file mode 100644 index 0000000..7fcdb2a --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/detached/DetachedTextualSignator_1_0_0.java @@ -0,0 +1,150 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a + * joint initiative of the Federal Chancellery Austria and Graz University of + * Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + * + * $Id: TextualSignator_1_0_0.java,v 1.3 2006/10/31 08:07:50 wprinz Exp $ + */ +package at.gv.egiz.pdfas.impl.signator.detached; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; + +import at.gv.egiz.pdfas.exceptions.ErrorCode; +import at.gv.egiz.pdfas.exceptions.framework.SignatorException; +import at.gv.egiz.pdfas.framework.SignatorFactory; +import at.gv.egiz.pdfas.framework.output.DataSink; +import at.gv.egiz.pdfas.framework.signator.SignatorInformation; +import at.gv.egiz.pdfas.impl.signator.textual.TextualSignatorInformation; +import at.gv.egiz.pdfas.impl.signator.textual.TextualSignator_1_0_0; +import at.knowcenter.wag.egov.egiz.PdfASID; +import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUPostConnection; + +/** + * Signs a document textually. + * + *

+ * In prepareSign, the document text is extracted and normalized. + *

+ *

+ * In finishSign, the signed SignatureObject is transformed into a Signature + * block, which is then written as an Incremental Update. + *

+ * + * @author wprinz + */ +public class DetachedTextualSignator_1_0_0 extends TextualSignator_1_0_0 +{ + /** + * 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() + */ + public PdfASID getMyId() + { + return MY_ID; + } + + // /** + // *

+ // * The parameter has_SIG_ID is not used by this Signator because it doesn't + // * pre-format the signature block. + // *

+ // * + // * @see at.knowcenter.wag.egov.egiz.framework.Signator#prepareSign(byte[], + // * String, TablePos, boolean) + // */ + // public IncrementalUpdateInformation prepareSign(PdfDataSource pdf, + // String signature_type, TablePos pos, boolean has_SIG_ID) throws + // PresentableException + // { + // IncrementalUpdateInformation iui = new IncrementalUpdateInformation(); + // iui.original_document = pdf; + // iui.signature_type = signature_type; + // iui.pos = pos; + // + // 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$ + // + // return iui; + // } + // + // /** + // * @see + // at.knowcenter.wag.egov.egiz.framework.Signator#finishSign(at.knowcenter.wag.egov.egiz.pdf.IncrementalUpdateInformation) + // */ + // public SignResult finishSign(IncrementalUpdateInformation iui) throws + // PresentableException + // { + // try + // { + // String response = + // iui.signed_signature_object.response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY); + // byte[] response_bytes = response.getBytes("UTF-8"); //$NON-NLS-1$ + // + // SignResult sign_result = new SignResult(MIME_TYPE, response_bytes); + // return sign_result; + // } + // catch (UnsupportedEncodingException e) + // { + // e.printStackTrace(); + // throw new PDFDocumentException(300, e); + // } + // } + + /** + * @see at.gv.egiz.pdfas.impl.signator.textual.TextualSignator_1_0_0#finishSign(at.gv.egiz.pdfas.framework.signator.SignatorInformation, + * at.gv.egiz.pdfas.framework.output.DataSink) + */ + public void finishSign(SignatorInformation signatorInformation, DataSink dataSink) throws SignatorException + { + try + { + TextualSignatorInformation tsi = (TextualSignatorInformation) signatorInformation; + + String response = tsi.signSignatureObject.response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY); + + OutputStream os = dataSink.createOutputStream(MIME_TYPE, "UTF-8"); + OutputStreamWriter osw = new OutputStreamWriter(os); + osw.write(response); + osw.close(); + } + catch (IOException e) + { + throw new SignatorException(ErrorCode.SIGNATURE_COULDNT_BE_CREATED, e); + } + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/textual/TextualSignatorInformation.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/textual/TextualSignatorInformation.java new file mode 100644 index 0000000..7a4835c --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/textual/TextualSignatorInformation.java @@ -0,0 +1,96 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.signator.textual; + +import java.util.ArrayList; +import java.util.List; + +import at.knowcenter.wag.egov.egiz.pdf.ActualTablePos; +import at.knowcenter.wag.egov.egiz.pdf.TablePos; +import at.knowcenter.wag.egov.egiz.sig.SignatureData; +import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject; +import at.gv.egiz.pdfas.framework.input.PdfDataSource; +import at.gv.egiz.pdfas.framework.signator.SignatorInformation; + +/** + * @author wprinz + * + */ +public class TextualSignatorInformation implements SignatorInformation +{ + protected PdfDataSource originalDocument = null; + + protected SignatureData signatureData = null; + + protected String profile = null; + + protected TablePos pos = null; + + public SignSignatureObject signSignatureObject = null; + + protected ActualTablePos atp = null; + + protected List nonTextualObjects = new ArrayList(); + + /** + * @see at.gv.egiz.pdfas.framework.signator.SignatorInformation#getSignatureData() + */ + public SignatureData getSignatureData() + { + return this.signatureData; + } + + /** + * @see at.gv.egiz.pdfas.framework.signator.SignatorInformation#setSignSignatureObject(at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject) + */ + public void setSignSignatureObject(SignSignatureObject signSignatureObject) + { + this.signSignatureObject = signSignatureObject; + } + + /** + * @see at.gv.egiz.pdfas.framework.signator.SignatorInformation#getSignSignatureObject() + */ + public SignSignatureObject getSignSignatureObject() + { + return this.signSignatureObject; + } + + /** + * @see at.gv.egiz.pdfas.framework.signator.SignatorInformation#getActualTablePos() + */ + public ActualTablePos getActualTablePos() + { + return this.atp; + } + + public List getNonTextualObjects() { + return this.nonTextualObjects; + } + + public void setNonTextualObjects(List nonTextObjects) { + this.nonTextualObjects = nonTextObjects; + + } +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/textual/TextualSignator_1_0_0.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/textual/TextualSignator_1_0_0.java new file mode 100644 index 0000000..d0793d6 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/textual/TextualSignator_1_0_0.java @@ -0,0 +1,212 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a + * joint initiative of the Federal Chancellery Austria and Graz University of + * Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + * + * $Id: TextualSignator_1_0_0.java,v 1.3 2006/10/31 08:07:50 wprinz Exp $ + */ +package at.gv.egiz.pdfas.impl.signator.textual; + +import java.util.HashMap; +import java.util.Iterator; + +import at.gv.egiz.pdfas.api.timestamp.TimeStamper; +import at.gv.egiz.pdfas.exceptions.ErrorCode; +import at.gv.egiz.pdfas.exceptions.framework.SignatorException; +import at.gv.egiz.pdfas.framework.input.DataSource; +import at.gv.egiz.pdfas.framework.input.PdfDataSource; +import at.gv.egiz.pdfas.framework.output.DataSink; +import at.gv.egiz.pdfas.framework.signator.Signator; +import at.gv.egiz.pdfas.framework.signator.SignatorInformation; +import at.gv.egiz.pdfas.impl.input.TextDataSourceImpl; +import at.gv.egiz.pdfas.impl.signator.IncrementalUpdateHelper; +import at.gv.egiz.pdfas.utils.OgnlUtil; +import at.knowcenter.wag.egov.egiz.PdfAS; +import at.knowcenter.wag.egov.egiz.PdfASID; +import at.knowcenter.wag.egov.egiz.cfg.OverridePropertyHolder; +import at.knowcenter.wag.egov.egiz.exceptions.PresentableException; +import at.knowcenter.wag.egov.egiz.framework.SignatorFactory; +import at.knowcenter.wag.egov.egiz.pdf.IncrementalUpdateInformation; +import at.knowcenter.wag.egov.egiz.pdf.ObjectExtractor; +import at.knowcenter.wag.egov.egiz.pdf.PositioningInstruction; +import at.knowcenter.wag.egov.egiz.pdf.TablePos; +import at.knowcenter.wag.egov.egiz.sig.SignatureDataImpl; +import at.knowcenter.wag.egov.egiz.sig.SignatureEntry; +import at.knowcenter.wag.egov.egiz.sig.SignatureObject; +import at.knowcenter.wag.egov.egiz.sig.SignatureTypeDefinition; +import at.knowcenter.wag.egov.egiz.sig.SignatureTypes; +import at.knowcenter.wag.egov.egiz.sig.signatureobject.SignatureObjectHelper; + +import com.lowagie.text.pdf.PdfPTable; + +/** + * Signs a document textually. + * + *

+ * In prepareSign, the document text is extracted and normalized. + *

+ *

+ * In finishSign, the signed SignatureObject is transformed into a Signature + * block, which is then written as an Incremental Update. + *

+ * + * @author wprinz + */ +public class TextualSignator_1_0_0 implements Signator +{ + /** + * The Pdf-AS ID of this Signator. + */ + public static final PdfASID MY_ID = new PdfASID(SignatorFactory.VENDOR, SignatorFactory.TYPE_TEXTUAL, SignatorFactory.VERSION_1_0_0); + + /** + * @see at.knowcenter.wag.egov.egiz.framework.Signator#getMyId() + */ + public PdfASID getMyId() + { + return MY_ID; + } + + /** + * Default constructor. + */ + public TextualSignator_1_0_0() + { + // Default constructor. + } + + /** + *

+ * The parameter has_SIG_ID is not used by this Signator because it doesn't + * pre-format the signature block. + *

+ * + * @see at.gv.egiz.pdfas.framework.signator.Signator#prepareSign(at.gv.egiz.pdfas.framework.input.PdfDataSource, + * java.lang.String, at.knowcenter.wag.egov.egiz.pdf.TablePos, boolean) + */ + public SignatorInformation prepareSign(PdfDataSource pdfDataSource, String profile, TablePos pos, TimeStamper timestamper) throws SignatorException + { + try + { + + SignatureTypeDefinition std = SignatureTypes.getInstance().getSignatureTypeDefinition(profile); + if (!std.isTextExtractable()) + { + throw new SignatorException(ErrorCode.PROFILE_NOT_USABLE_FOR_TEXT, "The signature profile " + profile + " is not text extractable and thereby cannot be used for textual signature."); + } + + TextualSignatorInformation tsi = new TextualSignatorInformation(); + tsi.originalDocument = pdfDataSource; + tsi.profile = profile; + tsi.pos = pos; + + String document_text = PdfAS.extractNormalizedTextTextual(pdfDataSource, this.getEncoding()); + tsi.setNonTextualObjects(ObjectExtractor.extractNonTextInfo(pdfDataSource)); + // logger_.debug("signed_text = " + document_text); + + DataSource ds = new TextDataSourceImpl(document_text); + tsi.signatureData = new SignatureDataImpl(ds, "text/plain", "UTF-8"); + + return tsi; + } + catch (PresentableException pe) + { + throw new SignatorException(pe); + } + } + + /** + * @see at.gv.egiz.pdfas.framework.signator.Signator#finishSign(at.gv.egiz.pdfas.framework.signator.SignatorInformation, + * at.gv.egiz.pdfas.framework.output.DataSink) + */ + public void finishSign(SignatorInformation signatorInformation, DataSink dataSink) throws SignatorException + { + try + { + TextualSignatorInformation tsi = (TextualSignatorInformation) signatorInformation; + + // PdfAS.prefixID(iui.signed_signature_object, PdfAS.TEXT_ID); + + // iui.signed_signature_object.kz = getMyId().toString(); + tsi.signSignatureObject.kz = getMyId().toString(); + // TODO what is this for? + + SignatureObject so = SignatureObjectHelper.convertSignSignatureObjectToSignatureObject(tsi.signSignatureObject, tsi.profile); + + evaluteOgnl(so, tsi); + + PdfPTable pdf_table = PdfAS.createPdfPTableFromSignatureObject(so); + + PositioningInstruction pi = PdfAS.determineTablePositioning(tsi.pos, tsi.profile, tsi.originalDocument, pdf_table); + + IncrementalUpdateInformation iui = IncrementalUpdateHelper.writeIncrementalUpdateToDataSink(tsi.originalDocument, dataSink, pdf_table, tsi.profile, pi, null, signatorInformation, so); + tsi.atp = iui.actualTablePos; + +// OutputStream os = dataSink.createOutputStream(PdfAS.PDF_MIME_TYPE); +// os.write(signed_iui.signed_pdf); +// os.close(); + +// SignResult sign_result = new SignResult(PdfAS.PDF_MIME_TYPE, signed_iui.signed_pdf); +// return sign_result; + } + catch (PresentableException pe) + { + throw new SignatorException(pe); + } + finally { + OverridePropertyHolder.removeOgnlUtil(); + } +// catch (IOException e) +// { +// throw new SignatorException(ErrorCode.DOCUMENT_CANNOT_BE_READ, e); +// } + } + + private void evaluteOgnl(SignatureObject so, TextualSignatorInformation tsi) { + HashMap ognlCtx = new HashMap(); + //ognlCtx.put("iui", tsi.); + ognlCtx.put("sso", tsi.signSignatureObject); + ognlCtx.put("issuer", tsi.signSignatureObject.getIssuerDNMap()); + ognlCtx.put("subject", tsi.signSignatureObject.getSubjectDNMap()); + OgnlUtil ognl = new OgnlUtil(ognlCtx); + OverridePropertyHolder.setOgnlUtil(ognl); + + Iterator it = so.getSigEntries().values().iterator(); + while (it.hasNext()) + { + SignatureEntry se = (SignatureEntry) it.next(); + + if (ognl.containsExpression(se.getValue())) { + // evaluate expression + String res = ognl.compileMessage(se.getValue()); + se.setValue(res); + //ri.value = this.normalizer.normalize(res, true); + + } + } + } + + public String getEncoding() { + // old signatures used this encoding implicit most of the time (windows default) + return "cp1252"; + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/textual/TextualSignator_1_1_0.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/textual/TextualSignator_1_1_0.java new file mode 100644 index 0000000..fde9ae0 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/textual/TextualSignator_1_1_0.java @@ -0,0 +1,53 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a + * joint initiative of the Federal Chancellery Austria and Graz University of + * Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + * + * $Id: TextualSignator_1_0_0.java,v 1.3 2006/10/31 08:07:50 wprinz Exp $ + */ +package at.gv.egiz.pdfas.impl.signator.textual; + +import at.knowcenter.wag.egov.egiz.PdfASID; +import at.knowcenter.wag.egov.egiz.framework.SignatorFactory; + +/** + * Signs a document textually. + * + * @see TextualSignator_1_0_0 + * + * @author wprinz + */ +public class TextualSignator_1_1_0 extends TextualSignator_1_0_0 +{ + /** + * The Pdf-AS ID of this Signator. + */ + public static final PdfASID MY_ID = new PdfASID(SignatorFactory.VENDOR, SignatorFactory.TYPE_TEXTUAL, SignatorFactory.VERSION_1_1_0); + + /** + * @see at.knowcenter.wag.egov.egiz.framework.Signator#getMyId() + */ + public PdfASID getMyId() + { + return MY_ID; + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/textual/TextualSignator_1_2_0.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/textual/TextualSignator_1_2_0.java new file mode 100644 index 0000000..3d0d200 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/textual/TextualSignator_1_2_0.java @@ -0,0 +1,53 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.signator.textual; + +import at.knowcenter.wag.egov.egiz.PdfASID; +import at.knowcenter.wag.egov.egiz.framework.SignatorFactory; + +/** + * + * @author dferbas + * + */ +public class TextualSignator_1_2_0 extends TextualSignator_1_1_0 { + /** + * The Pdf-AS ID of this Signator. + */ + public static final PdfASID MY_ID = new PdfASID(SignatorFactory.VENDOR, SignatorFactory.TYPE_TEXTUAL, SignatorFactory.VERSION_1_2_0); + + /** + * @see at.knowcenter.wag.egov.egiz.framework.Signator#getMyId() + */ + public PdfASID getMyId() + { + return MY_ID; + } + + public String getEncoding() { + // nail encoding to utf8 from this version on + return "utf8"; + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/verificator/binary/BinaryVerificator_1_0_0.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/verificator/binary/BinaryVerificator_1_0_0.java new file mode 100644 index 0000000..9d67f0b --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/verificator/binary/BinaryVerificator_1_0_0.java @@ -0,0 +1,453 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a + * joint initiative of the Federal Chancellery Austria and Graz University of + * Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + * + * $Id: BinaryVerificator_1_0_0.java,v 1.3 2006/10/11 08:03:22 wprinz Exp $ + */ +package at.gv.egiz.pdfas.impl.verificator.binary; + +import java.io.ByteArrayOutputStream; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.log4j.Logger; + +import at.gv.egiz.pdfas.exceptions.ErrorCode; +import at.gv.egiz.pdfas.framework.input.PdfDataSource; +import at.gv.egiz.pdfas.framework.verificator.Verificator; +import at.gv.egiz.pdfas.impl.input.CompoundPdfDataSourceImpl; +import at.gv.egiz.pdfas.impl.input.DelimitedPdfDataSource; +import at.gv.egiz.pdfas.impl.vfilter.helper.VerificationFilterBinaryHelper; +import at.knowcenter.wag.egov.egiz.PdfASID; +import at.knowcenter.wag.egov.egiz.cfg.ConfigLogger; +import at.knowcenter.wag.egov.egiz.cfg.SettingsReader; +import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException; +import at.knowcenter.wag.egov.egiz.exceptions.PresentableException; +import at.knowcenter.wag.egov.egiz.framework.SignatorFactory; +import at.knowcenter.wag.egov.egiz.framework.VerificationFilter; +import at.knowcenter.wag.egov.egiz.pdf.BinaryBlockInfo; +import at.knowcenter.wag.egov.egiz.pdf.BinarySignature; +import at.knowcenter.wag.egov.egiz.pdf.BinarySignatureHolder; +import at.knowcenter.wag.egov.egiz.pdf.Placeholder; +import at.knowcenter.wag.egov.egiz.pdf.ReplaceInfo; +import at.knowcenter.wag.egov.egiz.pdf.StringInfo; +import at.knowcenter.wag.egov.egiz.sig.SignatureObject; +import at.knowcenter.wag.egov.egiz.sig.SignatureTypes; +import at.knowcenter.wag.exactparser.parsing.IndirectObjectReference; +import at.knowcenter.wag.exactparser.parsing.PDFUtils; +import at.knowcenter.wag.exactparser.parsing.results.ArrayParseResult; +import at.knowcenter.wag.exactparser.parsing.results.DictionaryParseResult; +import at.knowcenter.wag.exactparser.parsing.results.FooterParseResult; +import at.knowcenter.wag.exactparser.parsing.results.IndirectObjectReferenceParseResult; +import at.knowcenter.wag.exactparser.parsing.results.LiteralStringParseResult; +import at.knowcenter.wag.exactparser.parsing.results.NameParseResult; +import at.knowcenter.wag.exactparser.parsing.results.NumberParseResult; +import at.knowcenter.wag.exactparser.parsing.results.ObjectParseResult; +import at.knowcenter.wag.exactparser.parsing.results.ParseResult; + +/** + * The BinaryVerificator parses the EGIT Dictionary and extracts the signature + * holder from it. + * + * @author wprinz + */ +public class BinaryVerificator_1_0_0 implements Verificator +{ + /** + * The Pdf-AS ID of this Verificator. + */ + public static final PdfASID MY_ID = new PdfASID(SignatorFactory.VENDOR, SignatorFactory.TYPE_BINARY, SignatorFactory.VERSION_1_0_0); + + /** + * Use this to override the MY_ID field. + * + * @return Returns the Id of this Verificator. + */ + protected PdfASID getMyId() + { + return MY_ID; + } + + /** + * The /ODS key in the EGIZ Dict. + */ + public static final byte[] EGIZ_ODS_NAME = new byte[] { 'O', 'D', 'S' }; + + /** + * The /ID key in the EGIZ Dict. + */ + public static final byte[] EGIZ_KZ_NAME = VerificationFilter.EGIZ_KZ_NAME; + + /** + * The /ByteRange key in the EGIZ Dict. + */ + public static final byte[] EGIZ_BYTE_RANGE_NAME = new byte[] { 'B', 'y', 't', 'e', 'R', 'a', 'n', 'g', 'e' }; + + /** + * The /replaces key in the EGIZ Dict. + */ + public static final byte[] EGIZ_REPLACES_NAME = new byte[] { 'r', 'e', 'p', 'l', 'a', 'c', 'e', 's' }; + + /** + * The /encodings key in the EGIZ Dict. + */ + public static final byte[] EGIZ_ENCODINGS_NAME = new byte[] { 'e', 'n', 'c', 'o', 'd', 'i', 'n', 'g', 's' }; + + /** + * The /Cert key in the EGIZ Dict. + */ + public static final byte[] EGIZ_CERT_NAME = new byte[] { 'C', 'e', 'r', 't' }; + + /** + * The /TimeStamp key in the EGIZ Dict. + */ + public static final byte[] EGIZ_TIMESTAMP_NAME = new byte[] { 'T', 'i', 'm', 'e', 'S', 't', 'a', 'm', 'p' }; + + + /** + * The logger definition. + */ + private static final Logger logger_ = ConfigLogger.getLogger(BinaryVerificator_1_0_0.class); + + /** + * Default constructor. + */ + public BinaryVerificator_1_0_0() + { + // Default constructor. + } + + /** + * @see at.gv.egiz.pdfas.framework.verificator.Verificator#parseBlock(at.gv.egiz.pdfas.framework.input.PdfDataSource, + * byte[], + * at.knowcenter.wag.exactparser.parsing.results.FooterParseResult, int) + */ + public List parseBlock(PdfDataSource pdfDataSource, byte [] pdf, FooterParseResult block, int start_of_whole_block) throws PresentableException + { + // PERF: BinaryVerificator needs byte array. + + int egiz_index = PDFUtils.indexOfName(pdf, block.tpr.dpr.names, VerificationFilter.EGIZ_DICT_NAME); + if (egiz_index < 0) + { + throw new PDFDocumentException(ErrorCode.COULDNT_VERIFY, "egiz_index = " + egiz_index); + } + + IndirectObjectReferenceParseResult egiz_dict_iorpr = (IndirectObjectReferenceParseResult) block.tpr.dpr.values.get(egiz_index); + + IndirectObjectReference ior = egiz_dict_iorpr.ior; + + final int egiz_dict_offset = PDFUtils.getObjectOffsetFromXRefByIndirectObjectReference(block.xpr, ior); + + ObjectParseResult obj = PDFUtils.parseObject(pdf, egiz_dict_offset); + DictionaryParseResult egiz_dict = (DictionaryParseResult) obj.object; + + NumberParseResult ods_npr = (NumberParseResult) getRequiredValueOfKey(pdf, egiz_dict, EGIZ_ODS_NAME); + + ArrayParseResult kz_apr = (ArrayParseResult) getRequiredValueOfKey(pdf, egiz_dict, EGIZ_KZ_NAME); + PdfASID kz = null; +// String kz_string = VerificationFilter.restoreKZ(pdf, kz_apr); + String kz_string = VerificationFilterBinaryHelper.restoreKZ(pdf, kz_apr); // dferbas hack baik test + // TODO baik hack kz_string = "urn:pdfsigfilter:bka.gv.at:binaer:v1.0.0"; + kz = new PdfASID(kz_string); + if (!kz_string.equals(getMyId().toString())) + { + logger_.warn("Warning: Kennzeichnung not recognized:" + kz_string); + } + + ArrayParseResult byte_ranges_apr = (ArrayParseResult) getRequiredValueOfKey(pdf, egiz_dict, EGIZ_BYTE_RANGE_NAME); + + ArrayParseResult replaces_apr = (ArrayParseResult) getRequiredValueOfKey(pdf, egiz_dict, EGIZ_REPLACES_NAME); + + ArrayParseResult encodings_apr = (ArrayParseResult) getRequiredValueOfKey(pdf, egiz_dict, EGIZ_ENCODINGS_NAME); + + ArrayParseResult cert_apr = (ArrayParseResult) getValueOfKey(pdf, egiz_dict, EGIZ_CERT_NAME); + byte[] cert = null; + if (cert_apr != null && !cert_apr.elements.isEmpty()) + { + LiteralStringParseResult lspr = (LiteralStringParseResult) cert_apr.elements.get(0); + int str_length = lspr.content_end_index - lspr.content_start_index; + byte[] encoded = new byte[str_length]; + System.arraycopy(pdf, lspr.content_start_index, encoded, 0, encoded.length); + + cert = Placeholder.unescapePDFString(encoded); + } + + //timestamp + ArrayParseResult timestamp_apr = (ArrayParseResult) getValueOfKey(pdf, egiz_dict, EGIZ_TIMESTAMP_NAME); + byte[] timestamp = null; + if (timestamp_apr != null) { + logger_.debug("found /TimeStamp in egiz dict. Extracting..."); + + if (timestamp_apr != null && !timestamp_apr.elements.isEmpty()) + { + LiteralStringParseResult lspr = (LiteralStringParseResult) timestamp_apr.elements.get(0); + int str_length = lspr.content_end_index - lspr.content_start_index; + byte[] encoded = new byte[str_length]; + System.arraycopy(pdf, lspr.content_start_index, encoded, 0, encoded.length); + + timestamp = Placeholder.unescapePDFString(encoded); + + } + } + + + int num_byte_ranges = byte_ranges_apr.elements.size() / 2; + List byte_ranges = new ArrayList(); + for (int i = 0; i < num_byte_ranges; i++) + { + NumberParseResult start_npr = (NumberParseResult) byte_ranges_apr.elements.get(2 * i); + NumberParseResult length_npr = (NumberParseResult) byte_ranges_apr.elements.get(2 * i + 1); + + StringInfo si = new StringInfo(); + si.string_start = start_npr.number; + si.string_length = length_npr.number; + byte_ranges.add(si); + } + + StringInfo sis[] = new StringInfo[num_byte_ranges - 1]; + for (int i = 0; i < num_byte_ranges - 1; i++) + { + StringInfo prev = (StringInfo) byte_ranges.get(i); + StringInfo next = (StringInfo) byte_ranges.get(i + 1); + + StringInfo hole = new StringInfo(); + hole.string_start = prev.string_start + prev.string_length; + hole.string_length = next.string_start - hole.string_start; + + sis[i] = hole; + } + + int n = replaces_apr.elements.size(); + byte[][] brevs = new byte[n][]; + for (int i = 0; i < n; i++) + { + NameParseResult lspr = (NameParseResult) replaces_apr.elements.get(i); + + byte[] brev = new byte[3]; + System.arraycopy(pdf, lspr.name_start_index, brev, 0, brev.length); + + brevs[i] = brev; // SignatureTypes.convertBrevToType(brev); + } + + n = encodings_apr.elements.size(); + byte[][] encodings = new byte[n][]; + for (int i = 0; i < n; i++) + { + NameParseResult lspr = (NameParseResult) encodings_apr.elements.get(i); + + byte[] enc = new byte[3]; + System.arraycopy(pdf, lspr.name_start_index, enc, 0, enc.length); + encodings[i] = enc; + } + + BinaryBlockInfo bbi = new BinaryBlockInfo(); + bbi.replaces = BinarySignature.reconstructReplaces(pdf, brevs, sis, encodings); + bbi.signed_size = ods_npr.number; + + // BinaryBlockInfo bbi = BinarySignature.retrieveEgizDictInformation(pdf, + // ior.object_number, ior.generation_number, egiz_dict_offset); + + // byte[] original_pdf = BinarySignature.restoreEgizDictInformation(pdf, + // bbi); + + byte[] signed_pdf = BinarySignature.prepareDataToSign(pdf, byte_ranges); + // String signed_text = + // BinarySignature.retrieveSignableTextFromData(signed_pdf, + // signed_pdf.length); // has been moved into the BinarySignatureHolder + + SignatureObject signature_object = new SignatureObject(); + String default_type = SettingsReader.getInstance().getValueFromKey(SignatureTypes.DEFAULT_TYPE); + signature_object.setSigType(default_type); + signature_object.initByType(); + + signature_object.setKZ(kz); + + if (timestamp != null) { + String ts = new String(trimZeroBytes(timestamp)); + signature_object.setTimeStamp(ts); + if (logger_.isDebugEnabled()) { + logger_.debug("extracted timestamp " + ts); + } + } + + if (cert != null) + { + try + { + // ByteArrayInputStream bais = new ByteArrayInputStream(cert); + // CertificateFactory cf = CertificateFactory.getInstance("X.509"); + // X509Certificate certificate = (X509Certificate) + // cf.generateCertificate(bais); + + // trim zero bytes. - the base 64 cert must not have zero bytes. + byte[] b64 = trimZeroBytes(cert); + + signature_object.storeNewCertificateInLocalStore(b64); + } + catch (Exception e) + { + logger_.error(e.getMessage(), e); + } + + } + + Iterator rit = bbi.replaces.iterator(); + while (rit.hasNext()) + { + ReplaceInfo ri = (ReplaceInfo) rit.next(); + + String type = SignatureTypes.convertBrevToType(ri.brev); + + if (type == null) { + throw new PresentableException(ErrorCode.UNSUPPORTED_REPLACES_NAME, "Unsupported /replaces name."); + } + + // signature_object.setSigValue(ri.type, ri.value); + if (type.equals(SignatureTypes.SIG_DATE)) + { + signature_object.setSignationDate(ri.value); + continue; + } + + if (type.equals(SignatureTypes.SIG_ISSUER)) + { + signature_object.setSignationIssuer(ri.value); + continue; + } + + if (type.equals(SignatureTypes.SIG_VALUE)) + { + signature_object.setSignationValue(ri.value); + continue; + } + + if (type.equals(SignatureTypes.SIG_NUMBER)) + { + signature_object.setSignationSerialNumber(ri.value); + continue; + } + + if (type.equals(SignatureTypes.SIG_ID)) + { + signature_object.setSignationIDs(ri.value); + continue; + } + + if (type.equals(SignatureTypes.SIG_ALG)) + { + signature_object.setSigAlg(ri.value); + continue; + } + } + + int iu_length = signed_pdf.length - start_of_whole_block; + byte [] iu_block = new byte [iu_length]; + System.arraycopy(signed_pdf, start_of_whole_block, iu_block, 0, iu_length); + + DelimitedPdfDataSource dpds = new DelimitedPdfDataSource(pdfDataSource, start_of_whole_block); + PdfDataSource ds = new CompoundPdfDataSourceImpl(dpds, iu_block); + + //PdfDataSource dsByteArray = new ByteArrayPdfDataSourceImpl(signed_pdf, signed_pdf.length); + + BinarySignatureHolder signature_holder = new BinarySignatureHolder(ds, signature_object); + + List holders = new ArrayList(); + holders.add(signature_holder); + return holders; + } + + private byte[] trimZeroBytes(byte[] arr) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + for (int i = 0; i < arr.length; i++) + { + if (arr[i] != 0) + { + baos.write(arr[i]); + } + } + byte[] b64 = baos.toByteArray(); + return b64; + } + + /** + * Retrieves the value of the key from the dictionary. + * + * @param pdf + * The PDF. + * @param egiz_dict + * The dictionary. + * @param name + * The name of the key. + * @return Returns the value of the key. An exception is thrown if the key + * doesn't exist. + * @throws PDFDocumentException + * Thrown, if the key doesn't exist in the dictionary. + */ + protected ParseResult getRequiredValueOfKey(byte[] pdf, DictionaryParseResult egiz_dict, byte[] name) throws PDFDocumentException + { + final int index = PDFUtils.indexOfName(pdf, egiz_dict.names, name); + checkIndex(index); + ParseResult value = (ParseResult) egiz_dict.values.get(index); + return value; + } + + /** + * Throws an excaption, if the index is lower than 0. + * + * @param name_index + * The index. + * @throws PDFDocumentException + * Thrown, if the index is lower than 0. + */ + protected void checkIndex(int name_index) throws PDFDocumentException + { + if (name_index < 0) + { + throw new PDFDocumentException(ErrorCode.COULDNT_VERIFY, "The name wasn't found in the egiz dict."); + } + } + + /** + * Retrieves the value of the key from the dictionary. + * + * @param pdf + * The PDF. + * @param egiz_dict + * The dictionary. + * @param name + * The name of the key. + * @return Returns the key's value, or null if the dictionary didn't contain + * that key. + */ + protected ParseResult getValueOfKey(byte[] pdf, DictionaryParseResult egiz_dict, byte[] name) + { + final int index = PDFUtils.indexOfName(pdf, egiz_dict.names, name); + if (index < 0) + { + return null; + } + ParseResult value = (ParseResult) egiz_dict.values.get(index); + return value; + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/verificator/binary/BinaryVerificator_1_1_0.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/verificator/binary/BinaryVerificator_1_1_0.java new file mode 100644 index 0000000..ae18408 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/verificator/binary/BinaryVerificator_1_1_0.java @@ -0,0 +1,44 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.verificator.binary; + +import at.knowcenter.wag.egov.egiz.PdfASID; +import at.knowcenter.wag.egov.egiz.framework.SignatorFactory; + +/** + * @author wprinz + * + */ +public class BinaryVerificator_1_1_0 extends BinaryVerificator_1_0_0 +{ + public static final PdfASID MY_ID = new PdfASID(SignatorFactory.VENDOR, SignatorFactory.TYPE_BINARY, SignatorFactory.VERSION_1_1_0); + + /** + * @see at.knowcenter.wag.egov.egiz.framework.verificators.BinaryVerificator_1_0_0#getMyId() + */ + protected PdfASID getMyId() + { + return MY_ID; + } +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/Partition.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/Partition.java new file mode 100644 index 0000000..f4e91bd --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/Partition.java @@ -0,0 +1,29 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.vfilter; + +public interface Partition +{ + public boolean isTextPartition(); +} 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 new file mode 100644 index 0000000..3f0f482 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/VerificationFilterImpl.java @@ -0,0 +1,964 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.vfilter; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import org.apache.commons.lang.time.StopWatch; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.pdfas.exceptions.ErrorCode; +import at.gv.egiz.pdfas.exceptions.framework.VerificationFilterException; +import at.gv.egiz.pdfas.framework.SignatureHolderHelper; +import at.gv.egiz.pdfas.framework.VerificatorFactory; +import at.gv.egiz.pdfas.framework.input.PdfDataSource; +import at.gv.egiz.pdfas.framework.input.TextDataSource; +import at.gv.egiz.pdfas.framework.verificator.Verificator; +import at.gv.egiz.pdfas.framework.vfilter.VerificationFilter; +import at.gv.egiz.pdfas.framework.vfilter.VerificationFilterParameters; +import at.gv.egiz.pdfas.impl.input.DelimitedPdfDataSource; +import at.gv.egiz.pdfas.impl.input.helper.DataSourceHelper; +import at.gv.egiz.pdfas.impl.vfilter.helper.VerificationFilterBinaryHelper; +import at.gv.egiz.pdfas.impl.vfilter.helper.VerificationFilterHelper; +import at.gv.egiz.pdfas.impl.vfilter.partition.BinaryPartition; +import at.gv.egiz.pdfas.impl.vfilter.partition.TextPartition; +import at.knowcenter.wag.egov.egiz.PdfAS; +import at.knowcenter.wag.egov.egiz.PdfASID; +import at.knowcenter.wag.egov.egiz.cfg.SettingsReader; +import at.knowcenter.wag.egov.egiz.exceptions.NormalizeException; +import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException; +import at.knowcenter.wag.egov.egiz.exceptions.PresentableException; +import at.knowcenter.wag.egov.egiz.exceptions.SettingsException; +import at.knowcenter.wag.egov.egiz.exceptions.SignatureException; +import at.knowcenter.wag.egov.egiz.exceptions.SignatureTypesException; +import at.knowcenter.wag.egov.egiz.pdf.AbsoluteTextSignature; +import at.knowcenter.wag.egov.egiz.pdf.EGIZDate; +import at.knowcenter.wag.egov.egiz.pdf.NoSignatureHolder; +import at.knowcenter.wag.egov.egiz.pdf.SignatureHolder; +import at.knowcenter.wag.egov.egiz.pdf.TextualSignatureHolder; +import at.knowcenter.wag.exactparser.parsing.results.FooterParseResult; + +/** + * @author wprinz + */ +public class VerificationFilterImpl implements VerificationFilter +{ + + /** + * The log. + */ + private static final Log log = LogFactory.getLog(VerificationFilterImpl.class); + + + public static final String CHECK_DOCUMENT = "check_document"; + 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, + * at.gv.egiz.pdfas.framework.vfilter.VerificationFilterParameters) + */ + public List extractSignatureHolders(final PdfDataSource pdf, List blocks, final VerificationFilterParameters parameters) throws VerificationFilterException + { + log.trace("extractSignaturHolders:"); + StopWatch sw = new StopWatch(); + sw.start(); + + if (log.isDebugEnabled()) + { + log.debug("Original IU blocks: " + blocks.size()); + debugIUBlocks(blocks); + } + + unrollLinearization(blocks); + + if (log.isDebugEnabled()) + { + log.debug("IU blocks without linearization: " + blocks.size()); + debugIUBlocks(blocks); + } + + + SettingsReader settings; + try { + settings = SettingsReader.getInstance(); + } catch (SettingsException e) { + throw new VerificationFilterException(e); + } + String check_doc = settings.getSetting(CHECK_DOCUMENT, "false"); + + // check document for textual sigs here here if binary_only is set + if ("true".equalsIgnoreCase(check_doc) && + parameters.extractBinarySignaturesOnly()) { + + checkBinaryOnly(pdf, parameters.scanForOldSignatures()); + log.debug("checkDocument: " + sw.getTime() + "ms."); + } else { + log.debug("Skipping checkDocument for textual sigs."); + } + // end add + + List signatureHolderChain = null; + + if (parameters.extractBinarySignaturesOnly()) + { + log.debug("Extracting only binary signatures. Binary-only mode."); + + signatureHolderChain = performBinaryOnly(pdf, blocks); + } + else + { + List partitions = VerificationFilterHelper.partition(pdf, blocks); + if (log.isDebugEnabled()) + { + debugPartitions(partitions); + } + + if (parameters.assumeOnlySignatureUpdateBlocks()) + { + log.debug("Assuming that there are only signature Incremental Update blocks. Semi-conservative mode."); + + signatureHolderChain = performSemiConservative(pdf, parameters.scanForOldSignatures(), blocks, partitions); + } + else + { + log.debug("Scanning complete document. Conservative mode."); + + signatureHolderChain = performFullConservative(pdf, parameters.scanForOldSignatures(), blocks, partitions); + } + + } + + log.trace("extractSignaturHolders finished (" + (signatureHolderChain != null ? signatureHolderChain.size() : 0) + " elements)."); + sw.stop(); + log.debug("extractSignatureHolders: " + sw.getTime() + "ms."); + + return signatureHolderChain; + } + + /** + * @see at.gv.egiz.pdfas.framework.vfilter.VerificationFilter#extractSignaturHolders(at.gv.egiz.pdfas.framework.input.TextDataSource, + * at.gv.egiz.pdfas.framework.vfilter.VerificationFilterParameters) + */ + public List extractSignaturHolders(TextDataSource text, VerificationFilterParameters parameters) throws VerificationFilterException + { + if (parameters.extractBinarySignaturesOnly()) + { + log + .warn("A free text signature extraction was issued although the VerificationFilter was configured to detect only binary signatures (binary-only mode). The result is of course that no signatures can be found."); + + return new ArrayList(); + } + + String freetext = text.getText(); + String normalizedText = normalizeText(freetext); + + List foundSignatures = null; + if (parameters.scanForOldSignatures()) + { + log.debug("Extracting old and new signatures from text."); + + foundSignatures = extractNewAndOldSignaturesFromText(normalizedText); + } + else + { + log.debug("Extracting new signatures from text (not extracting old ones)."); + + foundSignatures = extractNewSignaturesFromText(normalizedText); + } + + List textOnlySignatures = filterOutBinarySignatures(foundSignatures); + + return textOnlySignatures; + } + + protected String normalizeText(String freetext) throws VerificationFilterException + { + try + { + return PdfAS.normalizeText(freetext); + } + catch (NormalizeException e) + { + throw new VerificationFilterException(e); + } + } + + /** + * Removes the linearization footer from the list of update blocks. + * + * @param blocks + * The list of FooterParseResult objects in \prev order. + */ + protected void unrollLinearization(List blocks) + { + int linearization_index = -1; + for (int i = 0; i < blocks.size(); i++) + { + FooterParseResult bpr = (FooterParseResult) blocks.get(i); + + if (bpr.sxpr.xref_index == 0) + { + if (linearization_index >= 0) + { + throw new RuntimeException("There is more than one linearization block! index = " + i); + } + linearization_index = i; + } + } + + if (linearization_index >= 0) + { +// logger_.debug("The document is linearized - unrolling +// linearization block " + linearization_index); + blocks.remove(linearization_index); + } + } + + protected List performBinaryOnly(PdfDataSource pdf, List blocks) throws VerificationFilterException + { + return extractBinarySignaturesOnly(pdf, blocks); + } + + protected List performSemiConservative(PdfDataSource pdf, boolean scanForOldSignatures, List blocks, List partitions) throws VerificationFilterException + { + log.debug("perform semiConservative()..."); + List binarySignatures = extractBinarySignaturesOnly(pdf, blocks); + + log.debug("determining last partition..."); + TextPartition lastTextPartition = VerificationFilterHelper.findLastTextPartition(partitions); + List extractedSignatures = null; + if (scanForOldSignatures) + { + SignaturesAndOld sao = extractSignaturesFromPartitionAndOld(pdf, lastTextPartition); + extractedSignatures = sao.newSignatures; + 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; + } + + protected List performFullConservative(PdfDataSource pdf, boolean scanForOldSignatures, List blocks, List partitions) throws VerificationFilterException + { + List binarySignatures = extractBinarySignaturesOnly(pdf, blocks); + + // extract signature values of found binary signature blocks and store these values in a Set + // this set is later used to filter out the binary signatures that are recognized as text + // signatures. + 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 + // IU blocks with disturbing text after them. + // On the other hand, these requires extra text extractions and + // signature searches and thereby is slow. + List flattedOutPartitions = flattenOutTextPartitions(partitions, blocks); + partitions = flattedOutPartitions; + + SettingsReader settings; + try { + settings = SettingsReader.getInstance(); + } catch (SettingsException e) { + throw new VerificationFilterException(e); + } + 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(); + + 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; + if (scanThisPartitionForOldSignature) + { + SignaturesAndOld sao = extractSignaturesFromPartitionAndOld(pdf, tp); + partitionResult = sao.newSignatures; + oldSignature = sao.oldSignature; + } + else + { + partitionResult = extractSignaturesFromPartition(pdf, tp); + } + + // 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; + } + + partitionResults.add(partitionResult); + } 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)); + 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."); + } 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; + while (it.hasNext()) + { + List partitionResult = (List) it.next(); + + if (prevPartitionResult == null) + { + extractedSignatures.addAll(partitionResult); + } + else + { + assert partitionResult.size() >= prevPartitionResult.size(); + +// for (int i = prevPartitionResult.size(); i < partitionResult.size(); i++) +// { +// SignatureHolder sh = (SignatureHolder) partitionResult.get(i); +// extractedSignatures.add(sh); +// } + mergeSignatures(prevPartitionResult, partitionResult, extractedSignatures); + } + + prevPartitionResult = partitionResult; + } + + 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 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()) + { + Partition p = (Partition)it.next(); + if (p instanceof TextPartition) + { + TextPartition tp = (TextPartition)p; + Iterator blockIt = tp.blocks.iterator(); + while (blockIt.hasNext()) + { + FooterParseResult fpr = (FooterParseResult)blockIt.next(); + TextPartition newPt = new TextPartition(); + newPt.blocks = new ArrayList(1); + newPt.blocks.add(fpr); + blockPartitions.add(newPt); + } + } + else + { + // binary partition + blockPartitions.add(p); + } + } + + // note: successive binary blocks are still combined to one binary partition + assert blockPartitions.size() <= blocks.size(); + + return blockPartitions; + } + + protected String extractText(PdfDataSource pdf, int endOfDocument) throws PresentableException { + return extractText(pdf, endOfDocument, "utf8"); + } + + 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 + { + return AbsoluteTextSignature.extractSignatureHoldersFromText(text); + } + catch (PresentableException e) + { + throw new VerificationFilterException(e); + } + } + + protected List extractNewAndOldSignaturesFromText(String text) throws VerificationFilterException + { + SignaturesAndOld sao = extractSignaturesAndOld(text); + if (sao.oldSignature != null) + { + sao.newSignatures.add(0, sao.oldSignature); + } + + return sao.newSignatures; + } + + protected List extractOldSignaturesFromText(String text) throws PresentableException + { + return PdfAS.extractSignatureHoldersTextual(text, true); + } + + protected List intermingleSignatures(List binarySignatures, List extractedSignatures) + { + List textualSignatures = filterOutBinarySignatures(extractedSignatures); + + List intermingled = new ArrayList(binarySignatures.size() + textualSignatures.size()); + intermingled.addAll(binarySignatures); + intermingled.addAll(textualSignatures); + + sortSignatures(intermingled); + + return intermingled; + } + + protected List filterOutBinarySignatures(List signatures) + { + List textOnly = new ArrayList(signatures.size()); + + Iterator it = signatures.iterator(); + while (it.hasNext()) + { + SignatureHolder sh = (SignatureHolder) it.next(); + if (sh.getSignatureObject().isTextual()) + { + textOnly.add(sh); + } + } + + return textOnly; + } + + protected void sortSignatures(List signatures) + { + SignatureHolderHelper.sortByDate(signatures); + } + + protected void debugIUBlocks(List blocks) + { + Iterator it = blocks.iterator(); + while (it.hasNext()) + { + FooterParseResult fpr = (FooterParseResult) it.next(); + log.debug("footer: " + fpr.start_index + " to " + fpr.next_index + ", has predecessor = " + fpr.tpr.has_predecessor); + } + } + + protected void debugPartitions(List partitions) + { + Iterator it = partitions.iterator(); + while (it.hasNext()) + { + Object o = it.next(); + assert o instanceof Partition; + + List blocks = null; + if (o instanceof TextPartition) + { + TextPartition tp = (TextPartition) o; + + blocks = tp.blocks; + + log.debug("text partition with " + tp.blocks.size() + " blocks:"); + } + else + { + BinaryPartition bp = (BinaryPartition) o; + + blocks = bp.blocks; + + log.debug("binary partition: with " + bp.blocks.size() + " blocks:"); + + } + debugIUBlocks(blocks); + log.debug("partition finished."); + } + } + + /** + * Extracts the binary singatures from the given PDF. + * + *

+ * IU blocks without an egiz dict are not considered. + *

+ * + * @param pdf + * @param blocks + * @return Returns the List of signature holders. + * @throws PresentableException + */ + protected List extractBinarySignaturesOnly(PdfDataSource pdf, List blocks) throws VerificationFilterException + { + SettingsReader settings; + try { + settings = SettingsReader.getInstance(); + } catch (SettingsException e) { + throw new VerificationFilterException(e); + } + String check_doc = settings.getSetting(CHECK_DOCUMENT, "false"); + 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 + byte[] data = DataSourceHelper.convertDataSourceToByteArray(pdf); + + List binarySignatures = new ArrayList(blocks.size()); + + Iterator it = blocks.iterator(); + int prev_end = 0; + boolean sig_detected = false; + while (it.hasNext()) + { + FooterParseResult fpr = (FooterParseResult) it.next(); + assert fpr.next_index > prev_end; + + if (VerificationFilterBinaryHelper.containsEGIZDict(data, fpr)) + { + 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); + + binarySignatures.addAll(binary_holders); + if(binary_holders.size() > 0) { + sig_detected = true; + } + } else { + // 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 + // 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") && + binary_only.equalsIgnoreCase("true") && + assume_sigs_only.equalsIgnoreCase("false") && + sig_detected) { + + if (!supressException) { + 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."); + } + + } + } + + prev_end = fpr.next_index; + } + + return binarySignatures; + } + catch (PresentableException e) + { + throw new VerificationFilterException(e); + } + } + + protected List extractSignatures(PdfDataSource pdf, int endOfDocument) throws VerificationFilterException + { + try + { + log.debug("Extracting text from 0 to " + endOfDocument + " (total document size = " + pdf.getLength() + "):"); + String extractedText = extractText(pdf, endOfDocument); + log.debug("Extracting text finished."); + log.debug("extracted text: " + extractedText); + + log.debug("Extracting signatures:"); + 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; + for (int i = 0; i < extractedSignatures.size(); i++) { + SignatureHolder sh = (SignatureHolder)extractedSignatures.get(i); + PdfASID kzid = sh.getSignatureObject().getKZ(); + if (kzid != null && kzid.isOldCp1252Version()) { + log.debug("found cp1252 signature"); + cp1252SignaturesPositions.add(new Integer(i)); + //iscp1252Sig = true; + //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."); + } + // merge signature holders + for (int i = 0; i < cp1252SignaturesPositions.size(); i++) { + int replaceIndex = ((Integer)cp1252SignaturesPositions.get(i)).intValue(); + extractedSignatures.remove(replaceIndex); + extractedSignatures.add(replaceIndex, cp1252ExtractedSignatures.get(replaceIndex)); + } + } + + } + + if (log.isDebugEnabled()) + { + log.debug("extracted signatures:"); + for (int i = 0; i < extractedSignatures.size(); i++) + { + SignatureHolder sh = (SignatureHolder)extractedSignatures.get(i); + String dateStr = sh.getSignatureObject().getSignationDate(); + EGIZDate ed = EGIZDate.parseFromString(dateStr); + log.debug("#" + i + ": dateStr = " + dateStr + ", egizDate = " + ed.toString()); + } + } + + return extractedSignatures; + } + catch (PresentableException e) + { + throw new VerificationFilterException(e); + } + } + + protected String determineRestText(List newSignatures, String extractedText) + { + if (newSignatures.isEmpty()) + { + return extractedText; + } + + // note that even if the oldest signature is a binary signature, + // the rest text is the text of this binary signature, which was extracted + // like a text signature. + TextualSignatureHolder oldestSignature = (TextualSignatureHolder) newSignatures.get(0); + return oldestSignature.getSignedText(); + } + + protected List extractSignaturesFromPartition(PdfDataSource pdf, Partition partition) throws VerificationFilterException + { + assert partition.isTextPartition(); + + int endOfDocument = VerificationFilterHelper.getEndOfPartition(partition); + List extractedSigs = extractSignatures(pdf, endOfDocument); + TextualSignatureHolder.mulitSetUiBlockEndPos(extractedSigs, endOfDocument); + return extractedSigs; + } + + protected SignaturesAndOld extractSignaturesFromPartitionAndOld(PdfDataSource pdf, Partition partition) throws VerificationFilterException + { + assert partition.isTextPartition(); + + try + { + int endOfDocument = VerificationFilterHelper.getEndOfPartition(partition); + +// log.debug("Extracting text from 0 to " + endOfDocument + " (total document size = " + pdf.getLength() + "):"); + String extractedText = extractText(pdf, endOfDocument); +// log.debug("Extracting text finished."); +// log.debug("extracted text: " + extractedText); + + SignaturesAndOld sao = extractSignaturesAndOld(extractedText); + TextualSignatureHolder.trySetUiBlockEndPos(sao.oldSignature, endOfDocument); + TextualSignatureHolder.mulitSetUiBlockEndPos(sao.newSignatures, endOfDocument); + + return sao; + } + catch (PresentableException e) + { + throw new VerificationFilterException(e); + } + } + + protected void checkBinaryOnly(PdfDataSource pdf, boolean considerOldSigs) throws VerificationFilterException { + + DelimitedPdfDataSource dds = new DelimitedPdfDataSource(pdf, pdf.getLength()); + String text = null; + try { + text = PdfAS.extractNormalizedTextTextual(dds, "utf-8"); + } catch (PresentableException e) { + throw new VerificationFilterException(e); + } + + List sigs = new ArrayList(); + + if(considerOldSigs) { + SignaturesAndOld sao = extractSignaturesAndOld(text); + if(sao != null) { + if(sao.newSignatures != null) { + sigs.addAll(sao.newSignatures); + } + if(sao.oldSignature != null) { + sigs.add(sao.oldSignature); + } + } + } 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 + { + 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."); + log.debug("oldSignature = null: " + (oldSignature==null)); + + SignaturesAndOld sao = new SignaturesAndOld(); + sao.newSignatures = extractedSignatures; + sao.oldSignature = oldSignature; + + return sao; + } + catch (PresentableException e) + { + throw new VerificationFilterException(e); + } + } + + /** + * 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 + * @throws PDFDocumentException + * @throws SignatureException + * @throws NormalizeException + * @throws SignatureTypesException + */ + protected SignatureHolder extractOldSignature(String extractedText, List newSignatures) throws PDFDocumentException, SignatureException, NormalizeException, SignatureTypesException + { + SignatureHolder oldSignature = null; + + String restText = determineRestText(newSignatures, extractedText); + + List oldSignatures = PdfAS.extractSignatureHoldersTextual(restText, true); + if (!oldSignatures.isEmpty()) + { + oldSignature = (SignatureHolder) oldSignatures.get(0); + if (!newSignatures.isEmpty()) + { + SignatureHolder oldestNewSignature = (SignatureHolder) newSignatures.get(0); + EGIZDate oldDate = EGIZDate.parseFromString(oldSignature.getSignatureObject().getSignationDate()); + EGIZDate newDate = EGIZDate.parseFromString(oldestNewSignature.getSignatureObject().getSignationDate()); + if (newDate.compareTo(oldDate) <= 0) + { + oldSignature = null; + } + } + } + return oldSignature; + } +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/VerificationFilterParametersImpl.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/VerificationFilterParametersImpl.java new file mode 100644 index 0000000..635dc99 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/VerificationFilterParametersImpl.java @@ -0,0 +1,98 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.vfilter; + +import java.io.Serializable; + +import at.gv.egiz.pdfas.framework.vfilter.VerificationFilterParameters; + +/** + * @author wprinz + * + */ +public class VerificationFilterParametersImpl implements VerificationFilterParameters, Serializable +{ + /** + * SVUID. + */ + private static final long serialVersionUID = -7118403150485416046L; + + protected boolean extractBinarySignaturesOnly = false; + + protected boolean assumeOnlySignatureUpdateBlocks = false; + + protected boolean scanForOldSignatures = true; + + protected boolean hasBeenCorrected = false; + + public VerificationFilterParametersImpl(boolean extractBinarySignaturesOnly, boolean assumeOnlySignatureUpdateBlocks, boolean scanForOldSignatures) + { + this.extractBinarySignaturesOnly = extractBinarySignaturesOnly; + this.assumeOnlySignatureUpdateBlocks = assumeOnlySignatureUpdateBlocks; + this.scanForOldSignatures = scanForOldSignatures; + } + + /** + * @see at.gv.egiz.pdfas.framework.vfilter.VerificationFilterParameters#extractBinarySignaturesOnly() + */ + public boolean extractBinarySignaturesOnly() + { + return this.extractBinarySignaturesOnly; + } + + /** + * @see at.gv.egiz.pdfas.framework.vfilter.VerificationFilterParameters#assumeOnlySignatureUpdateBlocks() + */ + public boolean assumeOnlySignatureUpdateBlocks() + { + return this.assumeOnlySignatureUpdateBlocks; + } + + + /** + * @see at.gv.egiz.pdfas.framework.vfilter.VerificationFilterParameters#scanForOldSignatures() + */ + public boolean scanForOldSignatures() + { + return this.scanForOldSignatures; + } + + /** + * @see java.lang.Object#toString() + */ + // @override + public String toString() + { + return "{VerificationFilterParametersImpl: extractBinarySignaturesOnly = " + extractBinarySignaturesOnly() + ", assumeOnlySignatureUpdateBlocks = " + assumeOnlySignatureUpdateBlocks() + "}"; + } + + public boolean hasBeenCorrected() { + return this.hasBeenCorrected; + } + + public void setBeenCorrected(boolean corrected) { + this.hasBeenCorrected = corrected; + + } +} 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 new file mode 100644 index 0000000..735b874 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/helper/VerificationFilterBinaryHelper.java @@ -0,0 +1,190 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.vfilter.helper; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.pdfas.exceptions.ErrorCode; +import at.knowcenter.wag.egov.egiz.PdfASID; +import at.knowcenter.wag.egov.egiz.exceptions.InvalidIDException; +import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException; +import at.knowcenter.wag.egov.egiz.pdf.BinarySignature; +import at.knowcenter.wag.egov.egiz.pdf.Placeholder; +import at.knowcenter.wag.egov.egiz.pdf.StringInfo; +import at.knowcenter.wag.exactparser.parsing.IndirectObjectReference; +import at.knowcenter.wag.exactparser.parsing.PDFUtils; +import at.knowcenter.wag.exactparser.parsing.results.ArrayParseResult; +import at.knowcenter.wag.exactparser.parsing.results.DictionaryParseResult; +import at.knowcenter.wag.exactparser.parsing.results.FooterParseResult; +import at.knowcenter.wag.exactparser.parsing.results.IndirectObjectReferenceParseResult; +import at.knowcenter.wag.exactparser.parsing.results.NumberParseResult; +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 +{ + /** + * The name of the egiz dict key. + */ + public static final byte[] EGIZ_DICT_NAME = { 'E', 'G', 'I', 'Z', 'S', 'i', 'g', 'D', 'i', 'c', 't' }; + + /** + * The name of the ID (SIG_KZ) property in the egiz dict. + */ + public static final byte[] EGIZ_KZ_NAME = { 'I', 'D' }; + + /** + * The log. + */ + private static final Log log = LogFactory.getLog(VerificationFilterBinaryHelper.class); + + /** + * Tells, if the given incremental update block contains a binary signature. + * + *

+ * According to definition, if a block is a binary block, it must/cannot + * contain other signatures than this one. + *

+ * + * @param block + * The incremental update block. + * @return Returns true, if this block is a binary signature block, false + * otherwise. + */ + public static boolean containsEGIZDict(final byte[] pdf, final FooterParseResult block) + { + int dict_index = PDFUtils.indexOfName(pdf, block.tpr.dpr.names, EGIZ_DICT_NAME); + if (dict_index <= 0) + { + return false; + } + + return true; + } + + /** + * Extracts the PDF AS ID of the egiz block. + * + * @param pdf + * The pdf. + * @param block + * The IU block. + * @return Returns the extracted PDF AS ID. + * @throws PDFDocumentException + * Forwarded exception. + * @throws InvalidIDException + * Forwarded exception. + */ + public static PdfASID extractKZFromEGIZBlock(final byte[] pdf, final FooterParseResult block) throws PDFDocumentException, InvalidIDException + { + int egiz_index = PDFUtils.indexOfName(pdf, block.tpr.dpr.names, EGIZ_DICT_NAME); + if (egiz_index < 0) + { + throw new PDFDocumentException(301, "egiz_index = " + egiz_index); + } + + IndirectObjectReferenceParseResult egiz_dict_iorpr = (IndirectObjectReferenceParseResult) block.tpr.dpr.values.get(egiz_index); + // logger_.debug("egiz_dict_ir = " + egiz_dict_iorpr.ior.object_number + // + " " + egiz_dict_iorpr.ior.generation_number); + + IndirectObjectReference ior = egiz_dict_iorpr.ior; + + final int egiz_dict_offset = PDFUtils.getObjectOffsetFromXRefByIndirectObjectReference(block.xpr, ior); + // logger_.debug("egiz_dict_offset = " + egiz_dict_offset); + + ObjectParseResult obj = PDFUtils.parseObject(pdf, egiz_dict_offset); + DictionaryParseResult egiz_dict = (DictionaryParseResult) obj.object; + + int kz_index = PDFUtils.indexOfName(pdf, egiz_dict.names, EGIZ_KZ_NAME); + if (kz_index < 0) + { + throw new PDFDocumentException(301, "kz_index = " + kz_index); + } + ArrayParseResult kz_apr = (ArrayParseResult) egiz_dict.values.get(kz_index); + + String kz_string = restoreKZ(pdf, kz_apr); + PdfASID kz = new PdfASID(kz_string); + + return kz; + } + + /** + * Restores the Kennzeichnung String from an Array. + * + * @param pdf + * The PDF. + * @param kz_apr + * The Array, as parsed from the EGIZ Dict. + * @return Returns the restored KZ. + * @throws PDFDocumentException + * Forwarded exception. + */ + public static String restoreKZ(byte[] pdf, ArrayParseResult kz_apr) throws PDFDocumentException + { + try + { + List partition = new ArrayList(); + + int linesToProcess = (kz_apr.elements.size() / 2); + log.trace("Lines to process for KZ: " + linesToProcess); + /* + if (linesToProcess > 1) { + log.debug("Multiple KZHOTFIX: forcing single line to process"); + linesToProcess = 1; + } + */ + for (int i = 0; i < linesToProcess; i++) + { + NumberParseResult start_npr = (NumberParseResult) kz_apr.elements.get(i * 2); + NumberParseResult length_npr = (NumberParseResult) kz_apr.elements.get(i * 2 + 1); + + StringInfo si = new StringInfo(); + si.string_start = start_npr.number; + si.string_length = length_npr.number; + si.pdf = pdf; + + log.trace("Adding KZ: " + si.toString()); + + partition.add(si); + } + + String KZ = Placeholder.reconstructStringFromPartition(pdf, partition, BinarySignature.ENCODING_WIN); + return KZ; + } + catch (IOException e1) + { + throw new PDFDocumentException(ErrorCode.DOCUMENT_CANNOT_BE_READ, e1); + } + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/helper/VerificationFilterHelper.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/helper/VerificationFilterHelper.java new file mode 100644 index 0000000..69803e7 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/helper/VerificationFilterHelper.java @@ -0,0 +1,162 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.vfilter.helper; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import at.gv.egiz.pdfas.exceptions.framework.VerificationFilterException; +import at.gv.egiz.pdfas.impl.input.helper.DataSourceHelper; +import at.gv.egiz.pdfas.impl.vfilter.Partition; +import at.gv.egiz.pdfas.impl.vfilter.partition.BinaryPartition; +import at.gv.egiz.pdfas.impl.vfilter.partition.TextPartition; +import at.gv.egiz.pdfas.framework.input.PdfDataSource; +import at.knowcenter.wag.exactparser.parsing.results.FooterParseResult; + +/** + * Contains helpful methods used by the VerificationFilter. + * + * @author wprinz + */ +public final class VerificationFilterHelper +{ + /** + * Partitions the list of Incremental Update blocks into text and binary + * partitions. + * + *

+ * A partition is a sequence of Incremental Update blocks of the same type. + *

+ *

+ * An Incremental Update block is considered to have the type "binary" if it + * contains an egiz dictionary. A block not containing an egiz dictionary is + * considert to have the type "text". + *

+ * + * @param pdf + * The PDF. + * @param blocks + * The Incremental Update blocks. + * @return Returns the partitioning of the blocks. + * @throws VerificationFilterException + * Thrown if something goes wrong. + */ + public static List partition(PdfDataSource pdf, List blocks) throws VerificationFilterException + { + List partitions = new ArrayList(blocks.size()); + + Iterator it = blocks.iterator(); + while (it.hasNext()) + { + FooterParseResult fpr = (FooterParseResult) it.next(); + + byte[] data = DataSourceHelper.convertDataSourceToByteArray(pdf); + if (VerificationFilterBinaryHelper.containsEGIZDict(data, fpr)) + { + BinaryPartition bp = null; + if (partitions.isEmpty() || ((Partition) partitions.get(partitions.size() - 1)).isTextPartition()) + { + bp = new BinaryPartition(); + bp.blocks = new ArrayList(blocks.size()); + partitions.add(bp); + } + else + { + bp = (BinaryPartition) partitions.get(partitions.size() - 1); + } + assert bp != null; + + bp.blocks.add(fpr); + } + else + { + TextPartition tp = null; + if (partitions.isEmpty() || !((Partition) partitions.get(partitions.size() - 1)).isTextPartition()) + { + tp = new TextPartition(); + tp.blocks = new ArrayList(blocks.size()); + partitions.add(tp); + } + else + { + tp = (TextPartition) partitions.get(partitions.size() - 1); + } + assert tp != null; + + tp.blocks.add(fpr); + } + } + + assert partitions.size() >= 1 : "There must be at least one partition"; + + return partitions; + } + + /** + * Determines the end of the given partiton. + * + * @param partition + * The partition. + * @return Returns the end index of the given partition. + */ + public static int getEndOfPartition(Partition partition) + { + List blocks = null; + if (partition instanceof TextPartition) + { + blocks = ((TextPartition) partition).blocks; + } + else + { + blocks = ((BinaryPartition) partition).blocks; + } + + return ((FooterParseResult) blocks.get(blocks.size() - 1)).next_index; + } + + /** + * Finds the last text partition in the given list of partitions. + * + * @param partitions + * The partitions. + * @return Returns the last TextPartition. + */ + public static TextPartition findLastTextPartition(List partitions) + { + Partition lastTextPartition = (Partition) partitions.get(partitions.size() - 1); + + if (!lastTextPartition.isTextPartition()) + { + assert partitions.size() > 1 : "The only one partition cannot be a binary partition - where is the original document?"; + Partition previousToLastPartition = (Partition) partitions.get(partitions.size() - 2); + assert previousToLastPartition.isTextPartition() : "The previous to last partition must be a text partition or something is wrong with the partitioning algorithm."; + + lastTextPartition = previousToLastPartition; + } + + return (TextPartition) lastTextPartition; + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/helper/VerificationFilterTextHelper.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/helper/VerificationFilterTextHelper.java new file mode 100644 index 0000000..87aa159 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/helper/VerificationFilterTextHelper.java @@ -0,0 +1,35 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.vfilter.helper; + +/** + * Contains helpful methods used by the VerificationFilter to analyze text and + * find text signatures. + * + * @author wprinz + */ +public final class VerificationFilterTextHelper +{ + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/partition/BinaryPartition.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/partition/BinaryPartition.java new file mode 100644 index 0000000..5b3c7e2 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/partition/BinaryPartition.java @@ -0,0 +1,39 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.vfilter.partition; + +import java.util.List; + +import at.gv.egiz.pdfas.impl.vfilter.Partition; + + +public class BinaryPartition implements Partition +{ + public List blocks = null; + + public boolean isTextPartition() + { + return false; + } +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/partition/TextPartition.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/partition/TextPartition.java new file mode 100644 index 0000000..665a5ef --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/partition/TextPartition.java @@ -0,0 +1,40 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.vfilter.partition; + +import java.util.List; + +import at.gv.egiz.pdfas.impl.vfilter.Partition; + + +public class TextPartition implements Partition +{ + public List blocks = null; + + public boolean isTextPartition() + { + return true; + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/xmldsig/XMLDsigReconstructor.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/xmldsig/XMLDsigReconstructor.java new file mode 100644 index 0000000..f7d5f37 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/xmldsig/XMLDsigReconstructor.java @@ -0,0 +1,76 @@ +/** + * Copyright 2006 by Know-Center, Graz, Austria + * 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.impl.xmldsig; + +import at.gv.egiz.pdfas.api.commons.SignatureInformation; +import at.gv.egiz.pdfas.api.xmldsig.XMLDsigData; +import at.gv.egiz.pdfas.commandline.CommandlineConnectorChooser; +import at.gv.egiz.pdfas.framework.ConnectorParameters; +import at.knowcenter.wag.egov.egiz.PdfAS; +import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException; +import at.knowcenter.wag.egov.egiz.exceptions.ConnectorFactoryException; +import at.knowcenter.wag.egov.egiz.exceptions.SignatureException; +import at.knowcenter.wag.egov.egiz.pdf.SignatureHolder; +import at.knowcenter.wag.egov.egiz.sig.SignatureData; +import at.knowcenter.wag.egov.egiz.sig.SignatureObject; +import at.knowcenter.wag.egov.egiz.sig.connectors.Connector; +import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject; +import at.knowcenter.wag.egov.egiz.sig.signatureobject.SignatureObjectHelper; + +/** + * Utility class for reconstructing xmldsig + * + * @author exthex + * + */ +public class XMLDsigReconstructor { + + /** + * Reconstructs the xmldsig from the given parameters. + * + * @param si the signature information from which to reconstruct the xmldsig + * @param connectorType the type of connector (usually BKU or MOA) to use to create the xmldsig + * @return + * @throws ConnectorException + * @throws ConnectorFactoryException + * @throws SignatureException + */ + public static XMLDsigData reconstruct(SignatureInformation si, String connectorType) throws ConnectorException, ConnectorFactoryException, SignatureException { + SignatureHolder holder = (SignatureHolder)si.getInternalSignatureInformation(); + SignatureObject sigObject = holder.getSignatureObject(); + + SignSignatureObject so = SignatureObjectHelper.convertSignatureObjectToSignSignatureObject(sigObject); + SignatureData sd = PdfAS.convertSignatureHolderToSignatureData(holder); + + String profile = sigObject.getSignatureTypeDefinition().getType(); + String connectorId = CommandlineConnectorChooser.chooseCommandlineConnectorForVerify(connectorType, sigObject.getKZ(), so.id, profile); + + ConnectorParameters cp = new ConnectorParameters(); + cp.setProfileId(profile); + Connector c = at.gv.egiz.pdfas.framework.ConnectorFactory.createConnector(connectorId, cp); + + return c.reconstructXMLDsig(sd, so); + } + +} -- cgit v1.2.3