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 --- .../main/java/at/gv/egiz/pdfas/PdfAsFactory.java | 124 ++ .../egiz/pdfas/algorithmSuite/AlgorithmMapper.java | 143 +++ .../pdfas/algorithmSuite/AlgorithmSuiteObject.java | 183 +++ .../pdfas/algorithmSuite/AlgorithmSuiteUtil.java | 230 ++++ .../src/main/java/at/gv/egiz/pdfas/api/PdfAs.java | 285 +++++ .../egiz/pdfas/api/analyze/AnalyzeParameters.java | 107 ++ .../gv/egiz/pdfas/api/analyze/AnalyzeResult.java | 63 + .../egiz/pdfas/api/analyze/NonTextObjectInfo.java | 99 ++ .../at/gv/egiz/pdfas/api/commons/Constants.java | 185 +++ .../api/commons/DynamicSignatureLifetimeEnum.java | 72 ++ .../pdfas/api/commons/DynamicSignatureProfile.java | 125 ++ .../api/commons/DynamicSignatureProfileImpl.java | 215 ++++ .../pdfas/api/commons/SignatureInformation.java | 129 ++ .../egiz/pdfas/api/commons/SignatureProfile.java | 76 ++ .../pdfas/api/exceptions/ConfigUtilsException.java | 122 ++ .../egiz/pdfas/api/exceptions/PdfAsException.java | 98 ++ .../gv/egiz/pdfas/api/internal/LocalBKUParams.java | 64 + .../gv/egiz/pdfas/api/internal/PdfAsInternal.java | 163 +++ .../gv/egiz/pdfas/api/internal/SignatureEntry.java | 137 +++ .../java/at/gv/egiz/pdfas/api/io/DataSink.java | 98 ++ .../java/at/gv/egiz/pdfas/api/io/DataSource.java | 94 ++ .../java/at/gv/egiz/pdfas/api/io/FileBased.java | 51 + .../java/at/gv/egiz/pdfas/api/io/TextBased.java | 50 + .../at/gv/egiz/pdfas/api/sign/SignParameters.java | 393 ++++++ .../java/at/gv/egiz/pdfas/api/sign/SignResult.java | 84 ++ .../pdfas/api/sign/SignatureDetailInformation.java | 147 +++ .../egiz/pdfas/api/sign/pos/SignaturePosition.java | 72 ++ .../pdfas/api/sign/pos/SignaturePositioning.java | 296 +++++ .../api/sign/pos/axis/AbsoluteAxisAlgorithm.java | 62 + .../pdfas/api/sign/pos/axis/AutoAxisAlgorithm.java | 41 + .../pdfas/api/sign/pos/axis/AxisAlgorithm.java | 41 + .../api/sign/pos/page/AbsolutePageAlgorithm.java | 64 + .../pdfas/api/sign/pos/page/AutoPageAlgorithm.java | 47 + .../pdfas/api/sign/pos/page/NewPageAlgorithm.java | 41 + .../pdfas/api/sign/pos/page/PageAlgorithm.java | 41 + .../egiz/pdfas/api/timestamp/DummyTimeStamper.java | 62 + .../gv/egiz/pdfas/api/timestamp/TimeStamper.java | 41 + .../gv/egiz/pdfas/api/verify/SignatureCheck.java | 51 + .../api/verify/VerifyAfterAnalysisParameters.java | 166 +++ .../VerifyAfterReconstructXMLDsigParameters.java | 169 +++ .../gv/egiz/pdfas/api/verify/VerifyParameters.java | 249 ++++ .../at/gv/egiz/pdfas/api/verify/VerifyResult.java | 179 +++ .../at/gv/egiz/pdfas/api/verify/VerifyResults.java | 48 + .../api/xmldsig/ExtendedSignatureInformation.java | 69 ++ .../ReconstructXMLDsigAfterAnalysisParameters.java | 86 ++ .../api/xmldsig/ReconstructXMLDsigParameters.java | 218 ++++ .../api/xmldsig/ReconstructXMLDsigResult.java | 74 ++ .../at/gv/egiz/pdfas/api/xmldsig/XMLDsigData.java | 83 ++ .../commandline/CommandlineConnectorChooser.java | 199 +++ .../java/at/gv/egiz/pdfas/commandline/Main.java | 1275 ++++++++++++++++++++ .../at/gv/egiz/pdfas/exceptions/ErrorCode.java | 101 ++ .../gv/egiz/pdfas/exceptions/ErrorCodeHelper.java | 119 ++ .../external/ExternalErrorException.java | 66 + .../exceptions/framework/CorrectorException.java | 56 + .../framework/PlaceholderExtractionException.java | 79 ++ .../exceptions/framework/SignatorException.java | 60 + .../framework/VerificationFilterException.java | 60 + .../framework/VerificatorFactoryException.java | 69 ++ .../exceptions/pdf/CaptionNotFoundException.java | 75 ++ .../exceptions/pdf/KZSettingNotFoundException.java | 47 + .../exceptions/web/SessionExpiredException.java | 68 ++ .../gv/egiz/pdfas/framework/ConnectorFactory.java | 107 ++ .../egiz/pdfas/framework/ConnectorParameters.java | 118 ++ .../at/gv/egiz/pdfas/framework/DataManager.java | 55 + .../gv/egiz/pdfas/framework/DataSourceHolder.java | 45 + .../at/gv/egiz/pdfas/framework/DataStrategy.java | 57 + .../gv/egiz/pdfas/framework/SignatorFactory.java | 131 ++ .../pdfas/framework/SignatureHolderHelper.java | 57 + .../egiz/pdfas/framework/VerificatorFactory.java | 65 + .../pdfas/framework/config/SettingsHelper.java | 81 ++ .../gv/egiz/pdfas/framework/input/DataSource.java | 70 ++ .../pdfas/framework/input/ExtractionStage.java | 90 ++ .../egiz/pdfas/framework/input/PdfDataSource.java | 41 + .../pdfas/framework/input/PdfDataSourceHolder.java | 49 + .../egiz/pdfas/framework/input/TextDataSource.java | 39 + .../framework/input/correction/Corrector.java | 61 + .../input/correction/CorrectorFactory.java | 63 + .../gv/egiz/pdfas/framework/output/DataSink.java | 42 + .../sigdevice/SequentialSignatureDevice.java | 45 + .../pdfas/framework/sigdevice/SignatureDevice.java | 36 + .../gv/egiz/pdfas/framework/signator/Signator.java | 71 ++ .../framework/signator/SignatorInformation.java | 99 ++ .../pdfas/framework/verificator/Verificator.java | 61 + .../framework/vfilter/VerificationFilter.java | 72 ++ .../vfilter/VerificationFilterParameters.java | 105 ++ .../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 ++ .../at/gv/egiz/pdfas/io/ByteArrayDataSink.java | 107 ++ .../at/gv/egiz/pdfas/io/ByteArrayDataSource.java | 115 ++ .../at/gv/egiz/pdfas/io/FileBasedDataSink.java | 116 ++ .../at/gv/egiz/pdfas/io/FileBasedDataSource.java | 141 +++ .../pdfas/io/FileBasedTextBasedDataSource.java | 123 ++ .../egiz/pdfas/io/StringTextBasedDataSource.java | 116 ++ .../egiz/pdfas/performance/PerformanceCounter.java | 82 ++ .../pdfas/performance/PerformanceCounters.java | 42 + .../egiz/pdfas/performance/PerformanceTimer.java | 68 ++ .../placeholder/SignaturePlaceholderContext.java | 72 ++ .../placeholder/SignaturePlaceholderData.java | 152 +++ .../placeholder/SignaturePlaceholderExtractor.java | 350 ++++++ .../java/at/gv/egiz/pdfas/test/JarExtractTest.java | 51 + .../java/at/gv/egiz/pdfas/utils/ConfigUtils.java | 318 +++++ .../java/at/gv/egiz/pdfas/utils/DataHashUtils.java | 156 +++ .../main/java/at/gv/egiz/pdfas/utils/OgnlUtil.java | 209 ++++ .../java/at/gv/egiz/pdfas/utils/PDFASUtils.java | 92 ++ .../main/java/at/gv/egiz/pdfas/utils/PdfAUtil.java | 66 + .../java/at/gv/egiz/pdfas/utils/StreamUtils.java | 66 + .../java/at/gv/egiz/pdfas/utils/TempDirHelper.java | 377 ++++++ 158 files changed, 20975 insertions(+) create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/PdfAsFactory.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/algorithmSuite/AlgorithmMapper.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/algorithmSuite/AlgorithmSuiteObject.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/algorithmSuite/AlgorithmSuiteUtil.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/PdfAs.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/analyze/AnalyzeParameters.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/analyze/AnalyzeResult.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/analyze/NonTextObjectInfo.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/Constants.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/DynamicSignatureLifetimeEnum.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/DynamicSignatureProfile.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/DynamicSignatureProfileImpl.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/SignatureInformation.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/SignatureProfile.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/exceptions/ConfigUtilsException.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/exceptions/PdfAsException.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/internal/LocalBKUParams.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/internal/PdfAsInternal.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/internal/SignatureEntry.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/io/DataSink.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/io/DataSource.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/io/FileBased.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/io/TextBased.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/SignParameters.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/SignResult.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/SignatureDetailInformation.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/SignaturePosition.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/SignaturePositioning.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/axis/AbsoluteAxisAlgorithm.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/axis/AutoAxisAlgorithm.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/axis/AxisAlgorithm.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/AbsolutePageAlgorithm.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/AutoPageAlgorithm.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/NewPageAlgorithm.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/PageAlgorithm.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/timestamp/DummyTimeStamper.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/timestamp/TimeStamper.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/verify/SignatureCheck.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyAfterAnalysisParameters.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyAfterReconstructXMLDsigParameters.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyParameters.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyResult.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyResults.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/xmldsig/ExtendedSignatureInformation.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/xmldsig/ReconstructXMLDsigAfterAnalysisParameters.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/xmldsig/ReconstructXMLDsigParameters.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/xmldsig/ReconstructXMLDsigResult.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/xmldsig/XMLDsigData.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/commandline/CommandlineConnectorChooser.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/commandline/Main.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/ErrorCode.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/ErrorCodeHelper.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/external/ExternalErrorException.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/framework/CorrectorException.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/framework/PlaceholderExtractionException.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/framework/SignatorException.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/framework/VerificationFilterException.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/framework/VerificatorFactoryException.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/pdf/CaptionNotFoundException.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/pdf/KZSettingNotFoundException.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/web/SessionExpiredException.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/ConnectorFactory.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/ConnectorParameters.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/DataManager.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/DataSourceHolder.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/DataStrategy.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/SignatorFactory.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/SignatureHolderHelper.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/VerificatorFactory.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/config/SettingsHelper.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/input/DataSource.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/input/ExtractionStage.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/input/PdfDataSource.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/input/PdfDataSourceHolder.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/input/TextDataSource.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/input/correction/Corrector.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/input/correction/CorrectorFactory.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/output/DataSink.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/sigdevice/SequentialSignatureDevice.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/sigdevice/SignatureDevice.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/signator/Signator.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/signator/SignatorInformation.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/verificator/Verificator.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/vfilter/VerificationFilter.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/vfilter/VerificationFilterParameters.java 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 create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/ByteArrayDataSink.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/ByteArrayDataSource.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/FileBasedDataSink.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/FileBasedDataSource.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/FileBasedTextBasedDataSource.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/StringTextBasedDataSource.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/performance/PerformanceCounter.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/performance/PerformanceCounters.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/performance/PerformanceTimer.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/placeholder/SignaturePlaceholderContext.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/placeholder/SignaturePlaceholderData.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/placeholder/SignaturePlaceholderExtractor.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/test/JarExtractTest.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/ConfigUtils.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/DataHashUtils.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/OgnlUtil.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/PDFASUtils.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/PdfAUtil.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/StreamUtils.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/TempDirHelper.java (limited to 'pdf-as-lib/src/main/java/at/gv') diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/PdfAsFactory.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/PdfAsFactory.java new file mode 100644 index 0000000..ba184fb --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/PdfAsFactory.java @@ -0,0 +1,124 @@ +/** + * 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; + +import java.io.File; + +import at.gv.egiz.pdfas.api.PdfAs; +import at.gv.egiz.pdfas.api.exceptions.PdfAsException; +import at.gv.egiz.pdfas.impl.api.PdfAsObject; +import at.knowcenter.wag.egov.egiz.PdfAS; +import at.knowcenter.wag.egov.egiz.cfg.SettingsReader; + +/** + * Main factory for creating a PDF-AS API Instance (PdfAs Interface). + * + * @see PdfAs + * + * @author wprinz + */ +public class PdfAsFactory +{ + /** + * Creates a PDF-AS API instance for the given work directory. + * + * @param workDirectory + * The work directory. If null the configuration is assumed to be located + * within the user's home directory. Note: IAIK JCE and IAIK ECC security provders are + * automatically registered. + * + * @return Returns an instance of the PDF-AS API. + * @throws IllegalArgumentException + * Thrown, if the workDirectory doesn't exist. + * @throws PdfAsException + * Thrown, if the work directory does not meet its requirements, or + * if the config file is invalid. + * @see PdfAS#USERHOME_CONFIG_FOLDER + */ + public static PdfAs createPdfAs(File workDirectory) throws PdfAsException + { + return createPdfAs(workDirectory, SettingsReader.REGISTER_IAIK_PROVIDERS_ON_DEFAULT); + } + + /** + * Creates a PDF-AS API instance for the given work directory. + * + * @param workDirectory + * The work directory. If null the configuration is assumed to be located + * within the user's home 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 + * @return Returns an instance of the PDF-AS API. + * @throws IllegalArgumentException + * Thrown, if the workDirectory doesn't exist. + * @throws PdfAsException + * Thrown, if the work directory does not meet its requirements, or + * if the config file is invalid. + * @see PdfAS#USERHOME_CONFIG_FOLDER + */ + public static PdfAs createPdfAs(File workDirectory, boolean registerProvider) throws PdfAsException + { + return new PdfAsObject(workDirectory, registerProvider); + } + + /** + * Creates a PDF-AS API instance assuming that the configuration is located within the user's + * home directory. Note: IAIK JCE and IAIK ECC security providers are automatically registered. + * + * @return Returns an instance of the PDF-AS API. + * @throws IllegalArgumentException + * Thrown, if the work directory doesn't exist within the user's home directory. + * @throws PdfAsException + * Thrown, if the work directory does not meet its requirements, or + * if the config file is invalid. + * @see PdfAS#USERHOME_CONFIG_FOLDER + */ + public static PdfAs createPdfAs() throws PdfAsException + { + return createPdfAs(null); + } + + /** + * Creates a PDF-AS API instance assuming that the configuration is located within the user's + * home directory. + * + * @return Returns an instance of the PDF-AS API. + * @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 IllegalArgumentException + * Thrown, if the work directory doesn't exist within the user's home directory. + * @throws PdfAsException + * Thrown, if the work directory does not meet its requirements, or + * if the config file is invalid. + * @see PdfAS#USERHOME_CONFIG_FOLDER + */ + public static PdfAs createPdfAs(boolean registerProvider) throws PdfAsException + { + return createPdfAs(null, registerProvider); + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/algorithmSuite/AlgorithmMapper.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/algorithmSuite/AlgorithmMapper.java new file mode 100644 index 0000000..24ac9a5 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/algorithmSuite/AlgorithmMapper.java @@ -0,0 +1,143 @@ +/** + * 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.algorithmSuite; + +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Utility for mapping signature and hash algorithms between URI and abbreviation.
+ * Supported algorithms are defined in external resource {@value #SUPPORTED_ALGORITHMS_RESOURCE}
+ * + * e.g. sha1 <-> http://www.w3.org/2000/09/xmldsig#sha1 + * + * @author dferbas + * + */ + +public class AlgorithmMapper { + private static final String SUPPORTED_ALGORITHMS_RESOURCE = "supportedAlgorithms.txt"; + private static Map algorithmMap = new HashMap(); + private static Log log = LogFactory.getLog(AlgorithmMapper.class); + + /** + * read available algorithms from resource + */ + static { + try { + log.debug("reading supported algorithms from " + SUPPORTED_ALGORITHMS_RESOURCE); + List lines = IOUtils.readLines(AlgorithmMapper.class.getResourceAsStream(SUPPORTED_ALGORITHMS_RESOURCE)); + for (int i = 0; i < lines.size(); i++) { + String uri = (String)lines.get(i); + if (isValidLine(uri)) { + String abbr = parseAbbreviation(uri); + algorithmMap.put(abbr, uri); + if (log.isDebugEnabled()) { + log.debug("added supported algorithm: " + abbr + "=" + uri); + } + } + } + } catch (IOException e) { + throw new RuntimeException("error loading supportetAlgorithms.properties file", e); + } + } + + /** + * Get algorithm abbreviation (equals last part after namespace#) from uri
+ * + * e.g. sha1 from http://www.w3.org/2000/09/xmldsig#sha1 + * + * @param algorithmUri algorithm URI + * @return algorithm abbreviation + */ + public static String getAbbreviation(String algorithmUri) { + if (!algorithmMap.containsValue(algorithmUri)) { + throw new RuntimeException("unsupported Algorithm " + algorithmUri); + } + return parseAbbreviation(algorithmUri); + } + + private static boolean isValidLine(String uri) { + if (uri == null || uri.length() == 0) return false; + if (uri.trim().startsWith("#")) return false; + return true; + } + + /** + * Get valid URI from algorithm abbreviation
+ * + * e.g. http://www.w3.org/2000/09/xmldsig#sha1 from sha1 + * + * @param algorithmShort + * @return URI + */ + public static String getUri(String algorithmShort) { + if (!algorithmMap.containsKey(algorithmShort)) { + throw new RuntimeException("unsupported Algorithm " + algorithmShort); + } + return (String)algorithmMap.get(algorithmShort); + } + + /** + * Get hash (abbreviation) from signature method (eg. sha1 from ecdsa-sha1). + * @param suite abbreviation or full qualified signature method + * @return digest method abbreviation + */ + public static String getHashAbbrFromSuite(String suite) { + try { + int pos = suite.lastIndexOf('-'); + return suite.substring(pos + 1); + } catch (Exception e) { + throw new RuntimeException("cannot parse algorithm string for hash method: " + suite); + } + } + + /** + * + * Get hash method (URI) from signature method + * @param suite abbreviation or full qualified signature method + * @return digest method URI + * + */ + public static String getHashUriFromSuite(String suite) { + return getUri(getHashAbbrFromSuite(suite)); + } + + private static String parseAbbreviation(String algorithmUri) { + try { + int pos = algorithmUri.lastIndexOf('#'); + return algorithmUri.substring(pos + 1); + } catch (Exception e) { + throw new RuntimeException("invalid algorithm entry in " + SUPPORTED_ALGORITHMS_RESOURCE + + ": " + algorithmUri); + } + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/algorithmSuite/AlgorithmSuiteObject.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/algorithmSuite/AlgorithmSuiteObject.java new file mode 100644 index 0000000..a8e19b3 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/algorithmSuite/AlgorithmSuiteObject.java @@ -0,0 +1,183 @@ +/** + * 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.algorithmSuite; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Defines a used algorithm suite. Contains a {@link #signatureMethod} a + * {@link #dataDigestMethod} a {@link #propertiesDigestMethod} and a + * {@link #certDigestMethod}.
+ * + * This structured object is representing a string like + * ecdsa-sha256:sha256:sha256:ripemd160
+ * meaning + * signatureMethod:dataDigestMethod:propertiesDigestMethod:certDigestMethod + * + * @author dferbas + * + */ +public class AlgorithmSuiteObject { + private static Log log = LogFactory.getLog(AlgorithmSuiteObject.class); + + private String signatureMethod; + private String dataDigestMethod; + private String propertiesDigestMethod; + private String certDigestMethod; + + /** + * Create emtpy algorithm suite object + */ + public AlgorithmSuiteObject() { + + } + + /** + * Create object from parameter string like + * etsi-moc-1.2:ecdsa-sha1:ripemd160@207c44ff + * Prefix included + * + * @param parameterString + */ + public AlgorithmSuiteObject(String parameterString) { + parseFrom(parameterString, true); + } + + /** + * Create object from parameter string like
+ * etsi-moc-1.2:ecdsa-sha1:ripemd160@207c44ff hasPrefix=true
+ * ecdsa-sha1:ripemd160@207c44ff hasPrefix=false + * + * + * @param parameterString + * @param hasPrefix parse with/without prefix (e.g. etsi-moc-1.2) + */ + public AlgorithmSuiteObject(String parameterString, boolean hasPrefix) { + parseFrom(parameterString, hasPrefix); + } + + /** + * Initializes object from parameter string like + * etsi-moc-1.2:ecdsa-sha1:ripemd160@207c44ff hasPrefix=true
+ * ecdsa-sha1:ripemd160@207c44ff hasPrefix=false + * + * @param parameterString + * @param hasPrefix parse with/without prefix (e.g. etsi-moc-1.2) + */ + public void parseFrom(String parameterString, boolean hasPrefix) { + log.debug("parsing algorithmSuite from " + parameterString); + if (parameterString != null) { + parameterString = parameterString.split("@")[0]; + if (!hasPrefix) { + parameterString = "bla:" + parameterString; // fake prefix + } + String[] arr = parameterString.split(":"); + if (arr.length > 1) { + this.signatureMethod = arr[1]; + this.dataDigestMethod = this.propertiesDigestMethod = this.certDigestMethod = AlgorithmMapper + .getHashAbbrFromSuite(arr[1]); + + if (arr.length > 2) { + this.dataDigestMethod = this.propertiesDigestMethod = this.certDigestMethod = arr[2]; + } + if (arr.length > 3) { + this.propertiesDigestMethod = this.certDigestMethod = arr[3]; + } + if (arr.length > 4) { + this.certDigestMethod = arr[4]; + } + log.debug("successfully parsed to: " + this.toString()); + } + } + } + + /** + * Returns if algorithm object is valid specified (values are available) + * + * @return + */ + public boolean isSpecified() { + return this.signatureMethod != null; + } + + /** + * Signature method abbreviation. E.g. rsa-sha1, ecdsa-sha256 + * + * @return + */ + public String getSignatureMethod() { + return this.signatureMethod; + } + + /** + * Digest method for data (document). E.g. sha1, md5 + * + * @return + */ + public String getDataDigestMethod() { + return this.dataDigestMethod; + } + + /** + * Digest method for properties. E.g. sha1, md5 + * + * @return + */ + public String getPropertiesDigestMethod() { + return this.propertiesDigestMethod; + } + + /** + * Digest method for certificate digest. E.g. sha1, md5 + * + * @return + */ + public String getCertDigestMethod() { + return this.certDigestMethod; + } + + public void setSignatureMethod(String signatureMethod) { + this.signatureMethod = signatureMethod; + } + + public void setDataDigestMethod(String dataDigestMethod) { + this.dataDigestMethod = dataDigestMethod; + } + + public void setPropertiesDigestMethod(String propertiesDigestMethod) { + this.propertiesDigestMethod = propertiesDigestMethod; + } + + public void setCertDigestMethod(String certDigestMethod) { + this.certDigestMethod = certDigestMethod; + } + + public String toString() { + return "AlgorithmSuiteObject [certDigestMethod=" + this.certDigestMethod + + ", dataDigestMethod=" + this.dataDigestMethod + ", propertiesDigestMethod=" + + this.propertiesDigestMethod + ", signatureMethod=" + this.signatureMethod + "]"; + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/algorithmSuite/AlgorithmSuiteUtil.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/algorithmSuite/AlgorithmSuiteUtil.java new file mode 100644 index 0000000..eba63c7 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/algorithmSuite/AlgorithmSuiteUtil.java @@ -0,0 +1,230 @@ +/** + * 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.algorithmSuite; + +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.knowcenter.wag.egov.egiz.sig.connectors.ConnectorEnvironment; +import at.knowcenter.wag.egov.egiz.sig.connectors.TemplateReplaces; +import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject; + +/** + * Utility class for handling dynamic algorithm suites + * + * @author dferbas + * + */ +public class AlgorithmSuiteUtil { + private static Log log = LogFactory.getLog(AlgorithmSuiteUtil.class); + + /** + * Creates new verify_xml, evaluates algorithm suite and replaces methods in verify_xml + * + * @param algSuite out-param empty algorithm suite object + * @param environment connector environment to load verify template + * @param so signsignator object + * @return verify xml + */ + public static String evaluateReplaceAlgs(AlgorithmSuiteObject algSuite, ConnectorEnvironment environment, SignSignatureObject so) { + + String verify_template = environment.getVerifyTemplate(); + + String cert_alg = null; + String verify_xml = null; + X509Certificate cert = so.getX509Certificate(); + String ids_string = so.getSigID(); + + //AlgorithmSuiteObject algSuite = new AlgorithmSuiteObject(ids_string); + algSuite.parseFrom(ids_string, true); + // 1. is specified in sig_id + if (algSuite.isSpecified()) { + log.debug("Algorithm suite defined as parameter. Using new dynamic template replacement."); + cert_alg = AlgorithmMapper.getUri(algSuite.getSignatureMethod()); + + // 2. is specified in /alg replace -> baik + } else if (so.getSigAlgorithm() != null && so.getSigAlgorithm().length() > 0) { + String algAbbr = AlgorithmMapper.getAbbreviation(so.getSigAlgorithm()); + algSuite.parseFrom(algAbbr, false); + + if (algSuite.isSpecified()) { + log.debug("Algorithm /alg available. Using: " + so.getSigAlgorithm()); + cert_alg = AlgorithmMapper.getUri(algSuite.getSignatureMethod()); +// algSuite.setCertDigestMethod("sha1"); + //algSuite.setPropertiesDigestMethod("sha1"); + } + } + + // 3. default + if (cert_alg == null) { + log.debug("NO algorithm suite defined. Using default old static algorithm."); + + cert_alg = environment.getCertAlgEcdsa(); + if (cert.getPublicKey().getAlgorithm().indexOf("RSA") >= 0) //$NON-NLS-1$ + { + cert_alg = environment.getCertAlgRsa(); + } + + // fix digest methods to sha1 for old algorithm + String oldDigest = "sha1"; + algSuite.setCertDigestMethod(oldDigest); + algSuite.setDataDigestMethod(oldDigest); + algSuite.setPropertiesDigestMethod(oldDigest); + + } + + // cert alg replace + verify_xml = verify_template.replaceFirst(TemplateReplaces.CERT_ALG_REPLACE, cert_alg); + + // digest method replaces + verify_xml = verify_xml.replaceFirst(TemplateReplaces.DATA_DIGEST_REPLACE, + AlgorithmMapper.getUri(algSuite.getDataDigestMethod())); + verify_xml = verify_xml.replaceFirst(TemplateReplaces.PROPERTIES_DIGEST_REPLACE, + AlgorithmMapper.getUri(algSuite.getPropertiesDigestMethod())); + verify_xml = verify_xml.replaceFirst(TemplateReplaces.CERT_DIGEST_REPLACE, + AlgorithmMapper.getUri(algSuite.getCertDigestMethod())); + return verify_xml; + } + + + /** + * Extract algorithm suite as optimized string from CreateXMLSignatureResponse + * + * @param xmlResponse + * @return algorith suite string + */ + public static String extractAlgorithmSuiteString(String xmlResponse) { + + String elem = findFirstElement(xmlResponse, "SignatureMethod"); + + String alg = findAttributeValue(elem, "Algorithm"); + + List digAlgs = findAllAttributeValues(xmlResponse, "DigestMethod", "Algorithm"); + + digAlgs.add(0, AlgorithmMapper.getHashUriFromSuite(alg)); + + reduceDigestAlgs(digAlgs); + + digAlgs.remove(0); + + return createSigDevString(alg, digAlgs); + + } + + public static boolean isDefaultCertAlg(String algsString, String defaultCertAlg) { + return AlgorithmMapper.getAbbreviation(defaultCertAlg).equals(algsString); + } + + private static String createSigDevString(String suite, List digAlgs) { + StringBuffer sb = new StringBuffer(AlgorithmMapper.getAbbreviation(suite)); + for (Iterator iterator = digAlgs.iterator(); iterator.hasNext();) { + String dig = (String) iterator.next(); + sb.append(":").append(AlgorithmMapper.getAbbreviation(dig)); + } + return sb.toString(); + } + + private static String findAttributeValue(String elemContent, String attrName) { + + String sig_alg = removeAllWhitespace(elemContent); + + attrName += "=\""; + int start = sig_alg.indexOf(attrName) + attrName.length(); + int end = sig_alg.indexOf("\"", start); + return sig_alg.substring(start, end); + + } + + private static String findFirstElement(String xml, String elemName) { + Pattern p = Pattern.compile("<[\\w]*:?" + elemName); + Matcher m = p.matcher(xml); + if (m.find()) { + int start = m.start(); + int end = xml.indexOf("/>", start) + 2; + return xml.substring(start, end); + } + return null; + } + + private static List findElements(String xml, String elemName) { + Pattern p = Pattern.compile("<[\\w]*:?" + elemName); + Matcher m = p.matcher(xml); + ArrayList res = new ArrayList(); + while (m.find()) { + int start = m.start(); + int end = xml.indexOf("/>", start) + 2; + res.add(xml.substring(start, end)); + } + return res; + } + + private static String findAttributeValue(String xmlContent, String elemName, String attrName) { + String elemCont = findFirstElement(xmlContent, elemName); + return findAttributeValue(elemCont, attrName); + } + + private static List findAllAttributeValues(String xmlContent, String elemName, String attrName) { + List elemConts = findElements(xmlContent, elemName); + ArrayList res = new ArrayList(); + for (int i = 0; i < elemConts.size(); i++) { + res.add(findAttributeValue((String) elemConts.get(i), attrName)); + } + return res; + } + + /** + * Helper method to remove whitespaces from a string + * @param str + * @return + */ + public static String removeAllWhitespace(String str) { + return str.replaceAll("\\s", ""); //$NON-NLS-1$ //$NON-NLS-2$ + } + + private static void reduceDigestAlgs(List digestAlgs) { + if (digestAlgs == null) + return; + reduceDigestAlgsRec(digestAlgs, digestAlgs.size() - 1); + } + + private static void reduceDigestAlgsRec(List digestAlgs, int act) { + if (act <= 0) + return; + else if (digestAlgs.get(act - 1).equals(digestAlgs.get(act))) { + // reduce + digestAlgs.remove(act); + reduceDigestAlgsRec(digestAlgs, act - 1); + } else { + return; + } + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/PdfAs.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/PdfAs.java new file mode 100644 index 0000000..3fda87c --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/PdfAs.java @@ -0,0 +1,285 @@ +/** + * 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.api; + +import java.util.List; + +import at.gv.egiz.pdfas.api.analyze.AnalyzeParameters; +import at.gv.egiz.pdfas.api.analyze.AnalyzeResult; +import at.gv.egiz.pdfas.api.commons.DynamicSignatureLifetimeEnum; +import at.gv.egiz.pdfas.api.commons.DynamicSignatureProfile; +import at.gv.egiz.pdfas.api.commons.SignatureProfile; +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.ReconstructXMLDsigAfterAnalysisParameters; +import at.gv.egiz.pdfas.api.xmldsig.ReconstructXMLDsigParameters; +import at.gv.egiz.pdfas.api.xmldsig.ReconstructXMLDsigResult; +import at.gv.egiz.pdfas.framework.signator.SignatorInformation; + +/** + * The PDF-AS API main interface. + * + *

+ * Create an Object implementing this interface using the proper factory. + *

+ * + * @author wprinz + * @author exthex + */ +public interface PdfAs +{ +// 23.11.2010 changed by exthex - added: +// reconstructXMLDSIG(ReconstructXMLDsigParameters reconstructXMLDsigParameters) +// reconstructXMLDSIG(ReconstructXMLDsigAfterAnalysisParameters reconstructXMLDsigParameters) +// verify(VerifyAfterReconstructXMLDsigParameters verifyAfterReconstructXMLDsigParameters) + +// 16.12.2010 changed by exthex - added: +// prepareSign(SignParameters signParameters) +// sign(SignParameters signParameters, SignatureDetailInformation signatureDetailInformation) +// finishSign(SignParameters signParameters, SignatureDetailInformation signatureDetailInformation) + + /** + * Signs a PDF document using PDF-AS. + * + * @param signParameters + * The sign parameters. + * @return Returns the signed document plus additional information. + * @throws PdfAsException + * Thrown, if an error occurs. + * + * @see SignParameters + * @see SignResult + */ + public SignResult sign(SignParameters signParameters) throws PdfAsException; + + /** + * Signs a PDF document using PDF-AS.
+ * This uses the {@link SignatorInformation} which was obtained by a call to {@link PdfAs#prepareSign(SignParameters)} + * + * @param signParameters + * The sign parameters. + * @param signatureDetailInformation + * The signature information which was previously obtained by a call to {@link PdfAs#prepareSign(SignParameters)} + * @return Returns the signed document plus additional information. + * @throws PdfAsException + * Thrown, if an error occurs. + * + * @see SignParameters + * @see SignResult + */ + public SignResult sign(SignParameters signParameters, SignatureDetailInformation signatureDetailInformation) throws PdfAsException; + + /** + * Verifies a document with (potentially multiple) PDF-AS signatures. + * + * @param verifyParameters + * The verify parameters. + * @return Returns the verification results. + * @throws PdfAsException + * Thrown, if an error occurs. + * + * @see VerifyParameters + * @see VerifyResults + * @see VerifyResult + */ + public VerifyResults verify(VerifyParameters verifyParameters) throws PdfAsException; + + /** + * Analyzes a document for signatures and returns a verify-able list of such. + * + * @param analyzeParameters + * The analyzation parameters. + * @return Returns a list of verify-able signatures that were found in the + * document. + * @throws PdfAsException + * Thrown on error. + * + * @see AnalyzeParameters + * @see AnalyzeResult + * @see {@link #verify(AnalyzeResult)} + */ + public AnalyzeResult analyze(AnalyzeParameters analyzeParameters) throws PdfAsException; + + /** + * Reconstruct the from the given parameters. + * + * @param reconstructXMLDsigParameters + * The data from which to reconstruct the xmldsig + * @return a list of xmldsigs, one for each signature in the document + * @throws PdfAsException if the reconstruction fails + */ + public ReconstructXMLDsigResult reconstructXMLDSIG(ReconstructXMLDsigParameters reconstructXMLDsigParameters) throws PdfAsException; + + /** + * Reconstruct the from the given parameters. + * + * @param reconstructXMLDsigParameters + * The data from which to reconstruct the xmldsigs + * @return a list of xmldsigs, one for each signature in the document + * @throws PdfAsException + */ + public ReconstructXMLDsigResult reconstructXMLDSIG(ReconstructXMLDsigAfterAnalysisParameters reconstructXMLDsigParameters) throws PdfAsException; + + /** + * Verifies a list of signatures that have been analyzed previously. + * + * @param verifyAfterAnalysisParameters The parameters. + * + * @return Returns the verification results. + * @throws PdfAsException + * Thrown on error. + * + * @see AnalyzeResult + * @see VerifyAfterAnalysisParameters + * @see VerifyResults + * @see VerifyResult + * @see {@link #analyze(AnalyzeParameters)} + */ + public VerifyResults verify(VerifyAfterAnalysisParameters verifyAfterAnalysisParameters) throws PdfAsException; + + /** + * Verifies a list of signatures that have been analyzed previously and the xmldsigs have been reconstructed. + * + * @param verifyAfterReconstructXMLDsigParameters + * The parameters. + * @return the verification results. + * @throws PdfAsException + * Thrown on error. + */ + public VerifyResults verify(VerifyAfterReconstructXMLDsigParameters verifyAfterReconstructXMLDsigParameters) throws PdfAsException; + + /** + * Reloads the configuration from the work directory. + * + * @throws PdfAsException + * Thrown, if an error occurs. + */ + public void reloadConfig() throws PdfAsException; + + /** + * Returns the list of information objects about activated profiles available in the + * configuration. + * + *

+ * Note: Currently the profile information consists of the profile Id and the + * MOA Key Id only. + *

+ *

+ * Note: In near future the profile management will be moved out of the config + * file into an API class representation of the profiles which may render this + * (and related) methods obsolete. + *

+ * + * @return Returns the list of {@link SignatureProfile} objects with + * information about active profiles available in the configuration. + * @throws PdfAsException + * Thrown on error. + * + * @see SignatureProfile + */ + public List getProfileInformation() throws PdfAsException; + + /** + * Create a signature profile dynamically. You have do apply() it for usage. See {@link SignatureProfile}. + * @param parentProfile a parent profile id to inherit all properties + * @param mode lifetime mode + * @return the created signature profile to work with. + */ + public DynamicSignatureProfile createDynamicSignatureProfile(String parentProfile, DynamicSignatureLifetimeEnum mode); + + /** + * Create a signature profile dynamically. You have to provide a unique name and have do apply() it for usage. See {@link SignatureProfile}. + * It is recommended to use {@link #createDynamicSignatureProfile(String, DynamicSignatureLifetimeEnum)} that generates + * a unique name on its own. + * @see DynamicSignatureProfile + * @param parentProfile a parent profile id to inherit all properties + * @param myUniqueName a unique name for the profile + * @param mode lifetime mode + * @return the created signature profile to work with. + */ + public DynamicSignatureProfile createDynamicSignatureProfile(String myUniqueName, String parentProfile, DynamicSignatureLifetimeEnum mode); + + /** + * Create a signature profile dynamically. You have fill it with properties and apply() it for usage. See {@link SignatureProfile}. + *
+ * It is recommended to use {@link #createDynamicSignatureProfile(String, DynamicSignatureLifetimeEnum)} that inherits from an + * existing profile saving you a lot of work. + * @param mode lifetime mode + * @return the created signature profile to work with. + * @see DynamicSignatureProfile + */ + public DynamicSignatureProfile createEmptyDynamicSignatureProfile(DynamicSignatureLifetimeEnum mode); + + /** + * Create a signature profile dynamically. You have fill it with properties and apply() it for usage. See {@link SignatureProfile}. + *
+ * It is recommended to use {@link #createDynamicSignatureProfile(String, DynamicSignatureLifetimeEnum)} that inherits from an + * existing profile saving you a lot of work. + * @param myUniqueName a unique name for the profile + * @param mode lifetime mode + * @return the created signature profile to work with. + */ + public DynamicSignatureProfile createEmptyDynamicSignatureProfile(String myUniqueName, DynamicSignatureLifetimeEnum mode); + + /** + * Loads an existing dynamic signature profile by its name. Profiles are saved when they are applied + * and it has {@link DynamicSignatureLifetimeEnum#MANUAL} + * @param profileName + * @return the signature profile or null if not found. + * @see DynamicSignatureProfile + */ + public DynamicSignatureProfile loadDynamicSignatureProfile(String profileName); + + /** + * Prepares the signature of the given PDF document. The table for the signature data is placed but not filled.
+ * Usually used for preview. + * + * @param signParameters + * The sign parameters. + * @return Only the {@link SignatureDetailInformation#getSignaturePosition()}, {@link SignatureDetailInformation#getNonTextualObjects()}, {@link SignatureDetailInformation#getSignatureData()} are filled. + * @throws PdfAsException if something goes wrong during the process + */ + public SignatureDetailInformation prepareSign(SignParameters signParameters) throws PdfAsException; + + /** + * Finish the signature process. The PDF is filled with the signature data.
+ * Usually used if some steps like the actual signing are to be performed externally. + * + * @param signParameters + * The sign parameters. + * @param signatureDetailInformation + * The signature detail information. + * @return + * @throws PdfAsException + */ + public SignResult finishSign(SignParameters signParameters, SignatureDetailInformation signatureDetailInformation) throws PdfAsException; + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/analyze/AnalyzeParameters.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/analyze/AnalyzeParameters.java new file mode 100644 index 0000000..1ce7057 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/analyze/AnalyzeParameters.java @@ -0,0 +1,107 @@ +/** + * 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.api.analyze; + +import at.gv.egiz.pdfas.api.commons.Constants; +import at.gv.egiz.pdfas.api.io.DataSource; + +/** + * Parameter object that holds the analyze parameters. + * + * @author wprinz + */ +public class AnalyzeParameters +{ + + /** + * The document to be analyzed. + */ + protected DataSource document = null; + + /** + * The mode of operation how the document is analyzed. + * + *

+ * May be {@link Constants#VERIFY_MODE_BINARY_ONLY} to check the document for + * binary signatures only (very fast). Or may be + * {@link Constants#VERIFY_MODE_SEMI_CONSERVATIVE} to perform a semi + * conservative (optimized) text and binary verification (slow). Or may be + * {@link Constants#VERIFY_MODE_FULL_CONSERVATIVE} to perform a full + * conservative text and binary verification (very slow). + *

+ */ + protected String verifyMode = Constants.VERIFY_MODE_FULL_CONSERVATIVE; + + protected boolean returnNonTextualObjects = false; + + protected boolean hasBeenCorrected = false; + + /** + * @return the document + */ + public DataSource getDocument() + { + return this.document; + } + + /** + * @param document the document to set + */ + public void setDocument(DataSource document) + { + this.document = document; + } + + /** + * @return the verifyMode + */ + public String getVerifyMode() + { + return this.verifyMode; + } + + /** + * @param verifyMode the verifyMode to set + */ + public void setVerifyMode(String verifyMode) + { + this.verifyMode = verifyMode; + } + + public boolean isReturnNonTextualObjects() { + return this.returnNonTextualObjects; + } + + /** + * Tells if non text object of the signed pdf should be extracted and returned. + * One should show this to the user, especially in case of textual signature. + * Defaults to false + * + * @param returnNonTextualObjects + */ + public void setReturnNonTextualObjects(boolean returnNonTextualObjects) { + this.returnNonTextualObjects = returnNonTextualObjects; + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/analyze/AnalyzeResult.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/analyze/AnalyzeResult.java new file mode 100644 index 0000000..9b913ae --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/analyze/AnalyzeResult.java @@ -0,0 +1,63 @@ +/** + * 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.api.analyze; + +import java.util.List; + +import at.gv.egiz.pdfas.api.commons.SignatureInformation; +import at.gv.egiz.pdfas.api.exceptions.PdfAsException; + +/** + * The result of an analyze operation, which is a list of verifyable signatures. + * + * @author wprinz + * + */ +public interface AnalyzeResult +{ + /** + * Returns the list of found signatures. + * + * @return Returns a list of {@link SignatureInformation} objects representing all + * found signatures. + * @throws PdfAsException + * Thrown on error. + * + * @see SignatureInformation + */ + public List getSignatures() throws PdfAsException; + + public List getNoSignatures(); + + /** + * 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(); + + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/analyze/NonTextObjectInfo.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/analyze/NonTextObjectInfo.java new file mode 100644 index 0000000..08297b7 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/analyze/NonTextObjectInfo.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.api.analyze; + +/** + * Encapsulates information about non textual objects in a pdf document. + * + * @author dferbas + * + */ +public class NonTextObjectInfo { + public static final String TYPE_IMAGE = "image"; + public static final String TYPE_ANNOTATION = "annotation"; + + private String objectType; + private String subType; + private String name; + private int pageNr; + private double width; + private double height; + + public String getObjectType() { + return this.objectType; + } + + public void setObjectType(String objectType) { + this.objectType = objectType; + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public int getPageNr() { + return this.pageNr; + } + + public void setPageNr(int pageNr) { + this.pageNr = pageNr; + } + + public double getWidth() { + return this.width; + } + + public void setWidth(double width) { + this.width = width; + } + + public double getHeight() { + return this.height; + } + + public void setHeight(double height) { + this.height = height; + } + + public String getSubType() { + return this.subType; + } + + public void setSubType(String subType) { + this.subType = subType; + } + + + + public String toString() { + return "NonTextObjectInfo [height=" + this.height + ", name=" + this.name + ", objectType=" + + this.objectType + ", pageNr=" + this.pageNr + ", subType=" + this.subType + + ", width=" + this.width + "]"; + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/Constants.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/Constants.java new file mode 100644 index 0000000..b351d50 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/Constants.java @@ -0,0 +1,185 @@ +/** + * 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.api.commons; + +import at.knowcenter.wag.egov.egiz.pdf.AdobeSignatureHelper; + +/** + * Contains commonly used constants. + * + * @author wprinz + */ +public final class Constants +{ + + /** + * Hidden default constructor. + */ + private Constants() + { + // empty + } + + /** + * A binary signature. + * This value should not be modified due to external dependencies! + */ + public static final String SIGNATURE_TYPE_BINARY = "binary"; + + /** + * A textual signature. + * This value should not be modified due to external dependencies! + */ + public static final String SIGNATURE_TYPE_TEXTUAL = "textual"; + + /** + * The default signature type (one of "textual", "binary", "detachedtextual"). + */ + public static final String DEFAULT_SIGNATURE_TYPE = SIGNATURE_TYPE_BINARY; + + /** + * A "detached" textual signature. + * + *

+ * The document text is signed, but instead of returning the pdf with the signature block, + * the sign result XML of the connector is returned. + *

+ */ + public static final String SIGNATURE_TYPE_DETACHEDTEXTUAL = "detachedtextual"; + + /** + * The signature device moa. + * This value should not be modified due to external dependencies! + */ + public static final String SIGNATURE_DEVICE_MOA = "moa"; + + /** + * The signature device bku. + * This value should not be modified due to external dependencies! + */ + public static final String SIGNATURE_DEVICE_BKU = "bku"; + + /** + * The signature device a1. + * This value should not be modified due to external dependencies! + */ + public static final String SIGNATURE_DEVICE_A1 = "a1"; + + /** + * The signature device MOCCA (online bku). + * This value should not be modified due to external dependencies! + */ + public static final String SIGNATURE_DEVICE_MOC = "moc"; + + /** + * Added by rpiazzi + * The signature device MOBILE. + * This value should not be modified due to external dependencies! + */ + public static final String SIGNATURE_DEVICE_MOBILE = "mobile"; + + /** + * Added by rpiazzi + * The signature device MOBILETEST for the test version of the MOBILE CCS. + * This value should not be modified due to external dependencies! + */ + public static final String SIGNATURE_DEVICE_MOBILETEST = "mobiletest"; + + /** + * Only binary signatures are verified. + */ + public static final String VERIFY_MODE_BINARY_ONLY = "binaryOnly"; + + /** + * Binary and textual signatures are verified with time optimization. + * + *

+ * This mode of operation tries to minimize the numbers of text extractions, + * which are very time intensive, at the cost of some rare cases, in which some + * signatures may not be found. + *

+ */ + public static final String VERIFY_MODE_SEMI_CONSERVATIVE = "semiConservative"; + + /** + * Binary and textual signatures are verified. + */ + public static final String VERIFY_MODE_FULL_CONSERVATIVE = "fullConservative"; + + /** + * All signatures are verified. + */ + public static final int VERIFY_ALL = -1; + + /** + * The system property that may be used to declare the pdf-as configuration folder. + */ + public static final String CONFIG_DIR_SYSTEM_PROPERTY = "pdf-as.work-dir"; + + /** + * The zip file containing the default configuration. + */ + public static final String DEFAULT_CONFIGURATION_ZIP_RESOURCE = "DefaultConfiguration.zip"; + + /** + * The configuration folder for pdf-as within the user's home folder. + */ + public static final String USERHOME_CONFIG_FOLDER = "PDF-AS"; + + /** + * The name of the directory, where temporary files are stored. + */ + public static final String TEMP_DIR_NAME = "pdfastmp"; + + public static final String BKU_HEADER_SIGNATURE_LAYOUT = "SignatureLayout"; + + public static final String ADOBE_SIG_FILTER = AdobeSignatureHelper.ADOBE_SIG_FILTER; + + /** + * Strict matching mode for placeholder extraction.
+ * If the placeholder with the given id is not found in the document, an exception will be thrown. + */ + public static final int PLACEHOLDER_MATCH_MODE_STRICT = 0; + + /** + * A moderate matching mode for placeholder extraction.
+ * If the placeholder with the given id is not found in the document, the first placeholder without an id will be taken.
+ * If there is no such placeholder, the signature will be placed as usual, according to the pos parameter of the signature profile used. + */ + public static final int PLACEHOLDER_MATCH_MODE_MODERATE = 1; + + /** + * A more lenient matching mode for placeholder extraction.
+ * If the placeholder with the given id is not found in the document, the first found placeholder will be taken, regardless if it has an id set, or not.
+ * If there is no placeholder at all, the signature will be placed as usual, according to the pos parameter of the signature profile used. + */ + public static final int PLACEHOLDER_MATCH_MODE_LENIENT = 2; + + /** + * Identifier for QR based placeholders. + */ + public static final String QR_PLACEHOLDER_IDENTIFIER = "PDF-AS-POS"; + +} + diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/DynamicSignatureLifetimeEnum.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/DynamicSignatureLifetimeEnum.java new file mode 100644 index 0000000..7b3d17b --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/DynamicSignatureLifetimeEnum.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.api.commons; + +import java.io.Serializable; + +/** + * Pseudo enum defining lifetime models for {@link DynamicSignatureProfile}s. + * + * @author exthex + * + */ +public final class DynamicSignatureLifetimeEnum implements Serializable { + private static final long serialVersionUID = 1L; + + private int value; + + /** + * Automatic lifetime bound to one sign process + */ + public static final DynamicSignatureLifetimeEnum AUTO = new DynamicSignatureLifetimeEnum(1); + + /** + * Manual lifetime making YOU responsible for calling {@link DynamicSignatureProfile#dispose()}. + */ + public static final DynamicSignatureLifetimeEnum MANUAL = new DynamicSignatureLifetimeEnum(2); + + private DynamicSignatureLifetimeEnum(int val) { + this.value = val; + } + + public int hashCode() { + return value; + } + + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + DynamicSignatureLifetimeEnum other = (DynamicSignatureLifetimeEnum) obj; + if (value != other.value) + return false; + return true; + } + + + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/DynamicSignatureProfile.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/DynamicSignatureProfile.java new file mode 100644 index 0000000..7418f4d --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/DynamicSignatureProfile.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.api.commons; + +import at.gv.egiz.pdfas.api.PdfAs; +import at.gv.egiz.pdfas.api.sign.SignParameters; + +/** + * A dynamic signature profile. It is used to define a signature profile like the ones from pdf-as/config.properties at runtime. + * After creation via {@link PdfAs} you can set properties via {@link #setPropertyRaw(String, String)} + * or {@link #setFieldValue(String, String)}.
+ * You have to call {@link #apply()} to use the profile. The identifying name (e.g. for {@link SignParameters#setSignatureProfileId(String)} + * can be obtained via {@link #getName()}.
+ * Depending on the {@link DynamicSignatureLifetimeEnum} the profile can be alive and usable till you {@link #dispose()} it manually. + *

+ * Sample usage:
+ *

+      SignParameters sp = new SignParameters();
+      . . .           
+      sp.setSignatureType(Constants.SIGNATURE_TYPE_TEXTUAL);
+      sp.setSignatureDevice(Constants.SIGNATURE_DEVICE_MOA);
+
+      // create a new dynamic profile based on SIGNATURBLOCK_DE (every property is copied) with manual lifetime
+      DynamicSignatureProfile dsp = pdfAs.createDynamicSignatureProfile("myUniqueName", "SIGNATURBLOCK_DE", 
+            DynamicSignatureLifetimeEnum.MANUAL);  
+            
+      // set something
+      dsp.setPropertyRaw("key.SIG_META", "Statement");
+      dsp.setPropertyRaw("value.SIG_META", "respect to the man in the icecream van ${subject.EMAIL}");
+      dsp.setPropertyRaw("value.SIG_LABEL", "./images/signatur-logo_en.png");
+      dsp.setPropertyRaw("table.main.Style.halign", "right");
+      
+      // mandatory: apply the profile, you have to apply again after changes (overriding your previous setting)
+      dsp.apply();                 
+      sp.setSignatureProfileId(dsp.getName());            
+      
+      // execute PDF-AS
+      pdfAs.sign(sp);              
+      
+      . . .
+                       
+     // your profile is saved and you can obtain it again anytime later:
+      dsp = pdfAs.loadDynamicSignatureProfile("myUniqueName");
+      // use it for another sign.
+      // dont forget to dispose() sometimes because it was manual lifetime
+      System.out.println(dsp.getName());
+ *  
+ *

+ * + * @author exthex + * + */ +public interface DynamicSignatureProfile { + + /** + * Get the name of the dynamic signature profile. Equals the SignatureProfileId + * @return + */ + public abstract String getName(); + + /** + * Set a field value for the profile. Use {@link #setPropertyRaw(String, String)} for setting any property.
+ * For example to set sig_obj.MEIN_DYN_SIGNATURBLOCK.value.SIG_META just use SIG_META as fieldName. + * @param fieldName the name of the field + * @param value the value to set + */ + public abstract void setFieldValue(String fieldName, String value); + + /** + * Get a field value from the profile. See {@link #setFieldValue(String, String)} + * @param fieldName + * @return + */ + public abstract String getFieldValue(String fieldName); + + /** + * Set any property for the signature profile. + * Uses the same keys as the property file without the "prefix" for the profile. + * For example to set sig_obj.MEIN_DYN_SIGNATURBLOCK.key.SIG_META use key.SIG_META + * @param key property key + * @param val property value + */ + public void setPropertyRaw(String key, String val); + + /** + * Get any property from the signature profile. See {@link #setPropertyRaw(String, String)} for details. + * @param key + * @return + */ + public String getPropertyRaw(String key); + + /** + * Apply the signature profile. Call this after all properties are set and you want to use the profile. It is then added + * to the globally available signature profiles. Depending on the lifetime model {@link DynamicSignatureLifetimeEnum} you + * have to {@link #dispose()} it manually when not needed anymore. + */ + public abstract void apply(); + + /** + * Disposes the signature profile from the global store. Call this for {@link DynamicSignatureLifetimeEnum#MANUAL} only. + */ + public abstract void dispose(); + +} \ No newline at end of file diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/DynamicSignatureProfileImpl.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/DynamicSignatureProfileImpl.java new file mode 100644 index 0000000..7e1672a --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/DynamicSignatureProfileImpl.java @@ -0,0 +1,215 @@ +/** + * 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.api.commons; + +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import org.apache.commons.lang.StringUtils; + +import at.gv.egiz.pdfas.api.PdfAs; +import at.knowcenter.wag.egov.egiz.cfg.PropertyTree; +import at.knowcenter.wag.egov.egiz.cfg.SettingsReader; +import at.knowcenter.wag.egov.egiz.sig.SignatureTypes; + +// TODO exception types? +/** + * Implementation class of the {@link DynamicSignatureProfile}. Don't use this class directly. Use {@link PdfAs} to create and the + * {@link DynamicSignatureProfile} interface for manipulation. + * @author exthex + * + */ +public class DynamicSignatureProfileImpl implements DynamicSignatureProfile { + private String name; + private Properties newProps = new Properties(); + private int dynamicTypeCounter = 0; + private static Map profiles = new HashMap(); + private static ThreadLocal localProfiles = new ThreadLocal(); + private DynamicSignatureLifetimeEnum lifeMode; + + + private DynamicSignatureProfileImpl(DynamicSignatureLifetimeEnum mode, String name) { + if (name != null) { + this.name = name; + } else { + this.name = createDynamicTypeName(); + } + this.lifeMode = mode; + } + + public static DynamicSignatureProfileImpl createFromParent(String myUniqueName, String parentProfile, DynamicSignatureLifetimeEnum mode) { + DynamicSignatureProfileImpl res = new DynamicSignatureProfileImpl(mode, myUniqueName); + res.initFromParent(parentProfile); + return res; + } + + private void store() { + if (lifeMode.equals(DynamicSignatureLifetimeEnum.MANUAL)) { + profiles.put(this.getName(), this); + } else if (lifeMode.equals(DynamicSignatureLifetimeEnum.AUTO)) { + localProfiles.set(this); + } + } + + private void remove() { + if (lifeMode.equals(DynamicSignatureLifetimeEnum.MANUAL)) { + profiles.remove(this); + } else if (lifeMode.equals(DynamicSignatureLifetimeEnum.AUTO)) { + localProfiles.set(null); + } + } + + public static void disposeLocalProfile() { + DynamicSignatureProfileImpl profile = (DynamicSignatureProfileImpl) localProfiles.get(); + if (profile != null) { + profile.dispose(); + } + } + + public static DynamicSignatureProfileImpl createEmptyProfile(String myUniqueName, DynamicSignatureLifetimeEnum mode) { + return new DynamicSignatureProfileImpl(mode, myUniqueName); + } + + public static DynamicSignatureProfileImpl loadProfile(String name) { + return (DynamicSignatureProfileImpl) profiles.get(name); + } + + private synchronized String createDynamicTypeName() { + return "dynprofile__#" + this.dynamicTypeCounter++; + } + + /* (non-Javadoc) + * @see at.gv.egiz.pdfas.api.commons.DynamicSignatureProfile#getName() + */ + public String getName() { + return name; + } + + /* (non-Javadoc) + * @see at.gv.egiz.pdfas.api.commons.DynamicSignatureProfile#setName(String) + */ + public void setName(String uniqueName) { + this.name = uniqueName; + } + + public void setPropertyRaw(String key, String val) { + this.newProps.setProperty(localPropName(key), val); + } + + public String getPropertyRaw(String key) { + return this.newProps.getProperty(localPropName(key)); + } + + private void assertPropExists(String key) { + if (!this.newProps.containsKey(localPropName(key))) { + throw new RuntimeException("property '" + key + "'not existing, cannot add one"); + } + } + + private String localPropName(String key) { + return "sig_obj." + this.name + "." + key; + } + + /* (non-Javadoc) + * @see at.gv.egiz.pdfas.api.commons.DynamicSignatureProfile#setFieldValue(java.lang.String, java.lang.String) + */ + public void setFieldValue(String fieldName, String value) { + if (SignatureTypes.isRequredSigTypeKey(fieldName)) { + throw new RuntimeException("cannot set value for pre defined signature field names"); + } + + String key = "value." +fieldName; + assertPropExists(key); + setPropertyRaw(key, value); + } + + /* (non-Javadoc) + * @see at.gv.egiz.pdfas.api.commons.DynamicSignatureProfile#getFieldValue(java.lang.String) + */ + public String getFieldValue(String fieldName) { + return getPropertyRaw("value."+fieldName); + } + + private void initFromParent(String parentProfile) { + try { + SettingsReader cfg = null; + + cfg = SettingsReader.getInstance(); + + Properties props = cfg.getProperties(); + for (Enumeration e = props.keys(); e.hasMoreElements();) { + String oldKey = (String) e.nextElement(); + if (oldKey.startsWith("sig_obj." + parentProfile + ".")) { + String newKey = StringUtils.replace(oldKey, parentProfile, name); + String val = props.getProperty(oldKey); + this.newProps.put(newKey, val); + } + } + this.newProps.put("sig_obj.types." + name, "on"); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /* (non-Javadoc) + * @see at.gv.egiz.pdfas.api.commons.DynamicSignatureProfile#register() + */ + public synchronized void apply() { + try { + SettingsReader settings = SettingsReader.getInstance(); + + settings.getProperties().putAll(this.newProps); + + for (Enumeration e = newProps.keys(); e.hasMoreElements();) { + String key = (String) e.nextElement(); + settings.getPTree().setKeyValue(key, newProps.getProperty(key)); + } + + SignatureTypes.getInstance().addSignatureType(this.name); + store(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /* (non-Javadoc) + * @see at.gv.egiz.pdfas.api.commons.DynamicSignatureProfile#dispose() + */ + public synchronized void dispose() { + try { + SettingsReader.getInstance().getProperties().keySet().removeAll(newProps.keySet()); + + PropertyTree root = SettingsReader.getInstance().getPTree(); + root.getSubTree("sig_obj").removeEntry(this.name); + + SignatureTypes.getInstance().removeSignatureType(this.name); + remove(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/SignatureInformation.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/SignatureInformation.java new file mode 100644 index 0000000..7315af6 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/SignatureInformation.java @@ -0,0 +1,129 @@ +/** + * 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: SignatureHolder.java,v 1.3 2006/10/11 07:57:58 wprinz Exp $ + */ +package at.gv.egiz.pdfas.api.commons; + +import java.security.cert.X509Certificate; +import java.util.Date; +import java.util.List; + +import at.gv.egiz.pdfas.api.analyze.NonTextObjectInfo; +import at.gv.egiz.pdfas.api.io.DataSource; + +/** + * Holds the information of one found signature block, which is the signed data + * and the corresponding signature information. + * + * @author wprinz + */ +public interface SignatureInformation +{ + /** + * Returns the type of this signature (binary/textual). + * + *

+ * May be {@link Constants#SIGNATURE_TYPE_BINARY} or + * {@link Constants#SIGNATURE_TYPE_TEXTUAL}. + *

+ * + * @return Returns the type of this signature (binary/textual). + */ + public String getSignatureType(); + + /** + * Returns the DataSource providing the data that was signed. + * + *

+ * Note that this is the signed data as sent to the verification device by + * PDF-AS. The verification device (e.g. MOA) may perform several other + * transformations on the data before feeding it to the signature hash + * function. To get the actual hashed data use the ReturnHashInputData mechanism (which is very slow). + *

+ * + * @return Returns the DataSource providing the data that was signed. + * + * @see at.gv.egiz.pdfas.api.verify.VerifyParameters#setReturnHashInputData(boolean) + * @see at.gv.egiz.pdfas.api.verify.VerifyResult#getHashInputData() + * + */ + public DataSource getSignedData(); + + /** + * Returns the certificate of the signer. + * + *

+ * Information like subject name, issuer name or serial number can be + * retrieved form this certificate. + *

+ * + * @return Returns the certificate of the signer. + */ + public X509Certificate getSignerCertificate(); + + /** + * Returns the signing time, which is the time when the signature was created. + * + * @return Returns the signing time, which is the time when the signature was + * created. + */ + public Date getSigningTime(); + + /** + * Returns additional, internal information about the found signature. + * + *

+ * Note that this provides a way for developers to gather core information + * about the signature. What information is returned strongly depends on the + * core implementation. + *

+ * + * @return Returns additional, internal information about the signature. Null + * means that no additional information is available. + */ + public Object getInternalSignatureInformation(); + + /** + * Returns the embedded /TimeStamp value (b64 encoded) from the signature if available. + * @return + */ + public String getTimeStampValue(); + + /** + * Returns a list<{@link NonTextObjectInfo}> of non textual objects in the pdf document. + * Only available for textual signatures. Show this to the user who signed the textual content only! + * @return List<{@link NonTextObjectInfo} or null of not available (binary signature) + */ + public List getNonTextualObjects(); + + public void setNonTextualObjects(List nonTextualObjects); + + /** + * Returns true if non textual objects have been found, false if not. + * @return true if non textual objects have been found, false if not. + */ + public boolean hasNonTextualObjects(); + + +} \ No newline at end of file diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/SignatureProfile.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/SignatureProfile.java new file mode 100644 index 0000000..8cd3108 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/SignatureProfile.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.api.commons; + +import java.util.Properties; + +/** + * Definition of a signature profile. + * + * @author wprinz + */ +public interface SignatureProfile { + + // TODO: implement full profile support + + /** + * Returns the profile id. + * + * @return Returns the profile id. + */ + public String getProfileId(); + + /** + * Returns the MOA KeyIdentifier. + * + * @return Returns the MOA KeyIdentifier. + */ + public String getMOAKeyIdentifier(); + + /** + * Returns 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. + * + * @return The entries relevant to the signature block search algorithm as + * Java properties. + */ + public Properties getSignatureBlockEntries(); + + /** + * Returns the profile description. + * + * @return The profile description. + */ + public String getProfileDescription(); + + /** + * True only if this is the default profile according to config. + * @return + */ + public boolean isDefault(); +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/exceptions/ConfigUtilsException.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/exceptions/ConfigUtilsException.java new file mode 100644 index 0000000..644f74e --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/exceptions/ConfigUtilsException.java @@ -0,0 +1,122 @@ +/** + * 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.api.exceptions; + +/** + * @author Thomas Knall + */ +public class ConfigUtilsException extends Exception { + + /** + * Marker for serialization. + */ + private static final long serialVersionUID = 1L; + + /** + * The underlying exception. + */ + private Exception wrappedException; + + /** + * Returns the underlying exception. + * + * @return The underlying exception. + */ + public Exception getException() { + return this.wrappedException; + } + + /** + * Returns the message of the wrapped exception. + * + * @return The message of the wrapped exception. + */ + public String getMessage() { + String message = super.getMessage(); + if (message == null && this.wrappedException != null) { + return this.wrappedException.getMessage(); + } else { + return message; + } + } + + /** + * Instantiation of a new exception based on a message and another (wrapped) + * exception. + * + * @param message + * The exception message. + * @param exception + * Another exception. + */ + public ConfigUtilsException(final String message, final Exception exception) { + super(message); + this.wrappedException = exception; + } + + /** + * Instantiated a new exception based on a message. + * + * @param message + * The message of the new exception. + */ + public ConfigUtilsException(final String message) { + super(message); + this.wrappedException = null; + } + + /** + * Instantiates a new exception based on another (wrapped) exception. + * + * @param exception + * The wrapped exception. + */ + public ConfigUtilsException(final Exception exception) { + super(); + this.wrappedException = exception; + } + + /** + * Instantiates a new (unspecified) exception. + */ + public ConfigUtilsException() { + super(); + this.wrappedException = null; + + } + + /** + * Returns the text representation of this instance. + * + * @return The text representation of this instance. + */ + public String toString() { + if (this.wrappedException != null) { + return this.wrappedException.toString(); + } else { + return super.toString(); + } + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/exceptions/PdfAsException.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/exceptions/PdfAsException.java new file mode 100644 index 0000000..a050543 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/exceptions/PdfAsException.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.api.exceptions; + +/** + * This exception is the base for all PDF-AS exceptions. + * + *

+ * Every PDF-AS Exception has an error code. + *

+ * + * @author wprinz + */ +public abstract class PdfAsException extends Exception +{ + /** + * The error code. + */ + protected int errorCode = -1; + + /** + * Constructor. + * + * @param errorCode + * The error code. + * @param message + * The detail message. + */ + public PdfAsException(int errorCode, String message) + { + super(message); + + this.errorCode = errorCode; + } + + /** + * Constructor. + * + * @param errorCode + * The error code. + * @param message + * The detail message. + * @param cause + * The cause. + */ + public PdfAsException(int errorCode, String message, Throwable cause) + { + super(message, cause); + + this.errorCode = errorCode; + } + + /** + * Constructor. + * + * @param errorCode + * The error code. + * @param cause + * The cause. + */ + public PdfAsException(int errorCode, Throwable cause) + { + super(cause); + + this.errorCode = errorCode; + } + + /** + * Returns the error code of this exception. + * + * @return Returns the error code of this exception. + */ + public int getErrorCode() + { + return this.errorCode; + } +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/internal/LocalBKUParams.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/internal/LocalBKUParams.java new file mode 100644 index 0000000..b798903 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/internal/LocalBKUParams.java @@ -0,0 +1,64 @@ +/** + * 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.api.internal; + + +/** + * Parameter container for local BKUs. (BKU, Mocca) + * + * @author exthex + * + */ +public class LocalBKUParams { + + private String server; + private String userAgent; + private String signatureLayout; + + public LocalBKUParams(String server, String userAgent, String signatureLayout) { + this.server = server; + this.userAgent = userAgent; + this.signatureLayout = signatureLayout; + } + + public String getServer() { + return server; + } + public void setServer(String server) { + this.server = server; + } + public String getUserAgent() { + return userAgent; + } + public void setUserAgent(String userAgent) { + this.userAgent = userAgent; + } + public String getSignatureLayout() { + return signatureLayout; + } + public void setSignatureLayout(String signatureLayout) { + this.signatureLayout = signatureLayout; + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/internal/PdfAsInternal.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/internal/PdfAsInternal.java new file mode 100644 index 0000000..a77051d --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/internal/PdfAsInternal.java @@ -0,0 +1,163 @@ +/** + * 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.api.internal; + +import java.util.Map; + +import at.gv.egiz.pdfas.api.PdfAs; +import at.gv.egiz.pdfas.api.analyze.AnalyzeResult; +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.VerifyResult; +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; + +/** + * The methods of this interface are used by the pdf-as-web project and are not for external use.
+ * Using this API is inadvisable as its functionality might change without notice from release to release. + * + * @author exthex + * + */ +public interface PdfAsInternal { + + /** + * Check if a BKU with the given parameters is supported. + * + * @param bkuParams + * @throws ConnectorException if the BKU is not supported + * @throws SettingsException if the BKU is not supported + */ + public void verifyBKUSupport(LocalBKUParams bkuParams) throws ConnectorException, SettingsException; + + /** + * Finish the sign process. + * + * @param pdfAs + * @param signParameters + * @param sdi This info will most likely come from a {@link PdfAs#prepareSign(SignParameters)} call + * @param bkuParams + * @param xmlResponse the SecurityLayer response from the BKU + * @return the signed document + additional info + * @throws PdfAsException + */ + public SignResult finishLocalSign(PdfAs pdfAs, SignParameters signParameters, SignatureDetailInformation sdi, LocalBKUParams bkuParams, boolean multipart, String xmlResponse) throws PdfAsException; + + /** + * Get the security layer address for the given connector. (zB: http://127.0.0.1:3495/http-security-layer-request) + * + * @param profile + * @param device + * @return + * @throws SettingsException + */ + public String getLocalServiceAddress(String profile, String device) throws SettingsException; + + /** + * Get the CreateXMLSignatureRequest for the given parameters. + * The request will use the given callback address to retrieve the data to sign. + * + * @param signParameters the sign parameters. {@link SignParameters#getSignatureDevice()} determines the connector to use. + * @param multipart true to select a {@link at.knowcenter.wag.egov.egiz.sig.connectors.LocalConnector} that uses multipart requests + * @param loc_ref_url the URL where to retrieve the PDF to sign + * @param sdi {@link SignatureDetailInformation#getSignatureData()} provides the data to be signed. + * @return + * @throws ConnectorException + */ + public String prepareLocalSignRequest(SignParameters signParameters, boolean multipart, String loc_ref_url, SignatureDetailInformation sdi) throws ConnectorException; + + /** + * Create an AnalyzeResult from raw text, instead of a PDF. + * + * @param rawText + * @param sigValues the signature values + * @return + * @throws SignatureException + * @throws SettingsException + * @throws SignatureTypesException + * @throws NormalizeException + */ + public AnalyzeResult analyzeFromRawText(String rawText, Map sigValues) throws SignatureException, SettingsException, SignatureTypesException, NormalizeException; + + /** + * Create the SecurityLayer VerifyXMLSignatureRequest for the given parameters. + * + * @param sigInfo + * @param connector + * @param profile + * @param loc_ref_url + * @return + * @throws SignatureException + * @throws ConnectorException + */ + public String prepareLocalVerifyRequest(SignatureInformation sigInfo, String connector, String profile, String loc_ref_url) throws SignatureException, ConnectorException; + + /** + * Parse the given xml_response - must be a VerifyXMLSignatureResponse - from the BKU or Mocca and generates a VerifyResult from it. + * + * @param sigInfo + * @param connector + * @param profile + * @param loc_ref_url + * @param xmlResponse + * @return + * @throws SignatureException + * @throws ConnectorException + */ + public VerifyResult finishLocalVerify(SignatureInformation sigInfo, String connector, String profile, String loc_ref_url, String xmlResponse) throws SignatureException, ConnectorException; + + /** + * Get the {@link SignatureEntry} corresponding to a given {@link SignatureInformation} + * + * @param key + * @param sigInfo + * @return + */ + public SignatureEntry getSignatureEntryFromSignatureInformation(String key, SignatureInformation sigInfo); + + /** + * Get the signed text for a given sigInfo.
+ * If this signature is not text based this method will return null. + * + * @param sigInfo + * @return + */ + public String getSignedText(SignatureInformation sigInfo); + + /** + * Get a map of all connectors available for web. + * The key is the connector id, the value is the description. + * + * @return + * @throws ConnectorFactoryException + */ + public Map getConnectorsAvailableForWeb() throws ConnectorFactoryException; +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/internal/SignatureEntry.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/internal/SignatureEntry.java new file mode 100644 index 0000000..a3d77b8 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/internal/SignatureEntry.java @@ -0,0 +1,137 @@ +/** + * 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: SignatureEntry.java,v 1.3 2006/08/25 17:09:41 wprinz Exp $ + */ +package at.gv.egiz.pdfas.api.internal; + +import java.io.Serializable; + +/** + * A container for signature entries. + * Copied to internal api from {@link at.knowcenter.wag.egov.egiz.sig.SignatureEntry} + * + * @author exthex + * @see at.knowcenter.wag.egov.egiz.sig.SignatureEntry + */ +public class SignatureEntry implements Serializable { + + /** + * SVUID. + */ + private static final long serialVersionUID = -1L; + + /** + * The signature key. + */ + private String key_ = null; + /** + * The signature caption for the key found or set in the signature text. + */ + private String caption_ = null; + /** + * The signature value for the key found or set in the signature text. + */ + private String value_ = null; + + /** + * The empty constructor. + */ + public SignatureEntry() { + } + + /** + * A new SignatureEntry init with the key. + * + * @param key + */ + public SignatureEntry(String key) { + key_ = key; + } + + /** + * Returns the caption off the current key. + * + * @return Returns the caption. + */ + public String getCaption() { + return caption_; + } + + /** + * Set the caption of the current key. + * + * @param caption The caption to set. + */ + public void setCaption(String caption) { + caption_ = caption; + } + + /** + * Return the current key. + * + * @return Returns the key. + */ + public String getKey() { + return key_; + } + + /** + * Set the current key. + * + * @param key The key to set. + */ + public void setKey(String key) { + key_ = key; + } + + /** + * Return the value of the current key. + * + * @return Returns the value. + */ + public String getValue() { + return value_; + } + + /** + * Set the value of the current key. + * + * @param value The value to set. + */ + public void setValue(String value) { + value_ = value; + } + + /** + * The toString method, used for tests or debugging. + */ + public String toString() { + String the_string = ""; + the_string += "\n Key:" + key_; + the_string += "\nCaption:" + caption_; + the_string += "\n Value:" + value_; +// the_string += "\nStart I:" + startIndex_; + return the_string; + } +} \ No newline at end of file diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/io/DataSink.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/io/DataSink.java new file mode 100644 index 0000000..a539ce0 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/io/DataSink.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.api.io; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * Output document data sink. + * + *

+ * Actually, the DataSink can be seen as a factory for creating OutputStreams + * with mime type and character encoding provided. This allows the API user to + * decide how data is to be stored (e.g. in a file, in a byte array, etc.). + *

+ * + * @author wprinz + */ +public interface DataSink +{ + /** + * Creates an OutputStream for binary data. + * + *

+ * Note that the stream may be written only once. Creating another stream + * overwrites the existing one. + *

+ * + * @param mimeType + * The mime type of the output data. + * @return Returns the created output stream. + * @throws IOException + * Thrown if the stream cannot be created. + */ + public OutputStream createOutputStream(String mimeType) throws IOException; + + /** + * Creates an OutputStream for character data. + * + *

+ * This is basically the same as {@link #createOutputStream(String)}, but + * allows to specify the character encoding. + *

+ * + * @param mimeType + * The mime type of the output data. + * @param characterEncoding + * The character encoding of the data. + * @return Returns the created output stream. + * @throws IOException + * Thrown if the stream cannot be created. + */ + public OutputStream createOutputStream(String mimeType, String characterEncoding) throws IOException; + + /** + * Returns the mime type of the data stream. + * + *

+ * This is only valid after a stream has been created. + *

+ * + * @return Returns the mime type of the data stream. + */ + public String getMimeType(); + + /** + * Returns the character encoding of the data stream. + * + *

+ * This is only valid after a stream has been created. Null means that no + * character encoding was specified for the data (e.g. if the data is binary). + *

+ * + * @return Returns the character encoding of the data stream. + */ + public String getCharacterEncoding(); +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/io/DataSource.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/io/DataSource.java new file mode 100644 index 0000000..4150255 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/io/DataSource.java @@ -0,0 +1,94 @@ +/** + * 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.api.io; + +import java.io.InputStream; + +/** + * Input document data source. + * + *

+ * This allows the holder of the data to decide how the data is to be stored (e.g. in a File or in a byte array). + *

+ * + * @author wprinz + * + */ +public interface DataSource +{ + /** + * Creates a new InputStream that allows to read out the document's binary + * data from the beginning. + * + * @return Returns the InputStream with the binary data. + */ + public InputStream createInputStream(); + + /** + * Returns the length (number of bytes) of the stream. + * + * @return Returns the length (number of bytes) of the stream. + */ + public int getLength(); + + /** + * Returns the data of this DataSource as a byte array for random read only access. + * + *

+ * Calling this method indicates that you need a byte array for random + * read only access. The DataSource implementation should of + * course cache this byte array to avoid too much memory usage. + *

+ *

+ * Performance analysis has shown that the libraries internally convert the + * streams to byte arrays and that file system access is very slow. + *

+ *

+ * Never write to this byte array! + *

+ * + * @return Returns the data of this DataSource as a byte array for random read only access. + */ + public byte[] getAsByteArray(); + + /** + * Returns the mime type of the data. + * + * @return Returns the mime type of the data. + */ + public String getMimeType(); + + /** + * Returns the character encoding of the data. + * + *

+ * This makes only sense for character based mime types. + *

+ * + * @return Returns the character encoding of the data or null if no encoding + * is applicable (e.g. if the data is binary). + */ + public String getCharacterEncoding(); + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/io/FileBased.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/io/FileBased.java new file mode 100644 index 0000000..f3d0d0e --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/io/FileBased.java @@ -0,0 +1,51 @@ +/** + * 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.api.io; + +import java.io.File; + +/** + * Tells that the IO element (DataSink or DataSource) is backed by a file in the local file system. + * + *

+ * This is a hint that may be used by PDF-AS to optimize data access. + *

+ * + * @author wprinz + */ +public interface FileBased +{ + + /** + * Returns the File "behind" this io element. + * + *

+ * This is usually used to determine the file name itself. + *

+ * + * @return Returns the File "behind" this io element. + */ + public File getFile (); + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/io/TextBased.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/io/TextBased.java new file mode 100644 index 0000000..39602ff --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/io/TextBased.java @@ -0,0 +1,50 @@ +/** + * 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.api.io; + +/** + * Tells, that the IO Element (DataSink - but mostly DataSource) is based upon + * character data. + * + *

+ * This can be used to retrieve the character text directly with the correct + * encoding etc. + *

+ *

+ * This makes most sense for text DataSources. + *

+ * + * @author wprinz + */ +public interface TextBased +{ + + /** + * Returns the text. + * + * @return Returns the text. + */ + public String getText(); + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/SignParameters.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/SignParameters.java new file mode 100644 index 0000000..8834481 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/SignParameters.java @@ -0,0 +1,393 @@ +/** + * 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.api.sign; + +import java.util.Properties; + +import at.gv.egiz.pdfas.api.commons.Constants; +import at.gv.egiz.pdfas.api.io.DataSink; +import at.gv.egiz.pdfas.api.io.DataSource; +import at.gv.egiz.pdfas.api.sign.pos.SignaturePositioning; +import at.gv.egiz.pdfas.api.timestamp.TimeStamper; +import at.knowcenter.wag.egov.egiz.sig.SignatureTypes; + +/** + * Parameter object that holds the sign parameters. + * + * @author wprinz + */ +public class SignParameters +{ +// 23.11.2010 changed by exthex - added parameters for placeholder handling + + /** + * The document to be signed. + * + *

+ * The DataSource implementation encapsulates the actual representaion of the + * data. E.g. the DataSource may be File based or byte array based. See + * package at.gv.egiz.pdfas.framework.input and at.gv.pdfas.impl.input + *

+ */ + protected DataSource document = null; + + /** + * The type of the signature. + * + *

+ * May be {@link Constants#SIGNATURE_TYPE_BINARY} or + * {@link Constants#SIGNATURE_TYPE_TEXTUAL}. + *

+ */ + protected String signatureType = Constants.DEFAULT_SIGNATURE_TYPE; + + /** + * The signature device to perform the actual signature. + * + *

+ * May be {@link Constants#SIGNATURE_DEVICE_MOA} or + * {@link Constants#SIGNATURE_DEVICE_BKU}. + *

+ */ + protected String signatureDevice = Constants.SIGNATURE_DEVICE_MOA; + + /** + * The signature profile identifier identifying the profile to be used in the + * config file. + * + *

+ * Note: In near future it will be possible to provide a full specified + * profile here instead of the profile id. + *

+ */ + protected String signatureProfileId = null; + + /** + * The signature key identifier specifying which signature key should be used + * by the signature device to perform the signature. + * + *

+ * Providing a null value (default) means that no explicit signature key + * identifier is provided. The selected signature device will then use its + * default mechanism for retrieving this information (which is usually to read + * the key from the provided signature profile). + *

+ *

+ * Note that not all signature devices may support this parameter. + * If a signature device doesn't support this parameter the value should be null. + *

+ *

+ * This key is usually passed straight through to the signature device and + * thereby has to contain an appropriate value for the signature device + * chosen. + *

+ *

+ * Currently, only the {@link Constants#SIGNATURE_DEVICE_MOA} signature device + * evaluates this parameter and passes the provided String to MOA as the MOA + * key group identifier. If null is provided, the MOA signature device will + * determine the signature key identifier to be used from the provided profile + * and, if not specified there either, from the MOA default configuration. + *

+ */ + protected String signatureKeyIdentifier = null; + + /** + * The signature position. Consult the PDF-AS documentation section + * Commandline. + */ + protected SignaturePositioning signaturePositioning = null; + + /** + * The output DataSink that will receive the signed document. + */ + protected DataSink output = null; + + protected TimeStamper timeStamperImpl; + + /** + * The flag to de-/activate placeholder search + */ + protected Boolean checkForPlaceholder = null; + + /** + * The id of the placeholder which should be replaced. + */ + protected String placeholderId; + + /** + * The matching mode for placeholder extraction.
+ * If a {@link SignParameters#placeholderId} is set, the match mode determines what is to be done, if no matching placeholder is found in the document. + *
+ * Defaults to {@link Constants#PLACEHOLDER_MATCH_MODE_MODERATE}. + */ + protected int placeholderMatchMode = Constants.PLACEHOLDER_MATCH_MODE_MODERATE; + + protected Properties overrideProps = new Properties(); + + + + + + /** + * {@link #setTimeStamperImpl(TimeStamper)} + * @return + */ + public TimeStamper getTimeStamperImpl() { + return this.timeStamperImpl; + } + + /** + * Set a {@link TimeStamper} to create a timestamp on the signature value. Will be + * called after sign. For binary signatures only. Timestamp will be embedded in egiz dict /TimeStamp. + * @param timeStamperImpl + */ + public void setTimeStamperImpl(TimeStamper timeStamperImpl) { + this.timeStamperImpl = timeStamperImpl; + } + +/** + * @return the document + */ + public DataSource getDocument() + { + return document; + } + + /** + * @param document + * the document to set + */ + public void setDocument(DataSource document) + { + this.document = document; + } + + /** + * @return the signatureType + */ + public String getSignatureType() + { + return signatureType; + } + + /** + * @param signatureType + * the signatureType to set + */ + public void setSignatureType(String signatureType) + { + this.signatureType = signatureType; + } + + /** + * @return the signatureDevice + */ + public String getSignatureDevice() + { + return signatureDevice; + } + + /** + * @param signatureDevice + * the signatureDevice to set + */ + public void setSignatureDevice(String signatureDevice) + { + this.signatureDevice = signatureDevice; + } + + /** + * @return the signatureProfileId + */ + public String getSignatureProfileId() + { + return signatureProfileId; + } + + /** + * @param signatureProfileId + * the signatureProfileId to set + */ + public void setSignatureProfileId(String signatureProfileId) + { + this.signatureProfileId = signatureProfileId; + } + + /** + * @return the signaturePositioning + */ + public SignaturePositioning getSignaturePositioning() + { + return this.signaturePositioning; + } + + /** + * @param signaturePositioning + * the signaturePositioning to set + */ + public void setSignaturePositioning(SignaturePositioning signaturePositioning) + { + this.signaturePositioning = signaturePositioning; + } + + /** + * @return the output + */ + public DataSink getOutput() + { + return output; + } + + /** + * @param output + * the output to set + */ + public void setOutput(DataSink output) + { + this.output = output; + } + + /** + * @return the signatureKeyIdentifier + */ + public String getSignatureKeyIdentifier() + { + return this.signatureKeyIdentifier; + } + + /** + * @param signatureKeyIdentifier the signatureKeyIdentifier to set + */ + public void setSignatureKeyIdentifier(String signatureKeyIdentifier) + { + this.signatureKeyIdentifier = signatureKeyIdentifier; + } + + /** + * Override user defined values from the used signature profile like "value.SIG_META". + * You cannot override pre defined values like SIG_VALUE, SIG_DATE {@link SignatureTypes#REQUIRED_SIG_KEYS}. + * The override values are bound to the {@link SignParameters} instance. + *

+ * Sample usage: + *

+      SignParameters sp = new SignParameters();
+      . . .
+      
+      sp.setSignatureProfileId("SIGNATURBLOCK_DE");  
+      
+      // expressions do not work on binary signature fields without phlength setting!!
+      sp.setProfileOverrideValue("SIG_META", "It's nice to be important, but it is more important to be nice ${subject.L}");;
+      sp.setProfileOverrideValue("SIG_LABEL", "./images/signatur-logo_en.png");                  
+      
+      // execute sign using the overrides
+      pdfAs.sign(sp);
+  
+ *

+ * @param key the name of the setting to override e.g. "SIG_META" + * @param value The new value + */ + public void setProfileOverrideValue(String key, String value) { + if (SignatureTypes.isRequredSigTypeKey(key)) { + throw new RuntimeException("cannot set value for pre defined signature field names"); + } + this.overrideProps.put(key, value); + } + + /** + * Get override values created via {@link #setProfileOverrideValue(String, String)} + * @return + */ + public Properties getProfileOverrideProperties() { + return this.overrideProps; + + } + + /** + * Get the value of the checkForPlaceholder flag. + * + * @return + */ + public Boolean isCheckForPlaceholder() { + return this.checkForPlaceholder; + } + + /** + * Set this to true, if you want a search for placeholder images to be performed and + * appropriate images to be replaced. + * If this is not set, a search will only be performed if the configuration property "enable_placeholder_search" is set to true. + * + * @param check + */ + public void setCheckForPlaceholder(boolean check) { + this.checkForPlaceholder = Boolean.valueOf(check); + } + + /** + * Set an explicit placeholder id. + * Only placeholder images that have a matching ID property embedded will be considered for replacement. + * + * @param placeholderId + */ + public void setPlaceholderId(String placeholderId) { + this.placeholderId = placeholderId; + } + + /** + * The id of the placeholder to replace. + * + * @return the placeholderId + */ + public String getPlaceholderId() { + return placeholderId; + } + + /** + * Set the behavior if no exactly matching placeholder could be found.
+ * Exactly matching meaning:
+ *
  • If a placeholderId is set: a placeholder which has exactly this id embedded
  • + *
  • If no placeholderId is set: a placeholder without an embedded id is found
+ * + * @see Constants#PLACEHOLDER_MATCH_MODE_LENIENT + * @see Constants#PLACEHOLDER_MATCH_MODE_MODERATE + * @see Constants#PLACEHOLDER_MATCH_MODE_STRICT + * + * Defaults to {@link Constants#PLACEHOLDER_MATCH_MODE_MODERATE}. + * + * @param placeholderMatchMode + */ + public void setPlaceholderMatchMode(int placeholderMatchMode) { + this.placeholderMatchMode = placeholderMatchMode; + } + + /** + * Get the placeholder matching mode. + * + * @see SignParameters#getPlaceholderMatchMode() + * @return the placeholderMatchMode + */ + public int getPlaceholderMatchMode() { + return this.placeholderMatchMode; + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/SignResult.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/SignResult.java new file mode 100644 index 0000000..fa0282f --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/SignResult.java @@ -0,0 +1,84 @@ +/** + * 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.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.pos.SignaturePosition; + +/** + * The result of a sign operation. + * + * @author wprinz + */ +public interface SignResult +{ + + /** + * Returns the filled output data sink. + * + * @return Returns the filled output data sink. + */ + public DataSink getOutputDocument(); + + /** + * Returns the certificate of the signer. + * + * @return Returns the certificate of the signer. + */ + public X509Certificate getSignerCertificate(); + + /** + * Returns the position where the signature is finally placed. + * + *

+ * This information can be useful for post-processing the document. + *

+ * + *

+ * Consult the PDF-AS documentation section Commandline for further + * information about positioning. + *

+ * + * @return Returns the position where the signature is finally placed. May + * return null if no position information is available. + */ + public SignaturePosition getSignaturePosition(); + + /** + * Returns a list<{@link NonTextObjectInfo} of non textual objects in the pdf document. + * Only available for textual signatures. Show this to the user who signed the textual content only! + * @return List<{@link NonTextObjectInfo} or null of not available (binary signature) + */ + public List getNonTextualObjects(); + + /** + * Returns if pdf has non textual objects (only for textual signature available). + * @return + */ + public boolean hasNonTextualObjects(); +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/SignatureDetailInformation.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/SignatureDetailInformation.java new file mode 100644 index 0000000..c5a0263 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/SignatureDetailInformation.java @@ -0,0 +1,147 @@ +/** + * 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.api.sign; + +import java.security.cert.X509Certificate; +import java.util.Date; +import java.util.List; +import java.util.Map; + +import at.gv.egiz.pdfas.api.analyze.NonTextObjectInfo; +import at.gv.egiz.pdfas.api.io.DataSource; +import at.gv.egiz.pdfas.api.sign.pos.SignaturePosition; + +/** + * A container for all relevant signature related data. + * + * @author exthex + */ +public interface SignatureDetailInformation +{ + public DataSource getSignatureData(); + + /** + * Returns the position where the signature table was actually placed. + * + * @return Returns the position where the signature table was actually placed. + */ + public SignaturePosition getSignaturePosition(); + + /** + * Returns a list<{@link NonTextObjectInfo} of non textual objects in the pdf document. + * Only available for textual signatures. Show this to the user who signed the textual content only! + * @return List<{@link NonTextObjectInfo} or null of not available (binary signature) + */ + public List getNonTextualObjects(); + + /** + * Returns the date of signature extracted from the signature. + * @return + */ + public Date getSignDate(); + + /** + * Get the name of the issuer. + * Short for {@link SignatureDetailInformation#getX509Certificate()#getIssuer()#getName()} + * + * @return + */ + public String getIssuer(); + + /** + * Short for {@link SignatureDetailInformation#getX509Certificate()#getIssuerDNMap()} + * + * @return + */ + public Map getIssuerDNMap(); + + /** + * Short for {@link SignatureDetailInformation#getX509Certificate()#getSubjectName()#toString()} + * + * @return + */ + public String getSubjectName(); + + /** + * Short for {@link SignatureDetailInformation#getX509Certificate()#getSerialNumber()#toString()} + * + * @return + */ + public String getSerialNumber(); + + /** + * Get the algorithm the signature was created with. + * @return + */ + public String getSigAlgorithm(); + + /** + * + * @return the signature id. + */ + public String getSigID(); + + /** + * + * @return the signature method. + */ + public String getSigKZ(); + + /** + * + * @return the signature value. + */ + public String getSignatureValue(); + + /** + * + * @return the signature time stamp. + */ + public String getSigTimeStamp(); + + /** + * Short for {@link SignatureDetailInformation#getX509Certificate()#getSubjectDNMap()} + * + * @return + */ + public Map getSubjectDNMap(); + + /** + * + * @return the certificate used for signature. + */ + public X509Certificate getX509Certificate(); + + /** + * + * @return true if the signature is textual, false otherwise. + */ + public boolean isTextual(); + + /** + * + * @return true if this signature is binary, false otherwise. + */ + public boolean isBinary(); +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/SignaturePosition.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/SignaturePosition.java new file mode 100644 index 0000000..eee62cd --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/SignaturePosition.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.api.sign.pos; + +/** + * Holds the actual, absolute signature position where a signature was placed. + * + *

+ * This is usually returned after signing. + *

+ * + * @author wprinz + */ +public interface SignaturePosition +{ + /** + * Returns the page on which the signature was placed. + * + * @return Returns the page on which the signature was placed. + */ + public int getPage(); + + /** + * Returns the x position. + * + * @return Returns the x position. + */ + public float getX(); + + /** + * Returns the y position. + * + * @return Returns the y position. + */ + public float getY(); + + /** + * Returns the width of the signature. + * + * @return Returns the width of the signature. + */ + public float getWidth(); + + /** + * Returns the height of the signature. + * + * @return Returns the height of the signature. + */ + public float getHeight(); + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/SignaturePositioning.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/SignaturePositioning.java new file mode 100644 index 0000000..d46c3f2 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/SignaturePositioning.java @@ -0,0 +1,296 @@ +/** + * 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.api.sign.pos; + +import java.io.Serializable; +import java.util.StringTokenizer; + +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.gv.egiz.pdfas.exceptions.ErrorCode; +import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException; + +/** + * Defines how the signature positioning is to be performed. + * + *

+ * This positioning allows to select the location where the signature block is + * placed in the document. + *

+ * + * @author wprinz + */ +public class SignaturePositioning implements Serializable +{ + + /** + * + */ + private static final long serialVersionUID = 1L; + + /** + * The x axis algorithm. + * + *

+ * May be {@link AutoAxisAlgorithm} or {@link AbsoluteAxisAlgorithm} + *

+ */ + protected AxisAlgorithm xAlgorithm = new AutoAxisAlgorithm(); + + /** + * The y axis algorithm. + * + *

+ * May be {@link AutoAxisAlgorithm} or {@link AbsoluteAxisAlgorithm} + *

+ */ + protected AxisAlgorithm yAlgorithm = new AutoAxisAlgorithm(); + + /** + * The width algorithm. + * + *

+ * May be {@link AutoAxisAlgorithm} or {@link AbsoluteAxisAlgorithm} + *

+ */ + protected AxisAlgorithm widthAlgorithm = new AutoAxisAlgorithm(); + + /** + * The page algorithm. + * + *

+ * May be {@link AutoPageAlgorithm}, {@link AbsolutePageAlgorithm} or + * {@link NewPageAlgorithm} + *

+ */ + protected PageAlgorithm pageAlgorithm = new AutoPageAlgorithm(); + + /** + * Provides the position of the footline. + * + *

+ * Only used if the pageAlgorithm is {@link AutoPageAlgorithm} and the + * yAlgorithm is {@link AutoAxisAlgorithm} + *

+ */ + protected float footerLine = 0.0f; + + protected void checkAxisAlgorithm(AxisAlgorithm algorithm) + { + if (algorithm == null) + { + throw new IllegalArgumentException("The algorithm must not be null."); + } + if (!(algorithm instanceof AutoAxisAlgorithm) && !(algorithm instanceof AbsoluteAxisAlgorithm)) + { + throw new IllegalArgumentException("The algorithm must be either Auto or Absolute."); + } + } + + protected void checkPageAlgorithm(PageAlgorithm algorithm) + { + if (algorithm == null) + { + throw new IllegalArgumentException("The algorithm must not be null."); + } + if (!(algorithm instanceof AutoPageAlgorithm) && !(algorithm instanceof AbsolutePageAlgorithm) && !(algorithm instanceof NewPageAlgorithm)) + { + throw new IllegalArgumentException("The algorithm must be either Auto or Absolute."); + } + + } + + /** + * @return the xAlgorithm + */ + public AxisAlgorithm getXAlgorithm() + { + return this.xAlgorithm; + } + + /** + * @param algorithm + * the xAlgorithm to set + */ + public void setXAlgorithm(AxisAlgorithm algorithm) + { + checkAxisAlgorithm(algorithm); + xAlgorithm = algorithm; + } + + /** + * @return the yAlgorithm + */ + public AxisAlgorithm getYAlgorithm() + { + return this.yAlgorithm; + } + + /** + * @param algorithm + * the yAlgorithm to set + */ + public void setYAlgorithm(AxisAlgorithm algorithm) + { + checkAxisAlgorithm(algorithm); + + yAlgorithm = algorithm; + } + + /** + * @return the widthAlgorithm + */ + public AxisAlgorithm getWidthAlgorithm() + { + return this.widthAlgorithm; + } + + /** + * @param widthAlgorithm + * the widthAlgorithm to set + */ + public void setWidthAlgorithm(AxisAlgorithm widthAlgorithm) + { + checkAxisAlgorithm(widthAlgorithm); + + this.widthAlgorithm = widthAlgorithm; + } + + /** + * @return the pageAlgorithm + */ + public PageAlgorithm getPageAlgorithm() + { + return this.pageAlgorithm; + } + + /** + * @param pageAlgorithm + * the pageAlgorithm to set + */ + public void setPageAlgorithm(PageAlgorithm pageAlgorithm) + { + checkPageAlgorithm(pageAlgorithm); + this.pageAlgorithm = pageAlgorithm; + } + + /** + * @return the footerLine + */ + public float getFooterLine() + { + return this.footerLine; + } + + /** + * @param footerLine + * the footerLine to set + */ + public void setFooterLine(float footerLine) + { + this.footerLine = footerLine; + } + + public SignaturePositioning() { + } + + public SignaturePositioning(String position) throws PDFDocumentException { + if (position != null) { + StringTokenizer tokenizer = new StringTokenizer(position, ";"); + while (tokenizer.hasMoreTokens()) { + String token = tokenizer.nextToken().replaceAll(" ", ""); + String[] sToken = token.split(":"); + if (sToken == null || sToken.length != 2 || sToken[0].length() != 1) { + throw new PDFDocumentException(ErrorCode.INVALID_SIGNATURE_POSITION, "Invalid signature position element: " + token); + } + char cmd = sToken[0].toLowerCase().charAt(0); + String value = sToken[1]; + switch (cmd) { + case 'x': + if ("auto".equalsIgnoreCase(value)) { + this.setXAlgorithm(new AutoAxisAlgorithm()); + } else { + try { + this.setXAlgorithm(new AbsoluteAxisAlgorithm(Float.parseFloat(value))); + } catch (NumberFormatException e) { + throw new PDFDocumentException(ErrorCode.INVALID_SIGNATURE_POSITION, "Invalid signature position element: " + token); + } + } + break; + case 'y': + if ("auto".equalsIgnoreCase(value)) { + this.setYAlgorithm(new AutoAxisAlgorithm()); + } else { + try { + this.setYAlgorithm(new AbsoluteAxisAlgorithm(Float.parseFloat(value))); + } catch (NumberFormatException e) { + throw new PDFDocumentException(ErrorCode.INVALID_SIGNATURE_POSITION, "Invalid signature position element: " + token); + } + } + break; + case 'w': + if ("auto".equalsIgnoreCase(value)) { + this.setWidthAlgorithm(new AutoAxisAlgorithm()); + } else { + try { + this.setWidthAlgorithm(new AbsoluteAxisAlgorithm(Float.parseFloat(value))); + } catch (NumberFormatException e) { + throw new PDFDocumentException(ErrorCode.INVALID_SIGNATURE_POSITION, "Invalid signature position element: " + token); + } + } + break; + case 'p': + if ("auto".equalsIgnoreCase(value)) { + this.setPageAlgorithm(new AutoPageAlgorithm()); + } else if ("new".equalsIgnoreCase(value)) { + this.setPageAlgorithm(new NewPageAlgorithm()); + } else { + try { + this.setPageAlgorithm(new AbsolutePageAlgorithm(Integer.parseInt(value))); + } catch (NumberFormatException e) { + throw new PDFDocumentException(ErrorCode.INVALID_SIGNATURE_POSITION, "Invalid signature position element: " + token); + } + } + break; + case 'f': + try { + this.setFooterLine(Float.parseFloat(value)); + } catch (NumberFormatException e) { + throw new PDFDocumentException(ErrorCode.INVALID_SIGNATURE_POSITION, "Invalid signature position element: " + token); + } + break; + default: + throw new PDFDocumentException(ErrorCode.INVALID_SIGNATURE_POSITION, "Invalid signature position element: " + token); + } + } + } + } + + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/axis/AbsoluteAxisAlgorithm.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/axis/AbsoluteAxisAlgorithm.java new file mode 100644 index 0000000..ea2143d --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/axis/AbsoluteAxisAlgorithm.java @@ -0,0 +1,62 @@ +/** + * 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.api.sign.pos.axis; + +import java.io.Serializable; + +/** + * An absolute positioned element. + * @author wprinz + */ +public class AbsoluteAxisAlgorithm extends AxisAlgorithm implements Serializable +{ + + /** + * + */ + private static final long serialVersionUID = 1L; + + /** + * The absolute positioning value on the axis. + */ + protected float absoluteValue = 0.0f; + + /** + * Constructor. + * @param absoluteValue The absolute positioning value on the axis. + */ + public AbsoluteAxisAlgorithm (float absoluteValue) + { + this.absoluteValue = absoluteValue; + } + + /** + * Returns absolute positioning value on the axis. + * @return the absoluteValue Returns absolute positioning value on the axis. + */ + public float getAbsoluteValue() + { + return this.absoluteValue; + } +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/axis/AutoAxisAlgorithm.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/axis/AutoAxisAlgorithm.java new file mode 100644 index 0000000..a9857b4 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/axis/AutoAxisAlgorithm.java @@ -0,0 +1,41 @@ +/** + * 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.api.sign.pos.axis; + +import java.io.Serializable; + +/** + * Auto positioning for this element. + * + * @author wprinz + */ +public class AutoAxisAlgorithm extends AxisAlgorithm implements Serializable +{ + + /** + * + */ + private static final long serialVersionUID = 1L; +// empty +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/axis/AxisAlgorithm.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/axis/AxisAlgorithm.java new file mode 100644 index 0000000..dd1d170 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/axis/AxisAlgorithm.java @@ -0,0 +1,41 @@ +/** + * 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.api.sign.pos.axis; + +import java.io.Serializable; + +/** + * Determines how a certain position is chosen on the axis (x, y, width). + * + * @author wprinz + */ +public abstract class AxisAlgorithm implements Serializable +{ + + /** + * + */ + private static final long serialVersionUID = 1L; +// base class +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/AbsolutePageAlgorithm.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/AbsolutePageAlgorithm.java new file mode 100644 index 0000000..434c20c --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/AbsolutePageAlgorithm.java @@ -0,0 +1,64 @@ +/** + * 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.api.sign.pos.page; + +import java.io.Serializable; + +/** + * The page is selected absolutely by giving the page number directly. + * + * @author wprinz + */ +public class AbsolutePageAlgorithm extends PageAlgorithm implements Serializable +{ + /** + * + */ + private static final long serialVersionUID = 1L; + + /** + * The page. + */ + protected int page = -1; + + /** + * Constructor. + * + * @param page + * The page. + */ + public AbsolutePageAlgorithm(int page) + { + this.page = page; + } + + /** + * @return the page + */ + public int getPage() + { + return this.page; + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/AutoPageAlgorithm.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/AutoPageAlgorithm.java new file mode 100644 index 0000000..fffcbad --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/AutoPageAlgorithm.java @@ -0,0 +1,47 @@ +/** + * 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.api.sign.pos.page; + +import java.io.Serializable; + +/** + * The page for placing the signature is selected automatically. + * + *

+ * The algorithm first tries to place the signature on the free space of the + * last page (considering the footer). If there is not enough space on the last + * page, a new page is appended and the signature is placed there. + *

+ * + * @author wprinz + */ +public class AutoPageAlgorithm extends PageAlgorithm implements Serializable +{ + + /** + * + */ + private static final long serialVersionUID = 1L; +// empty +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/NewPageAlgorithm.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/NewPageAlgorithm.java new file mode 100644 index 0000000..ded9f61 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/NewPageAlgorithm.java @@ -0,0 +1,41 @@ +/** + * 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.api.sign.pos.page; + +import java.io.Serializable; + +/** + * Places the signature on a new Page. + * + * @author wprinz + */ +public class NewPageAlgorithm extends PageAlgorithm implements Serializable +{ + + /** + * + */ + private static final long serialVersionUID = 1L; + // empty block +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/PageAlgorithm.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/PageAlgorithm.java new file mode 100644 index 0000000..16aa72c --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/PageAlgorithm.java @@ -0,0 +1,41 @@ +/** + * 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.api.sign.pos.page; + +import java.io.Serializable; + +/** + * Determines how the page on which the signature is to be placed is selected. + * + * @author wprinz + */ +public abstract class PageAlgorithm implements Serializable +{ + + /** + * + */ + private static final long serialVersionUID = 1L; + // empty +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/timestamp/DummyTimeStamper.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/timestamp/DummyTimeStamper.java new file mode 100644 index 0000000..f3944da --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/timestamp/DummyTimeStamper.java @@ -0,0 +1,62 @@ +/** + * 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.api.timestamp; + +import java.util.Date; + +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.lang.time.DateFormatUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Dummy/test implementation of the timestamper. Logs and stores test-timestamp for assertion {@link #getLastTimeStamp()} + * + * @author dferbas + * + */ +public class DummyTimeStamper implements TimeStamper { + private static Log log = LogFactory.getLog(DummyTimeStamper.class); + + private String lastTimeStamp; + + public String applyTimeStamp(String b64SignatureValue) { + log.debug("Applying dummy timestamp on signature value: " + b64SignatureValue); + String ts = DateFormatUtils.format(new Date(), "yyyy-MM-dd'T'hh:mm:ss.SSSZ"); + log.debug("Timestamp: " + ts); + ts = new String(Base64.encodeBase64(ts.getBytes())); + log.debug("Timestamp value (base64): " + ts); + this.lastTimeStamp = ts; + return ts; + } + + public String getLastTimeStamp() { + return this.lastTimeStamp; + } + + public void setLastTimeStamp(String lastTimeStamp) { + this.lastTimeStamp = lastTimeStamp; + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/timestamp/TimeStamper.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/timestamp/TimeStamper.java new file mode 100644 index 0000000..99bda3a --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/timestamp/TimeStamper.java @@ -0,0 +1,41 @@ +/** + * 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.api.timestamp; + +/** + * Interface for timestamper implementations/handlers + * + * @author dferbas + * + */ +public interface TimeStamper { + + /** + * Implement timestamp in this method. + * @param b64SignatureValue signature value, base64 encoded + * @return timestamp to be embedded in egiz dictionary base64 encoded (following RFC3161). + */ + public String applyTimeStamp(String b64SignatureValue); + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/verify/SignatureCheck.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/verify/SignatureCheck.java new file mode 100644 index 0000000..c169077 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/verify/SignatureCheck.java @@ -0,0 +1,51 @@ +/** + * 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.api.verify; + +/** + * The result of a signature check performed by a verification device. + * + * @see VerifyResult + * + * @author wprinz + */ +public interface SignatureCheck +{ + /** + * Returns the response code of the check. + * + * @return Returns the response code of the check. + */ + public int getCode(); + + /** + * Returns the textual response message of the check (corresponding to the + * code). + * + * @return Returns the textual response message of the check (corresponding to + * the code). + */ + public String getMessage(); + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyAfterAnalysisParameters.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyAfterAnalysisParameters.java new file mode 100644 index 0000000..8b9e2c6 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyAfterAnalysisParameters.java @@ -0,0 +1,166 @@ +/** + * 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.api.verify; + +import java.util.Date; + +import at.gv.egiz.pdfas.api.analyze.AnalyzeResult; +import at.gv.egiz.pdfas.api.commons.Constants; + +/** + * Parameter object that holds the verify after analysis parameters. + * + * @author wprinz + */ +public class VerifyAfterAnalysisParameters +{ + + /** + * The list of signatures to be verified. + */ + protected AnalyzeResult analyzeResult = null; + + /** + * The signature device to perform the actual signature. + * + *

+ * May be {@link Constants#SIGNATURE_DEVICE_MOA} or + * {@link Constants#SIGNATURE_DEVICE_BKU}. + *

+ */ + protected String signatureDevice = Constants.SIGNATURE_DEVICE_MOA; + + /** + * Allows to pass a VerificationTime to the signature device. + */ + protected Date verificationTime = null; + + /** + * Tells the signature device (e.g. MOA) to return the signature hash input + * data (which is the probably transformed signed data). + * + *

+ * Note that this forces MOA to return the potentially large signature data to + * be returned in the result XML, which may result in very bad performance. + *

+ */ + protected boolean returnHashInputData = false; + + /** + * The index of the signature to be verified. A value < 0 indicates to verify all signatures. + */ + protected int verifySignatureIndex = -1; + + /** + * @return the analyzeResult + */ + public AnalyzeResult getAnalyzeResult() + { + return this.analyzeResult; + } + + /** + * @param analyzeResult + * the analyzeResult to set + */ + public void setAnalyzeResult(AnalyzeResult analyzeResult) + { + this.analyzeResult = analyzeResult; + } + + /** + * @return the signatureDevice + */ + public String getSignatureDevice() + { + return this.signatureDevice; + } + + /** + * @param signatureDevice + * the signatureDevice to set + */ + public void setSignatureDevice(String signatureDevice) + { + this.signatureDevice = signatureDevice; + } + + /** + * @return the verificationTime + */ + public Date getVerificationTime() + { + return this.verificationTime; + } + + /** + * @param verificationTime the verificationTime to set + */ + public void setVerificationTime(Date verificationTime) + { + this.verificationTime = verificationTime; + } + + /** + * @return the returnHashInputData + */ + public boolean isReturnHashInputData() + { + return this.returnHashInputData; + } + + /** + * @param returnHashInputData + * the returnHashInputData to set + */ + public void setReturnHashInputData(boolean returnHashInputData) + { + this.returnHashInputData = returnHashInputData; + } + + /** + * Set the index of the signature to verify (index starting at 0). A value < 0 indicates to verify all values. + * @param verify_which + */ + public void setVerifySignatureIndex(int verify_which) { + this.verifySignatureIndex = verify_which; + } + + public int getVerifySignatureIndex() { + return verifySignatureIndex; + } + + /** + * @see VerifyParameters#setSuppressVerifyExceptions(boolean) + * @param suppress + */ + public void setSuppressVerifyExceptions(boolean suppress) { + VerifyParameters.setSuppressVerify(suppress); + } + + public boolean isSuppressVerifyExceptions() { + return VerifyParameters.isSuppressVerifyExceptions(); + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyAfterReconstructXMLDsigParameters.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyAfterReconstructXMLDsigParameters.java new file mode 100644 index 0000000..8f8d17c --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyAfterReconstructXMLDsigParameters.java @@ -0,0 +1,169 @@ +/** + * 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.api.verify; + +import java.util.Date; + +import at.gv.egiz.pdfas.api.commons.Constants; +import at.gv.egiz.pdfas.api.xmldsig.ReconstructXMLDsigResult; + +/** + * This class represents the parameters needed for verify after reconstructXMLDsig has already been executed. + * + * @author exthex + * + */ +public class VerifyAfterReconstructXMLDsigParameters { + + /** + * The list of signatures to be verified. + */ + protected ReconstructXMLDsigResult reconstructXMLDsigResult = null; + + /** + * The signature device to perform the actual signature. + * + *

+ * May be {@link Constants#SIGNATURE_DEVICE_MOA} or + * {@link Constants#SIGNATURE_DEVICE_BKU}. + *

+ */ + protected String signatureDevice; + + /** + * Allows to pass a VerificationTime to the signature device. + */ + protected Date verificationTime = null; + + /** + * Tells the signature device (e.g. MOA) to return the signature hash input + * data (which is the probably transformed signed data). + * + *

+ * Note that this forces MOA to return the potentially large signature data to + * be returned in the result XML, which may result in very bad performance. + *

+ */ + protected boolean returnHashInputData = false; + + /** + * The index of the signature to be verified. A value < 0 indicates to verify all signatures. + */ + protected int verifySignatureIndex = -1; + + /** + * @return the reconstructXMLDsigResult + */ + public ReconstructXMLDsigResult getReconstructXMLDsigResult() + { + return this.reconstructXMLDsigResult; + } + + /** + * @param reconstructXMLDsigResult + * the reconstructXMLDsigResult to set + */ + public void setReconstructXMLDsigResult(ReconstructXMLDsigResult reconstructXMLDsigResult) + { + this.reconstructXMLDsigResult = reconstructXMLDsigResult; + } + + /** + * @return the signatureDevice + */ + public String getSignatureDevice() + { + return this.signatureDevice; + } + + /** + * Set the signature device to use for verification. + * If none is set here, the signature device that was used for reconstructXMLDsig will be used. + * + * @param signatureDevice + * the signatureDevice to set + */ + public void setSignatureDevice(String signatureDevice) + { + this.signatureDevice = signatureDevice; + } + + /** + * @return the verificationTime + */ + public Date getVerificationTime() + { + return this.verificationTime; + } + + /** + * @param verificationTime the verificationTime to set + */ + public void setVerificationTime(Date verificationTime) + { + this.verificationTime = verificationTime; + } + + /** + * @return the returnHashInputData + */ + public boolean isReturnHashInputData() + { + return this.returnHashInputData; + } + + /** + * @param returnHashInputData + * the returnHashInputData to set + */ + public void setReturnHashInputData(boolean returnHashInputData) + { + this.returnHashInputData = returnHashInputData; + } + + /** + * Set the index of the signature to verify (index starting at 0). A value < 0 indicates to verify all values. + * @param verify_which + */ + public void setVerifySignatureIndex(int verify_which) { + this.verifySignatureIndex = verify_which; + } + + public int getVerifySignatureIndex() { + return verifySignatureIndex; + } + + /** + * @see VerifyParameters#setSuppressVerifyExceptions(boolean) + * @param suppress + */ + public void setSuppressVerifyExceptions(boolean suppress) { + VerifyParameters.setSuppressVerify(suppress); + } + + public boolean isSuppressVerifyExceptions() { + return VerifyParameters.isSuppressVerifyExceptions(); + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyParameters.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyParameters.java new file mode 100644 index 0000000..e7301dc --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyParameters.java @@ -0,0 +1,249 @@ +/** + * 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.api.verify; + +import java.util.Date; + +import at.gv.egiz.pdfas.api.commons.Constants; +import at.gv.egiz.pdfas.api.io.DataSource; + +/** + * Parameter object that holds the verify parameters. + * + * @author wprinz + */ +public class VerifyParameters +{ + // This would be a perfect point for multiple inheritance in Java. + // VerifyParameters extends AnalyzeParameters, VerifyAfterAnalysisParameters + // Then a lot of code could be easily reused in the PdfAsObject's check*Parameters methods. + + /** + * The document to be verified. + */ + protected DataSource document = null; + + /** + * The signature device to perform the actual signature. + * + *

+ * May be {@link Constants#SIGNATURE_DEVICE_MOA} or + * {@link Constants#SIGNATURE_DEVICE_BKU}. + *

+ */ + protected String signatureDevice = Constants.SIGNATURE_DEVICE_MOA; + + /** + * The mode of operation how the document is analyzed. + * + *

+ * May be {@link Constants#VERIFY_MODE_BINARY_ONLY} to check the document for + * binary signatures only (very fast). Or may be + * {@link Constants#VERIFY_MODE_SEMI_CONSERVATIVE} to perform a semi + * conservative (optimized) text and binary verification (slow). Or may be + * {@link Constants#VERIFY_MODE_FULL_CONSERVATIVE} to perform a full + * conservative text and binary verification (very slow). + *

+ */ + protected String verifyMode = Constants.VERIFY_MODE_FULL_CONSERVATIVE; + + /** + * The (zero based) index of the signature to verify. + * + *

+ * This allows to verify only one found signature instead of all. {@link Constants#VERIFY_ALL} means to + * verify all found signatures. + *

+ */ + protected int signatureToVerify = Constants.VERIFY_ALL; + + /** + * Allows to pass a VerificationTime to the verification device. + * + *

+ * Note that the actual usage of this parameter depends on the verification device. + *

+ */ + protected Date verificationTime = null; + + /** + * Tells the signature device (e.g. MOA) to return the signature hash input + * data (which is the probably transformed signed data). + * + *

+ * Note that this forces MOA to return the potentially large signature data to + * be returned in the result XML, which may result in very bad performance. + *

+ */ + protected boolean returnHashInputData = false; + + protected boolean returnNonTextualObjects = false; + + private static ThreadLocal suppressVerifyExceptions = new ThreadLocal(); + + + public VerifyParameters() { + suppressVerifyExceptions.set(Boolean.FALSE); + } + /** + * @return the document + */ + public DataSource getDocument() + { + return this.document; + } + + /** + * @param document + * the document to set + */ + public void setDocument(DataSource document) + { + this.document = document; + } + + /** + * @return the signatureDevice + */ + public String getSignatureDevice() + { + return this.signatureDevice; + } + + /** + * @param signatureDevice + * the signatureDevice to set + */ + public void setSignatureDevice(String signatureDevice) + { + this.signatureDevice = signatureDevice; + } + + /** + * @return the verifyMode + */ + public String getVerifyMode() + { + return this.verifyMode; + } + + /** + * @param verifyMode + * the verifyMode to set + */ + public void setVerifyMode(String verifyMode) + { + this.verifyMode = verifyMode; + } + + /** + * @return the signatureToVerify + */ + public int getSignatureToVerify() + { + return this.signatureToVerify; + } + + /** + * @param signatureToVerify + * the signatureToVerify to set + */ + public void setSignatureToVerify(int signatureToVerify) + { + this.signatureToVerify = signatureToVerify; + } + + /** + * @return the verificationTime + */ + public Date getVerificationTime() + { + return this.verificationTime; + } + + /** + * @param verificationTime + * the verificationTime to set + */ + public void setVerificationTime(Date verificationTime) + { + this.verificationTime = verificationTime; + } + + /** + * @return the returnHashInputData + */ + public boolean isReturnHashInputData() + { + return this.returnHashInputData; + } + + /** + * @param returnHashInputData + * the returnHashInputData to set + */ + public void setReturnHashInputData(boolean returnHashInputData) + { + this.returnHashInputData = returnHashInputData; + } + + public boolean isReturnNonTextualObjects() { + return this.returnNonTextualObjects; + } + + /** + * Tells if non text object of the signed pdf should be extracted and returned. + * One should show this to the user, especially in case of textual signature. + * Defaults to false + * + * @param returnNonTextualObjects + */ + public void setReturnNonTextualObjects(boolean returnNonTextualObjects) { + this.returnNonTextualObjects = returnNonTextualObjects; + } + + /** + * Set if verify exceptions (because of unknown signatures) are suppressed or not (default). + * Suppressing can be helpful for multiple signatures if you want to verify the working rest. Unsupported + * Signatures are reported without throwing an exception via {@link VerifyResult#getVerificationException()} + * @param suppress + */ + public void setSuppressVerifyExceptions(boolean suppress) { + setSuppressVerify(suppress); + } + + /** + * See {@link #setSuppressVerifyExceptions(boolean)} + * @return + */ + public static boolean isSuppressVerifyExceptions() { + if (suppressVerifyExceptions.get() == null) return false; + return ((Boolean) suppressVerifyExceptions.get()).booleanValue(); + } + + static void setSuppressVerify(boolean suppress) { + suppressVerifyExceptions.set(new Boolean(suppress)); + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyResult.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyResult.java new file mode 100644 index 0000000..fb48e5e --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyResult.java @@ -0,0 +1,179 @@ +/** + * 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.api.verify; + +import java.util.Date; +import java.util.List; + +import at.gv.egiz.pdfas.api.PdfAs; +import at.gv.egiz.pdfas.api.analyze.NonTextObjectInfo; +import at.gv.egiz.pdfas.api.commons.SignatureInformation; +import at.gv.egiz.pdfas.api.exceptions.PdfAsException; +import at.gv.egiz.pdfas.api.xmldsig.XMLDsigData; + +/** + * Encapsulates the data of a verification of one signature. + * + * @author wprinz + */ +public interface VerifyResult extends SignatureInformation +{ + /** + * Returns if the verification was possible or could not even be startet. see {@link #getVerificationException()} for details. + * @return + */ + public boolean isVerificationDone(); + + /** + * Returns a verification exception if any. Shows that the verification could not be started. See {@link #isVerificationDone()}. + * @return + */ + public PdfAsException getVerificationException(); + + /** + * Returns the result of the certificate check. + * + * @return Returns the result of the certificate check. + */ + public SignatureCheck getCertificateCheck(); + + /** + * Returns the result of the value (and hash) check. + * + * @return Returns the result of the value (and hash) check. + */ + public SignatureCheck getValueCheckCode(); + + /** + * Returns the result of the manifest check. + * + * @return Returns the result of the manifest check. + */ + public SignatureCheck getManifestCheckCode(); + + /** + * Returns true, if the signer's certificate is a qualified certificate. + * + * @return Returns true, if the signer's certificate is a qualified + * certificate. + */ + public boolean isQualifiedCertificate(); + + /** + * Returns {@code true} if public authority is indicated. + * @return {@code true} if public authority. + */ + public boolean isPublicAuthority(); + + /** + * Returns the public authority code or {@code null}. + * @return The public authority code or {@code null}. + */ + public String getPublicAuthorityCode(); + + /** + * Returns a list of Strings each stating one public property of the + * certificate. + * + *

+ * Such public properties are certificate extensions each being assigned an + * own OID. For example the public property "Verwaltungseigenschaft" has the + * OID "1.2.40.0.10.1.1.1". + *

+ * + * @return Returns the list of Strings representing the public properties of + * this certificate, if any. + */ + public List getPublicProperties(); + + /** + * Returns the verification time, which is the time when the signature was + * verified. + * + *

+ * Note that this is actually the Date passed to the verify methods over + * {@link VerifyParameters#setVerificationTime(Date)} or + * {@link VerifyAfterAnalysisParameters#setVerificationTime(Date)}. The + * signature devices don't respond the actual verification time so there is no + * guarantee that the set verification time was actually used as time of + * verification. Please consult the device's documentation for more + * information. + *

+ *

+ * If the verification device does not return a verification time and no + * verification time was set in the + * {@link VerifyParameters#setVerificationTime(Date)} or + * {@link VerifyAfterAnalysisParameters#setVerificationTime(Date)}, the time + * returned by this method will be equal to the signing time ( + * {@link SignatureInformation#getSigningTime()}). + *

+ * + * @return Returns the verification time, which is the time when the signature + * was verified. + */ + public Date getVerificationTime(); + + /** + * Returns the hash input data as returned by MOA as Base64-encoded String. + * + *

+ * This will only return a value other than null if the corresponding + * {@link VerifyParameters} has been set to true. + *

+ *

+ * Note that the HashInputData does not necessarily have to be exactly the + * same as the signed data return by the + * {@link SignatureInformation#getSignedData()} method. + *

+ * + * @return Returns the base64 encoded hash input data as returned by MOA. + * + * @see SignatureInformation#getSignedData() + */ + public String getHashInputData(); + + /** + * Returns a list<{@link NonTextObjectInfo}> of non textual objects in the pdf document. + * Only available for textual signatures. Show this to the user who signed the textual content only! + * @return List<{@link NonTextObjectInfo} or null of not available (binary signature) + */ + public List getNonTextualObjects(); + + + /** + * Returns true if non textual objects have been found, false if not. + * @return true if non textual objects have been found, false if not. + */ + public boolean hasNonTextualObjects(); + + /** + * Get the reconstructed xmldsig XML data. The reconstruction is done during the verification process. + * + * @see PdfAs#reconstructXMLDSIG(at.gv.egiz.pdfas.api.xmldsig.ReconstructXMLDsigParameters) + * @see PdfAs#reconstructXMLDSIG(at.gv.egiz.pdfas.api.xmldsig.ReconstructXMLDsigAfterAnalysisParameters) + * @return + */ + public XMLDsigData getReconstructedXMLDsig(); + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyResults.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyResults.java new file mode 100644 index 0000000..44b62a7 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyResults.java @@ -0,0 +1,48 @@ +/** + * 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.api.verify; + +import java.util.List; + +/** + * The result of the verification of a document. + * + *

+ * Currently, this is not more than a list of VerifyResult objects, one for each + * verified signature. There may be additional items in future PDF-AS versions. + *

+ * + * @author wprinz + */ +public interface VerifyResults +{ + /** + * Returns the List of VerifyResult objects, one for each verified signature. + * + * @return Returns the List of VerifyResult objects, one for each verified + * signature. + */ + public List getResults(); + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/xmldsig/ExtendedSignatureInformation.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/xmldsig/ExtendedSignatureInformation.java new file mode 100644 index 0000000..df12b52 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/xmldsig/ExtendedSignatureInformation.java @@ -0,0 +1,69 @@ +/** + * 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.api.xmldsig; + +import at.gv.egiz.pdfas.api.commons.SignatureInformation; + +/** + * A wrapper to combine {@link SignatureInformation} and {@link XMLDsigData} + * + * @author exthex + * + */ +public class ExtendedSignatureInformation { + + private final SignatureInformation signatureInformation; + + private final XMLDsigData xmlDsigData; + + /** + * Constructor. + * + * @param siginfo + * The signature information + * @param dsigData + * The matching xmldsig to the signature information. + */ + public ExtendedSignatureInformation(SignatureInformation siginfo, XMLDsigData dsigData) { + this.signatureInformation = siginfo; + this.xmlDsigData = dsigData; + } + + /** + * + * @return the signatureInformation + */ + public SignatureInformation getSignatureInformation() { + return signatureInformation; + } + + /** + * + * @return the xmlDsigData + */ + public XMLDsigData getXmlDsigData() { + return xmlDsigData; + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/xmldsig/ReconstructXMLDsigAfterAnalysisParameters.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/xmldsig/ReconstructXMLDsigAfterAnalysisParameters.java new file mode 100644 index 0000000..229fba0 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/xmldsig/ReconstructXMLDsigAfterAnalysisParameters.java @@ -0,0 +1,86 @@ +/** + * 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.api.xmldsig; + +import at.gv.egiz.pdfas.api.analyze.AnalyzeResult; +import at.gv.egiz.pdfas.api.commons.Constants; + +/** + * Parameters for the reconstructXMLDsig method which is to be called after a analyze call. + * + * @author exthex + * + */ +public class ReconstructXMLDsigAfterAnalysisParameters { + + + /** + * The list of signatures to be verified. + */ + protected AnalyzeResult analyzeResult = null; + + /** + * The signature device to perform the actual signature. + * + *

+ * May be {@link Constants#SIGNATURE_DEVICE_MOA} or + * {@link Constants#SIGNATURE_DEVICE_BKU}. + *

+ */ + protected String signatureDevice = Constants.SIGNATURE_DEVICE_MOA; + + /** + * @return the analyzeResult + */ + public AnalyzeResult getAnalyzeResult() + { + return this.analyzeResult; + } + + /** + * @param analyzeResult + * the analyzeResult to set + */ + public void setAnalyzeResult(AnalyzeResult analyzeResult) + { + this.analyzeResult = analyzeResult; + } + + /** + * @return the signatureDevice + */ + public String getSignatureDevice() + { + return this.signatureDevice; + } + + /** + * @param signatureDevice + * the signatureDevice to set + */ + public void setSignatureDevice(String signatureDevice) + { + this.signatureDevice = signatureDevice; + } +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/xmldsig/ReconstructXMLDsigParameters.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/xmldsig/ReconstructXMLDsigParameters.java new file mode 100644 index 0000000..445d7ae --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/xmldsig/ReconstructXMLDsigParameters.java @@ -0,0 +1,218 @@ +/** + * 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.api.xmldsig; + +import java.util.Date; + +import at.gv.egiz.pdfas.api.PdfAs; +import at.gv.egiz.pdfas.api.commons.Constants; +import at.gv.egiz.pdfas.api.io.DataSource; + +/** + * Parameters for the {@link PdfAs#reconstructXMLDSIG(ReconstructXMLDsigParameters)} method. + * No need to call analyze before calling this method. + * + * @author exthex + * + */ +public class ReconstructXMLDsigParameters { + + /** + * The document to be verified. + */ + protected DataSource document = null; + + /** + * The signature device to perform the actual signature. + * + *

+ * May be {@link Constants#SIGNATURE_DEVICE_MOA} or + * {@link Constants#SIGNATURE_DEVICE_BKU}. + *

+ */ + protected String signatureDevice = Constants.SIGNATURE_DEVICE_MOA; + + /** + * The mode of operation how the document is analyzed. + * + *

+ * May be {@link Constants#VERIFY_MODE_BINARY_ONLY} to check the document for + * binary signatures only (very fast). Or may be + * {@link Constants#VERIFY_MODE_SEMI_CONSERVATIVE} to perform a semi + * conservative (optimized) text and binary verification (slow). Or may be + * {@link Constants#VERIFY_MODE_FULL_CONSERVATIVE} to perform a full + * conservative text and binary verification (very slow). + *

+ */ + protected String verifyMode = Constants.VERIFY_MODE_FULL_CONSERVATIVE; + + /** + * The (zero based) index of the signature to verify. + * + *

+ * This allows to verify only one found signature instead of all. {@link Constants#VERIFY_ALL} means to + * verify all found signatures. + *

+ */ + protected int signatureToVerify = Constants.VERIFY_ALL; + + /** + * Allows to pass a VerificationTime to the verification device. + * + *

+ * Note that the actual usage of this parameter depends on the verification device. + *

+ */ + protected Date verificationTime = null; + + /** + * Tells the signature device (e.g. MOA) to return the signature hash input + * data (which is the probably transformed signed data). + * + *

+ * Note that this forces MOA to return the potentially large signature data to + * be returned in the result XML, which may result in very bad performance. + *

+ */ + protected boolean returnHashInputData = false; + + protected boolean returnNonTextualObjects = false; + + /** + * @return the document + */ + public DataSource getDocument() + { + return this.document; + } + + /** + * @param document + * the document to set + */ + public void setDocument(DataSource document) + { + this.document = document; + } + + /** + * @return the signatureDevice + */ + public String getSignatureDevice() + { + return this.signatureDevice; + } + + /** + * @param signatureDevice + * the signatureDevice to set + */ + public void setSignatureDevice(String signatureDevice) + { + this.signatureDevice = signatureDevice; + } + + /** + * @return the verifyMode + */ + public String getVerifyMode() + { + return this.verifyMode; + } + + /** + * @param verifyMode + * the verifyMode to set + */ + public void setVerifyMode(String verifyMode) + { + this.verifyMode = verifyMode; + } + + /** + * @return the signatureToVerify + */ + public int getSignatureToVerify() + { + return this.signatureToVerify; + } + + /** + * @param signatureToVerify + * the signatureToVerify to set + */ + public void setSignatureToVerify(int signatureToVerify) + { + this.signatureToVerify = signatureToVerify; + } + + /** + * @return the verificationTime + */ + public Date getVerificationTime() + { + return this.verificationTime; + } + + /** + * @param verificationTime + * the verificationTime to set + */ + public void setVerificationTime(Date verificationTime) + { + this.verificationTime = verificationTime; + } + + /** + * @return the returnHashInputData + */ + public boolean isReturnHashInputData() + { + return this.returnHashInputData; + } + + /** + * @param returnHashInputData + * the returnHashInputData to set + */ + public void setReturnHashInputData(boolean returnHashInputData) + { + this.returnHashInputData = returnHashInputData; + } + + public boolean isReturnNonTextualObjects() { + return this.returnNonTextualObjects; + } + + /** + * Tells if non text object of the signed pdf should be extracted and returned. + * One should show this to the user, especially in case of textual signature. + * Defaults to false + * + * @param returnNonTextualObjects + */ + public void setReturnNonTextualObjects(boolean returnNonTextualObjects) { + this.returnNonTextualObjects = returnNonTextualObjects; + } +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/xmldsig/ReconstructXMLDsigResult.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/xmldsig/ReconstructXMLDsigResult.java new file mode 100644 index 0000000..580f3af --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/xmldsig/ReconstructXMLDsigResult.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.api.xmldsig; + +import java.util.List; + +import at.gv.egiz.pdfas.api.commons.Constants; +import at.gv.egiz.pdfas.api.commons.SignatureInformation; + +/** + * The result of a reconstructXMLDsig call.
+ * This is just a wrapper for a list of {@link ExtendedSignatureInformation}s + * + * + * @author exthex + */ +public class ReconstructXMLDsigResult { + + private List extendedSignatures; + + private String device; + + /** + * + * @param extendedSignatureInfos + * @param signatureDevice + */ + public ReconstructXMLDsigResult(List extendedSignatureInfos, String signatureDevice) { + this.extendedSignatures = extendedSignatureInfos; + this.device = signatureDevice; + } + + /** + * Get the signature device that was used to create this result. + * + * @return {@link Constants#SIGNATURE_DEVICE_MOA} or {@link Constants#SIGNATURE_DEVICE_BKU} + */ + public String getDevice() { + return device; + } + + /** + * Returns the list of found signatures. + * + * @return Returns a list of {@link ExtendedSignatureInformation} objects representing all + * found signatures + {@link XMLDsigData}. + * @see SignatureInformation + */ + public List getExtendedSignatures() { + return this.extendedSignatures; + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/xmldsig/XMLDsigData.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/xmldsig/XMLDsigData.java new file mode 100644 index 0000000..0449cfa --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/xmldsig/XMLDsigData.java @@ -0,0 +1,83 @@ +/** + * 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.api.xmldsig; + +/** + * A container for XMLDsig data. + * + * @author exthex + * + */ +public class XMLDsigData { + + private String xmlDsig; + + private boolean detached; + + /** + * Constructor. + * + * @param xmldsig the xml string of the xmldsig. + * @param detached true if detached, false otherwise + */ + public XMLDsigData(String xmldsig, boolean detached) { + this.xmlDsig = xmldsig; + this.detached = detached; + } + + /** + * Get the xmldsig string + * @return + */ + public String getXmlDsig() { + return xmlDsig; + } + + /** + * Set the xmldsig string. + * + * @param xmlDsig + */ + public void setXmlDsig(String xmlDsig) { + this.xmlDsig = xmlDsig; + } + + /** + * + * @return true if detached, false otherwise + */ + public boolean isDetached() { + return detached; + } + + /** + * Set the detached. + * + * @param detached + */ + public void setDetached(boolean detached) { + this.detached = detached; + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/commandline/CommandlineConnectorChooser.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/commandline/CommandlineConnectorChooser.java new file mode 100644 index 0000000..6c0c19c --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/commandline/CommandlineConnectorChooser.java @@ -0,0 +1,199 @@ +/** + * 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.commandline; + +import at.gv.egiz.pdfas.exceptions.ErrorCode; +import at.gv.egiz.pdfas.framework.ConnectorFactory; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.knowcenter.wag.egov.egiz.PdfAS; +import at.knowcenter.wag.egov.egiz.PdfASID; +import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException; +import at.knowcenter.wag.egov.egiz.framework.SignatorFactory; +import at.knowcenter.wag.egov.egiz.sig.sigid.HotfixIdFormatter; + +/** + * Encapsulates the logic of choosing the correct connector for the commandline + * that can later be created using the ConnectorFactory. + * + * @author wprinz + */ +public class CommandlineConnectorChooser +{ + /** + * The log. + */ + private static Log log = LogFactory.getLog(CommandlineConnectorChooser.class); + + protected static final String BKU = "bku"; //$NON-NLS-1$ + + protected static final String MOA = "moa"; //$NON-NLS-1$ + + public static boolean needsSigId (String connectorId) + { + return !ConnectorFactory.isMOA(connectorId); + } + + public static String chooseCommandlineConnectorForSign(String connectorType) throws ConnectorException + { + log.debug("Choosing Connector for commandline signation..."); + + log.debug("connector type = " + connectorType); + + if (connectorType.equals(BKU)) + { + log.debug("sig_app is BKU ==> DetachedMultipartBKUConnector"); //$NON-NLS-1$ + + return ConnectorFactory.DETACHED_MULTIPART_BKU_CONNECTOR; + } + if (connectorType.equals(MOA)) + { + // TODO MOA detached signing is not allowed at the commandline + + // TR: wurde erweitert um detached MOA-Signaturen + // log.warn("Detached MOA is not supported on the commandline. -> choosing Base64 temporarily."); + // return ConnectorFactory.ENVELOPING_BASE64_MOA_CONNECTOR; + + return ConnectorFactory.DETACHED_LOCREF_MOA_CONNECTOR; + } + + throw new ConnectorException(300, "Unknown connector type '" + connectorType + "' specified."); + } + + public static String chooseCommandlineConnectorForVerify(String connectorType, PdfASID sig_kz, String sig_id, String profile) throws ConnectorException + { + log.debug("Choosing Connector for Commandline verification..."); + + log.debug("connector type = " + connectorType); + log.debug("sig_kz = " + sig_kz); //$NON-NLS-1$ + log.debug("sig_id = " + sig_id); //$NON-NLS-1$ + + if (sig_kz == null) + { + log.debug("sig_kz is null -> choosing an old enveloped base64 connector"); //$NON-NLS-1$ + + return chooseEnvelopingBase64ConnectorOld(connectorType); + } + + log.debug("sig_kz is not null -> one of the newer signatures"); + + if (sig_kz.getVersion().equals(SignatorFactory.VERSION_1_0_0)) + { + log.debug("Version is 1.0.0 -> Base64 Signatur (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 chooseEnvelopingBase64ConnectorHotfix(connectorType); + } + + 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 chooseEnvelopingBase64ConnectorOld(connectorType); + } + if (sig_id_parts[0].equals(HotfixIdFormatter.SIG_ID_PREFIX)) + { + log.debug("sig_id prefix is hotfix -> choosing hotfix base64 connector"); + + return chooseEnvelopingBase64ConnectorHotfix(connectorType); + } + + 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)) + { + log.debug("Version is 1.1.0 -> chose a detached connector."); + + return chooseDetachedMultipartConnector(connectorType); + } + if (sig_kz.getVersion().equals(SignatorFactory.VERSION_1_2_0)) + { + log.debug("Version is 1.2.0 -> chose a detached connector."); + + return chooseDetachedMultipartConnector(connectorType); + } + throw new ConnectorException(ErrorCode.UNSUPPORTED_SIGNATURE, "The SIG_KZ version '" + sig_kz.getVersion() + "' is unknown. Please get a new version of PDF-AS. Your version is: " + PdfAS.PDFAS_VERSION); + } + + protected static String chooseEnvelopingBase64ConnectorOld(String sig_app) throws ConnectorException + { + if (sig_app.equals(BKU)) + { + log.debug("sig_app is BKU ==> OldEnvelopingBase64BKUConnector"); //$NON-NLS-1$ + + return ConnectorFactory.OLD_ENVELOPING_BASE64_BKU_CONNECTOR; + } + if (sig_app.equals(MOA)) + { + log.debug("sig_app is MOA ==> EnvelopingBase64MOAConnector"); //$NON-NLS-1$ + + return ConnectorFactory.ENVELOPING_BASE64_MOA_CONNECTOR; + } + throw new ConnectorException(310, "Unknown sig_app '" + sig_app + "'."); //$NON-NLS-1$ //$NON-NLS-2$ + + } + + protected static String chooseEnvelopingBase64ConnectorHotfix(String sig_app) throws ConnectorException + { + if (sig_app.equals(BKU)) + { + log.debug("sig_app is BKU ==> EnvelopingBase64BKUConnector"); //$NON-NLS-1$ + + return ConnectorFactory.ENVELOPING_BASE64_BKU_CONNECTOR; + } + if (sig_app.equals(MOA)) + { + log.debug("sig_app is MOA ==> EnvelopingBase64MOAConnector"); //$NON-NLS-1$ + + return ConnectorFactory.ENVELOPING_BASE64_MOA_CONNECTOR; + } + throw new ConnectorException(310, "Unknown sig_app '" + sig_app + "'."); //$NON-NLS-1$ //$NON-NLS-2$ + } + + protected static String chooseDetachedMultipartConnector(String sig_app) throws ConnectorException + { + if (sig_app.equals(BKU)) + { + log.debug("sig_app is BKU ==> DetachedMultipartBKUConnector"); //$NON-NLS-1$ + + return ConnectorFactory.DETACHED_MULTIPART_BKU_CONNECTOR; + } + if (sig_app.equals(MOA)) + { + log.debug("sig_app is MOA ==> DetachedMOAConnector"); //$NON-NLS-1$ + +// String msg = "A Detached signature cannot be verified with the MOA connector (yet)."; //$NON-NLS-1$ +// log.error(msg); +// throw new ConnectorException(ErrorCode.DETACHED_SIGNATURE_NOT_SUPPORTED, msg); + return ConnectorFactory.DETACHED_LOCREF_MOA_CONNECTOR; + } + throw new ConnectorException(310, "Unknown sig_app '" + sig_app + "'."); //$NON-NLS-1$ //$NON-NLS-2$ + } +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/commandline/Main.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/commandline/Main.java new file mode 100644 index 0000000..52355f8 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/commandline/Main.java @@ -0,0 +1,1275 @@ +/** + * 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: Main.java,v 1.5 2006/10/31 08:06:56 wprinz Exp $ + */ +package at.gv.egiz.pdfas.commandline; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.pdfas.PdfAsFactory; +import at.gv.egiz.pdfas.api.PdfAs; +import at.gv.egiz.pdfas.api.commons.Constants; +import at.gv.egiz.pdfas.api.exceptions.ConfigUtilsException; +import at.gv.egiz.pdfas.api.exceptions.PdfAsException; +import at.gv.egiz.pdfas.api.io.DataSink; +import at.gv.egiz.pdfas.api.io.DataSource; +import at.gv.egiz.pdfas.api.sign.SignParameters; +import at.gv.egiz.pdfas.api.sign.pos.SignaturePositioning; +import at.gv.egiz.pdfas.api.sign.pos.axis.AbsoluteAxisAlgorithm; +import at.gv.egiz.pdfas.api.sign.pos.page.AbsolutePageAlgorithm; +import at.gv.egiz.pdfas.api.sign.pos.page.NewPageAlgorithm; +import at.gv.egiz.pdfas.api.verify.VerifyParameters; +import at.gv.egiz.pdfas.api.verify.VerifyResult; +import at.gv.egiz.pdfas.api.verify.VerifyResults; +import at.gv.egiz.pdfas.exceptions.ErrorCode; +import at.gv.egiz.pdfas.exceptions.ErrorCodeHelper; +import at.gv.egiz.pdfas.framework.config.SettingsHelper; +import at.gv.egiz.pdfas.framework.vfilter.VerificationFilterParameters; +import at.gv.egiz.pdfas.io.FileBasedDataSink; +import at.gv.egiz.pdfas.io.FileBasedDataSource; +import at.gv.egiz.pdfas.io.StringTextBasedDataSource; +import at.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.SettingsReader; +import at.knowcenter.wag.egov.egiz.exceptions.ConnectorFactoryException; +import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException; +import at.knowcenter.wag.egov.egiz.exceptions.PresentableException; +import at.knowcenter.wag.egov.egiz.exceptions.SettingNotFoundException; +import at.knowcenter.wag.egov.egiz.exceptions.SignatureTypesException; +import at.knowcenter.wag.egov.egiz.framework.SignatorFactory; +import at.knowcenter.wag.egov.egiz.pdf.TablePos; +import at.knowcenter.wag.egov.egiz.sig.ConnectorFactory; +import at.knowcenter.wag.egov.egiz.sig.ConnectorInformation; +import at.knowcenter.wag.egov.egiz.sig.SignatureTypes; + +/** + * The main program entry point of the commandline tool. + * + *

+ * The commandline uses the PDF-AS API. + *

+ * + * @author wprinz + */ +public abstract class Main +{ +// 23.11.2010 changed by exthex - added parameters for placeholder handling + /** + * Command line parameter setting the application mode sign|verify + */ + protected static final String PARAMETER_MODE = "-mode"; + + /** + * Command line parameter setting the application to connect + */ + protected static final String PARAMETER_CONNECTOR = "-connector"; + + /** + * Command line parameter setting the signature mode. + */ + protected static final String PARAMETER_SIGNATURE_MODE = "-sigmode"; + + /** + * Command line parameter setting the signature type. + */ + protected static final String PARAMETER_SIGNATURE_TYPE = "-sigtype"; + + /** + * Command line parameter setting the username + */ + protected static final String PARAMETER_USER_NAME = "-username"; + + /** + * Command line parameter setting the users password + */ + protected static final String PARAMETER_USER_PASSWORD = "-password"; + + /** + * Command line parameter selecting the position of the signature. + */ + protected static final String PARAMETER_POS = "-pos"; + + /** + * Command line parameter signaling to search the source document for a placeholder for the signature + */ + protected static final String PARAMETER_PLACEHOLDER_SEARCH = "-searchplaceholder"; + + /** + * Command line parameter selecting the id of the placeholder to use + */ + protected static final String PARAMETER_PLACEHOLDER_ID = "-placeholder_id"; + + /** + * Command line parameter selecting the match mode for the placeholder + */ + protected static final String PARAMETER_PLACEHOLDER_MATCH_MODE = "-placeholder_matchmode"; + + /** + * Command line parameter selecting the signature which is going to be + * verified. + */ + protected static final String PARAMETER_VERIFY_WHICH = "-verify_which"; + + /** + * Command line parameter that starts the deployment of the default configuration to the current + * user's home folder. + * @see Constants#USERHOME_CONFIG_FOLDER + */ + protected static final String PARAMETER_DEPLOY_DEFAULT_CONFIGURATION = "-ddc"; + + /** + * The application mode sign + */ + public static final String VALUE_MODE_SIGN = "sign"; + + /** + * The application mode verify + */ + public static final String VALUE_MODE_VERIFY = "verify"; + + /** + * The value for signature mode binary. + */ + public static final String VALUE_SIGNATURE_MODE_BINARY = Constants.SIGNATURE_TYPE_BINARY; + + /** + * The value for signature mode textual. + */ + public static final String VALUE_SIGNATURE_MODE_TEXTUAL = Constants.SIGNATURE_TYPE_TEXTUAL; + + /** + * The value for signature mode detached. + */ + public static final String VALUE_SIGNATURE_MODE_DETACHED = "detached"; + + /** + * The value for signature mode detachedtextual. + */ + public static final String VALUE_SIGNATURE_MODE_DETACHED_TEXT = Constants.SIGNATURE_TYPE_DETACHEDTEXTUAL; + + /** + * The placeholder match mode STRICT + */ + public static final String VALUE_PLACEHOLDER_MATCH_MODE_STRICT = "strict"; + + /** + * The placeholder match mode STRICT + */ + public static final String VALUE_PLACEHOLDER_MATCH_MODE_MODERATE = "moderate"; + + /** + * The placeholder match mode STRICT + */ + public static final String VALUE_PLACEHOLDER_MATCH_MODE_LENIENT = "lenient"; + + /** + * The log. + */ + private static final Log logger_ = LogFactory.getLog(Main.class); + + /** + * Main program entry point. + * + * @param args + * The commandline arguments. + * @throws IOException + */ + public static void main(String[] args) throws IOException + { + // ConfigLogger.setLevel(Level.DEBUG); + + // search for PARAMETER_DEPLOY_DEFAULT_CONFIGURATION before initializing the SettingsReader + for (int i = 0; i < args.length; i++) { + if (args[i].trim().equals(PARAMETER_DEPLOY_DEFAULT_CONFIGURATION)) { + try { + String defaultConfigurationDeployedTo = ConfigUtils.deployDefaultConfiguration(); + if (defaultConfigurationDeployedTo != null) { + System.out.println("Default configuration successfully deployed to \"" + defaultConfigurationDeployedTo + "\"."); + } else { + System.out.println("Default configuration has NOT been deployed. Maybe the configuration already exists."); + } + if (args.length == 1) { + // no other parameters supplied; exit application + System.exit(0); + } + } catch (ConfigUtilsException e) { + System.err.println("Deployment of default configuration failed: " + e.getMessage()); + System.exit(1); + } + } + } + + SettingsReader.initializeForCommandLine(); + ConfigUtils.initializeLogger(); + + // printUsage(System.out); + + String mode = null; + String signature_mode = Constants.DEFAULT_SIGNATURE_TYPE; + String connector = null; + + String signature_type = null; + String user_name = null; + String user_password = null; + String pos_string = null; + + boolean search_placeholder = true; + String placeholderId = null; + int placeholderMatchMode = Constants.PLACEHOLDER_MATCH_MODE_MODERATE; + + int verify_which = -1; + + String input = null; + String output = null; + + try + { + // force settings preload + SettingsReader.getInstance(); + + // for (int i = 0; i < args.length; i++) + // { + // logger_.debug("arg[" + i + "] = " + args[i]); + // } + + for (int i = 0; i < args.length; i++) + { + String cur_arg = args[i].trim(); + + if (cur_arg.equals(PARAMETER_DEPLOY_DEFAULT_CONFIGURATION)) { + // already applied + continue; + } + + if (cur_arg.equals(PARAMETER_MODE)) + { + i++; + if (i >= args.length) + { + printNoValue(PARAMETER_MODE); + return; + } + mode = args[i]; + if (!checkMode(mode)) + { + printUnrecognizedValue(PARAMETER_MODE, mode); + return; + } + continue; + } + + if (cur_arg.equals(PARAMETER_CONNECTOR)) + { + i++; + if (i >= args.length) + { + printNoValue(PARAMETER_CONNECTOR); + return; + } + connector = args[i]; + if (!checkConnector(connector)) + { + printUnrecognizedValue(PARAMETER_CONNECTOR, connector); + return; + } + continue; + } + + if (cur_arg.equals(PARAMETER_SIGNATURE_MODE)) + { + i++; + if (i >= args.length) + { + printNoValue(PARAMETER_SIGNATURE_MODE); + return; + } + signature_mode = args[i]; + if (!checkSignatureMode(signature_mode)) + { + printUnrecognizedValue(PARAMETER_SIGNATURE_MODE, signature_mode); + return; + } + continue; + } + + if (cur_arg.equals(PARAMETER_SIGNATURE_TYPE)) + { + i++; + if (i >= args.length) + { + printNoValue(PARAMETER_SIGNATURE_TYPE); + return; + } + signature_type = args[i]; + if (!checkSignatureType(signature_type)) + { + printUnrecognizedValue(PARAMETER_SIGNATURE_TYPE, signature_type); + return; + } + continue; + } + + if (cur_arg.equals(PARAMETER_PLACEHOLDER_SEARCH)) + { + i++; + if (i >= args.length) + { + printNoValue(PARAMETER_PLACEHOLDER_SEARCH); + return; + } + search_placeholder = Boolean.valueOf(args[i]).booleanValue(); + continue; + } + + if (cur_arg.equals(PARAMETER_PLACEHOLDER_ID)) + { + i++; + if (i >= args.length) + { + printNoValue(PARAMETER_PLACEHOLDER_ID); + return; + } + placeholderId = args[i]; + continue; + } + + if (cur_arg.equals(PARAMETER_PLACEHOLDER_MATCH_MODE)) + { + i++; + if (i >= args.length) + { + printNoValue(PARAMETER_PLACEHOLDER_MATCH_MODE); + return; + } + String matchMode = args[i]; + if (matchMode.equals(VALUE_PLACEHOLDER_MATCH_MODE_LENIENT)) + placeholderMatchMode = Constants.PLACEHOLDER_MATCH_MODE_LENIENT; + else if (matchMode.equals(VALUE_PLACEHOLDER_MATCH_MODE_MODERATE)) + placeholderMatchMode = Constants.PLACEHOLDER_MATCH_MODE_MODERATE; + else if (matchMode.equals(VALUE_PLACEHOLDER_MATCH_MODE_STRICT)) + placeholderMatchMode = Constants.PLACEHOLDER_MATCH_MODE_STRICT; + else + printUnrecognizedValue(PARAMETER_PLACEHOLDER_MATCH_MODE, args[i]); + continue; + } + + if (cur_arg.equals(PARAMETER_USER_NAME)) + { + i++; + if (i >= args.length) + { + printNoValue(PARAMETER_USER_NAME); + return; + } + user_name = args[i]; + continue; + } + + if (cur_arg.equals(PARAMETER_USER_PASSWORD)) + { + i++; + if (i >= args.length) + { + printNoValue(PARAMETER_USER_PASSWORD); + return; + } + user_password = args[i]; + continue; + } + + if (cur_arg.equals(PARAMETER_POS)) + { + i++; + if (i >= args.length) + { + printNoValue(PARAMETER_POS); + return; + } + pos_string = args[i]; + continue; + } + + if (cur_arg.equals(PARAMETER_VERIFY_WHICH)) + { + i++; + if (i >= args.length) + { + printNoValue(PARAMETER_VERIFY_WHICH); + return; + } + String str_verify_which = args[i]; + try + { + verify_which = Integer.parseInt(str_verify_which); + } + catch (NumberFormatException e) + { + printUnrecognizedValue(PARAMETER_VERIFY_WHICH, str_verify_which); + return; + } + + continue; + } + + if (cur_arg.charAt(0) == '-') + { + printUnrecognizedOption(cur_arg); + return; + } + + if (input == null) + { + input = cur_arg; + continue; + } + + if (output == null) + { + output = cur_arg; + continue; + } + + printUnrecognizedAdditionalCommandlineArgument(cur_arg); + return; + } + + if (mode == null) + { + printMissingParameter("a mode", PARAMETER_MODE); + return; + } + if (connector == null) + { + printMissingParameter("a connector", PARAMETER_CONNECTOR); + return; + } + if (mode.equals(VALUE_MODE_SIGN)) + { + if (signature_mode == null) + { + printMissingParameter("a signature mode", PARAMETER_SIGNATURE_MODE); + return; + } + if (signature_type == null) + { + SettingsReader settings = SettingsReader.getInstance(); + String default_type = settings.getValueFromKey(SignatureTypes.DEFAULT_TYPE); + signature_type = default_type; + } + if (user_name == null) + { + user_name = ""; + // printMissingParameter("a user name", PARAMETER_USER_NAME); + // return; + } + if (user_password == null) + { + user_password = ""; + // printMissingParameter("a user password", PARAMETER_USER_PASSWORD); + // return; + } + } + + if (input == null) + { + printMissing("an input document"); + return; + } + + File file = new File(input); + if (!file.exists()) + { + System.err.println("The input file '" + input + "' doesn't exist."); + return; + } + + if (mode.equals(VALUE_MODE_SIGN) && output == null) + { + output = generateOutputFileNameFromInput(input, signature_mode); + } + + carryOutCommand(mode, signature_mode, connector, signature_type, user_name, user_password, verify_which, input, output, pos_string, search_placeholder, placeholderId, placeholderMatchMode); + + } + catch (PdfAsException e) + { + printPresentableException(e); + + if (output != null) + { + File oFile = new File(output); + if (oFile.exists()) { + logger_.debug("Deleting output file on error."); + boolean deleted = oFile.delete(); + if (!deleted) + { + logger_.error("Couldn't delete output file " + output); + } + } + } + } + finally + { + SettingsReader.clearTemporaryDirectory(); + } + } + + protected static void carryOutCommand(final String mode, final String signature_mode, final String connector, final String signature_type, final String user_name, final String user_password, + final int verify_which, final String input, String output, final String pos_string, boolean search_placeholder, String placeholderId, int placeholderMatchMode) throws PdfAsException + { + // File file = new File(input); + // + // byte[] input_bytes = null; + // try + // { + // FileInputStream fis = new FileInputStream(file); + // input_bytes = new byte[(int) file.length()]; + // fis.read(input_bytes); + // fis.close(); + // } + // catch (IOException e) + // { + // throw new PDFDocumentException(201); + // } + + PrintWriter messageOutput = new PrintWriter(System.out); + + if (mode.equals(VALUE_MODE_SIGN)) + { + carryOutSign(input, connector, signature_mode, signature_type, pos_string, user_name, user_password, output, messageOutput, search_placeholder, placeholderId, placeholderMatchMode); + } + else + { + carryOutVerify(input, connector, verify_which, messageOutput); + } + messageOutput.flush(); + } + + public static void carryOutSign(String input, String connector, String signature_mode, String signature_type, String pos_string, String user_name, String user_password, String output, + PrintWriter messageOutput, boolean search_placeholder, String placeholderId, int placeholderMatchMode) throws PdfAsException + { + messageOutput.println("Signing " + input + "..."); + + // for performance measurement + long startTime = 0; + long fileSize = 0; + if (logger_.isInfoEnabled()) + { + startTime = System.currentTimeMillis(); + } + + DataSource dataSource = null; + try + { + File file = new File(input); + dataSource = new FileBasedDataSource(file, "application/pdf"); + if (logger_.isDebugEnabled()) + { + fileSize = file.length(); + } + } + catch (IOException e) + { + throw new PDFDocumentException(201, e); + } + + DataSink dataSink = null; + File outputFile = null; + try + { + outputFile = new File(output); + + dataSink = new FileBasedDataSink(outputFile); + } + catch (IOException e) + { + throw new PDFDocumentException(ErrorCode.CANNOT_WRITE_PDF, e); + } + + try { + processSign(dataSource, connector, signature_mode, signature_type, pos_string, search_placeholder, placeholderId, placeholderMatchMode, dataSink); + } catch (Exception e) { + // Exception caught in order to delete file based datasink + if (outputFile != null && outputFile.exists()) + { + logger_.debug("Deleting output file on error."); + boolean deleted = outputFile.delete(); + if (!deleted) + { + logger_.error("Couldn't delete output file " + output); + } + } + if (e instanceof PresentableException) { + throw (PresentableException)e; + } else { + logger_.error(e); + throw new PresentableException(ErrorCode.UNKNOWN_ERROR, e); + } + } + + // for performance measurement + if (logger_.isInfoEnabled()) + { + long endTime = System.currentTimeMillis(); + String toReport = "SIGN;" + signature_mode + ";" + input + ";" + fileSize + ";" + (endTime - startTime); + logger_.info(toReport); + } + + messageOutput.println("Signing was successful (" + output + ")."); + } + + public static void carryOutVerify(String input, String connector, int verify_which, PrintWriter messageOutput) throws PdfAsException + { + messageOutput.println("Verifying " + input + "..."); + + // for performance measurement + long startTime = 0; + long fileSize = 0; + if (logger_.isInfoEnabled()) + { + startTime = System.currentTimeMillis(); + } + + DataSource dataSource = null; + try + { + File file = new File(input); + if (logger_.isDebugEnabled()) + { + fileSize = file.length(); + } + String extension = extractExtension(input); + if (extension != null && extension.equals("txt")) + { + try + { + FileInputStream fis = new FileInputStream(file); + byte[] input_bytes = new byte[(int) file.length()]; + fis.read(input_bytes); + fis.close(); + + String text = new String(input_bytes, "UTF-8"); + dataSource = new StringTextBasedDataSource(text); + } + catch (UnsupportedEncodingException e) + { + throw new RuntimeException("Very strange: UTF-8 character encoding not supported.", e); + } + } + else + { + dataSource = new FileBasedDataSource(file, "application/pdf"); + } + } + catch (IOException e) + { + throw new PDFDocumentException(ErrorCode.DOCUMENT_CANNOT_BE_READ, e); + } + + VerifyResults results = processVerify(dataSource, connector, verify_which); + + messageOutput.println("Verification results:"); + formatVerifyResults(results, messageOutput); + + // for performance measurement + if (logger_.isInfoEnabled()) + { + long endTime = System.currentTimeMillis(); + String toReport = "VERIFY;" + input + ";" + fileSize + ";" + (endTime - startTime) + ";" + debugVerifyResults(results); + logger_.info(toReport); + } + + } + + /** + * Extracts the extension from a file name string. + * + *

+ * The extension of a file name is whatever text follows the last '.'. + *

+ * + * @param file_name + * The file name. + * @return Returns the extension. If the file name ends with the '.', then an + * empty string is returned. If the file name doesn't contain any '.' + * or file_name is null, null is returned. + */ + public static String extractExtension(String file_name) + { + if (file_name == null) + { + return null; + } + + int dot_index = file_name.lastIndexOf('.'); + if (dot_index < 0) + { + return null; + } + return file_name.substring(dot_index + 1); + } + + public static void processSign(DataSource dataSource, String connector, String signature_mode, String signature_type, String pos_string, boolean search_placeholder, String placeholderId, int placeholderMatchMode, DataSink dataSink) throws PdfAsException + { + TablePos pos = null; + if (pos_string != null) + { + try + { + pos = PdfAS.parsePositionFromPosString(pos_string); + } + catch (PDFDocumentException e) + { + printUnrecognizedValue(PARAMETER_POS, pos_string); + return; + + } + } + SignaturePositioning posi = null; + if (pos != null) + { + posi = new SignaturePositioning(); + if (!pos.isXauto()) + { + posi.setXAlgorithm(new AbsoluteAxisAlgorithm(pos.getPosX())); + } + if (!pos.isYauto()) + { + posi.setYAlgorithm(new AbsoluteAxisAlgorithm(pos.getPosY())); + } + if (!pos.isWauto()) + { + posi.setWidthAlgorithm(new AbsoluteAxisAlgorithm(pos.getWidth())); + } + if (pos.isNewPage()) + { + posi.setPageAlgorithm(new NewPageAlgorithm()); + } + if (!pos.isPauto()) + { + posi.setPageAlgorithm(new AbsolutePageAlgorithm(pos.getPage())); + } + posi.setFooterLine(pos.getFooterLine()); + } + + PdfAs pdfAs = PdfAsFactory.createPdfAs(new File(SettingsReader.RESOURCES_PATH)); + + SignParameters sp = new SignParameters(); + sp.setDocument(dataSource); + sp.setOutput(dataSink); + sp.setSignatureType(signature_mode); // TODO detached signaturen! + sp.setSignatureDevice(connector); + sp.setSignatureProfileId(signature_type); + sp.setSignaturePositioning(posi); + sp.setCheckForPlaceholder(search_placeholder); + sp.setPlaceholderId(placeholderId); + sp.setPlaceholderMatchMode(placeholderMatchMode); + pdfAs.sign(sp); + + } + + public static VerifyResults processVerify(DataSource dataSource, String connector, int verify_which) throws PdfAsException + { + String verifyMode = Constants.VERIFY_MODE_FULL_CONSERVATIVE; + VerificationFilterParameters parameters = SettingsHelper.readVerificationFilterParametersFromSettings(); + if (parameters.extractBinarySignaturesOnly()) + { + verifyMode = Constants.VERIFY_MODE_BINARY_ONLY; + } + else + { + if (parameters.assumeOnlySignatureUpdateBlocks()) + { + verifyMode = Constants.VERIFY_MODE_SEMI_CONSERVATIVE; + } + else + { + verifyMode = Constants.VERIFY_MODE_FULL_CONSERVATIVE; + } + } + + PdfAs pdfAs = PdfAsFactory.createPdfAs(new File(SettingsReader.RESOURCES_PATH)); + + VerifyParameters vp = new VerifyParameters(); + vp.setDocument(dataSource); + vp.setVerifyMode(verifyMode); + vp.setSignatureDevice(connector); + vp.setReturnHashInputData(false); + vp.setVerificationTime(null); + vp.setSignatureToVerify(verify_which); + VerifyResults vrs = pdfAs.verify(vp); + + return vrs; + } + + protected static String generateOutputFileNameFromInput(String input, String sig_mode) + { + String output = input + "_out"; + if (sig_mode.startsWith("detached")) + { + output += ".xml"; + } + else + { + output += ".pdf"; + } + + return output; + } + + /** + * Prints that the provided option was unrecognized. + * + * @param option + * The unrecognized option. + * @throws PresentableException + * Forwarded exception. + */ + protected static void printUnrecognizedOption(final String option) throws PresentableException + { + System.err.println("Unrecognized option '" + option + "'."); + printUsage(System.out); + } + + /** + * Prints that the provided value was unrecognized. + * + * @param parameter + * The parameter, which is missing a value. + * @throws PresentableException + * Forwarded exception. + */ + protected static void printNoValue(final String parameter) throws PresentableException + { + System.err.println("The parameter " + parameter + " requires a value as next argument."); + printUsage(System.out); + } + + /** + * Prints that the provided value was unrecognized. + * + * @param value + * The unrecognized value. + * @throws PresentableException + * Forwarded exception. + */ + protected static void printUnrecognizedValue(final String parameter, final String value) throws PresentableException + { + System.err.println("The parameter " + parameter + " doesn't recognize the provided value '" + value + "'."); + printUsage(System.out); + } + + /** + * Prints that the provided additional commandline argument was unrecognized. + * + * @param argument + * The unrecognized argument. + * @throws PresentableException + * Forwarded exception. + */ + protected static void printUnrecognizedAdditionalCommandlineArgument(final String argument) throws PresentableException + { + System.err.println("Unrecognized additional commandline argument '" + argument + "'."); + printUsage(System.out); + } + + /** + * Prints that a certain parameter was missing. + * + * @param missing_term + * A description of the missing parameter ("e.g. a mode"). + * @param parameter + * The missing parameter itself (e.g. "-mode"). + * @throws PresentableException + * Forwarded exception. + */ + protected static void printMissingParameter(final String missing_term, final String parameter) throws PresentableException + { + printMissing(missing_term + " ('" + parameter + "' parameter)"); + } + + /** + * Prints that something is missing. + * + * @param missing_term + * A descriptive message of the missing thing. + * @throws PresentableException + * Forwarded exception. + */ + protected static void printMissing(final String missing_term) throws PresentableException + { + System.err.println("Please specify " + missing_term + "."); + printUsage(System.out); + } + + /** + * Prints out the ErrorCodeException in a descriptive form. + * + * @param ece + * The ErrorCodeException to be printed. + */ + protected static void printPresentableException(final PdfAsException e) + { + String errorMessage = ErrorCodeHelper.formErrorMessage(e); + System.err.println(errorMessage); +// if (e.getErrorCode() == ErrorCode.PLACEHOLDER_EXCEPTION) +// { +// PlaceholderException phe = null; +// if (e instanceof PlaceholderException) +// { +// phe = (PlaceholderException) e; +// } +// else +// { +// phe = (PlaceholderException) e.getCause(); +// } +// +// System.err.println("Der Platzhalter des Feldes " + phe.getField() + " ist um " + phe.getMissing() + " Bytes zu kurz. "); +// } +// +// System.err.println("Fehler " + e.getErrorCode() + ": " + ErrorCodeHelper.getMessageForErrorCode(e.getErrorCode())); +// +// if (e instanceof ExternalErrorException) +// { +// ExternalErrorException eee = (ExternalErrorException) e; +// System.err.println("Externer Fehlergrund: " + eee.getExternalErrorCode() + ": " + eee.getExternalErrorMessage()); +// } + + logger_.error(e); + } + + /** + * Prints the usage text. + * + * @param writer + * The writer to print the text to. + * @throws PresentableException + * Forwarded exception. + */ + public static void printUsage(PrintStream writer) throws PresentableException + { + writer.println("Usage: pdf-as [[OPTIONS] [output file]|UTILOPTIONS]"); + writer.println(" Required OPTIONS:"); + + writer.println(" " + PARAMETER_MODE + " <" + VALUE_MODE_SIGN + "|" + VALUE_MODE_VERIFY + ">"); + writer.println(" " + VALUE_MODE_SIGN + " ... signs a document"); + writer.println(" " + VALUE_MODE_VERIFY + " ... verifies a document"); + + writer.print(" " + PARAMETER_CONNECTOR + " "); + ConnectorInformation[] ci = ConnectorFactory.getConnectorInformationArray(); + + // prepare list of connectors available for commandline + ArrayList ciList = new ArrayList(); + for (int i = 0; i < ci.length; i++) { + String id = ci[i].getIdentifier(); + if (ConnectorFactory.isAvailableForCommandline(id)) { + ciList.add(ci[i]); + } + } + + // list available connectors wrapped in <...|...> + Iterator ciIt = ciList.iterator(); + writer.print("<"); + while (ciIt.hasNext()) { + writer.print(((ConnectorInformation) ciIt.next()).getIdentifier()); + if (ciIt.hasNext()) { + writer.print("|"); + } + } + writer.print(">"); + writer.println(); + +// for (int i = 0; i < ci.length; i++) +// { +// String id = ci[i].getIdentifier(); +// if (!ConnectorFactory.isAvailableForCommandline(id)) +// { +// continue; +// } +// writer.print(id); +// if (i < ci.length - 1) +// { +// writer.print("|"); +// } +// } + ciIt = ciList.iterator(); + while (ciIt.hasNext()) { + ConnectorInformation cinf = (ConnectorInformation) ciIt.next(); + writer.println(" " + cinf.getIdentifier() + " ... " + cinf.getDescription()); + } + +// for (int i = 0; i < ci.length; i++) +// { +// String id = ci[i].getIdentifier(); +// if (!ConnectorFactory.isAvailableForCommandline(id)) +// { +// continue; +// } +// writer.println(" " + id + " ... " + ci[i].getDescription()); +// } + + writer.println(" UTILity OPTIONS"); + + writer.println(" " + PARAMETER_DEPLOY_DEFAULT_CONFIGURATION + " ... deploys the default configuration to the current user's home"); + + writer.println(" OPTIONS for signation:"); + + writer.println(" " + PARAMETER_SIGNATURE_MODE + " <" + VALUE_SIGNATURE_MODE_BINARY + "|" + VALUE_SIGNATURE_MODE_TEXTUAL + "> [optional]"); + writer.println(" " + VALUE_SIGNATURE_MODE_BINARY + " ... signs the complete binary document" + (Constants.DEFAULT_SIGNATURE_TYPE.equals(VALUE_SIGNATURE_MODE_BINARY) ? " (default)" : "")); + writer.println(" " + VALUE_SIGNATURE_MODE_TEXTUAL + " ... signs only the textual portion of the document" + (Constants.DEFAULT_SIGNATURE_TYPE.equals(VALUE_SIGNATURE_MODE_TEXTUAL) ? " (default)" : "")); + writer.println(" " + VALUE_SIGNATURE_MODE_DETACHED_TEXT + " ... signs the document using the textual mode and returns the xml signature of it." + (Constants.DEFAULT_SIGNATURE_TYPE.equals(VALUE_SIGNATURE_MODE_DETACHED_TEXT) ? " (default)" : "")); + + writer.print(" " + PARAMETER_SIGNATURE_TYPE + " <"); + SignatureTypes sig_types = SignatureTypes.getInstance(); + SettingsReader settings = SettingsReader.getInstance(); + Set types_array = sig_types.getSignatureTypes(); + Iterator it = types_array.iterator(); + while (it.hasNext()) + { + String type = (String) it.next(); + writer.print(type); + if (it.hasNext()) + { + writer.print("|"); + } + } + writer.println(">"); + writer.println(" ... [optional] the profile to be used. If omitted, the default"); + writer.println(" profile is used."); + String default_type = settings.getValueFromKey(SignatureTypes.DEFAULT_TYPE); + it = types_array.iterator(); + while (it.hasNext()) + { + String type = (String) it.next(); + String descr_key = SignatureTypes.SIG_OBJ + type + "." + SignatureTypes.SIG_DESCR; + String type_descr = settings.getValueFromKey(descr_key); + + writer.println(" " + type + " ... " + (type.equals(default_type) ? "(default) " : "") + type_descr); + } + + writer.println(" " + PARAMETER_USER_NAME + " ... [optional] the user name"); + writer.println(" " + PARAMETER_USER_PASSWORD + " ... [optional] the user password"); + + writer.println(" " + PARAMETER_POS + " ... [optional] the position of the signature block"); + writer.println(" position has the format [x:x_algo];[y:y_algo];[w:w_algo][p:p_algo];[f:f_algo]"); + writer.println(" if not present default is set to x:auto;y:auto;w:auto;p:auto;f:0"); + writer.println(" x_algo:='auto' ... automatic positioning x"); + writer.println(" floatvalue ... absolute x must be >= 0"); + writer.println(" y_algo:='auto' ... automatic positioning y"); + writer.println(" floatvalue ... absolute y must be >= 0"); + writer.println(" w_algo:='auto' ... automatic width"); + writer.println(" floatvalue ... absolute width must be > 0"); + writer.println(" p_algo:='auto' ... automatic last page"); + writer.println(" 'new' ... new page"); + writer.println(" intvalue ... pagenumber must be > 0 if p>number of pages in document p-->handled like p:'new'"); + writer.println(" f_algo floatvalue ... consider footerline must be >= 0 (only if y_algo is auto and p_algo is not 'new')"); + + writer.println(" " + PARAMETER_PLACEHOLDER_SEARCH + " ... [optional] if set to true, the source document will be scanned for signature placeholder images. If not set, the enable_placeholder_search value in the config file decides whether or not a search for placeholder images will be performed."); + writer.println(" " + PARAMETER_PLACEHOLDER_ID + " ... [optional] search for signature placeholder images containing the given id"); + writer.println(" " + PARAMETER_PLACEHOLDER_MATCH_MODE + " <" + VALUE_PLACEHOLDER_MATCH_MODE_LENIENT + "|" + VALUE_PLACEHOLDER_MATCH_MODE_MODERATE + "|" + VALUE_PLACEHOLDER_MATCH_MODE_STRICT + "> ... [optional] specify the behavior if no matching placeholder could be found. Default is ."); + writer.println(" " + VALUE_PLACEHOLDER_MATCH_MODE_LENIENT + " ... sign in place of the first found placeholder, regardless if it matches exactly, or at the end of the document if none is found."); + writer.println(" " + VALUE_PLACEHOLDER_MATCH_MODE_MODERATE + " ... sign in place of the first found placeholder which has no explicit id set, or at the end of the document if none is found."); + writer.println(" " + VALUE_PLACEHOLDER_MATCH_MODE_STRICT + " ... throws a PlaceholderExtractionException."); + + writer.println(" OPTIONS for verification:"); + writer.println(" " + PARAMETER_VERIFY_WHICH + " ... [optional] zero based number of the signature"); + writer.println(" to be verified. If omitted, all signatures are verified."); + + writer.println(" Example usage:"); + writer.println(" pdf-as " + PARAMETER_MODE + " " + VALUE_MODE_SIGN + " " + PARAMETER_CONNECTOR + " " + Constants.SIGNATURE_DEVICE_BKU + " " + PARAMETER_SIGNATURE_MODE + " " + VALUE_SIGNATURE_MODE_TEXTUAL + " some_document.pdf"); + writer.println(" pdf-as " + PARAMETER_MODE + " " + VALUE_MODE_VERIFY + " " + PARAMETER_CONNECTOR + " " + Constants.SIGNATURE_DEVICE_BKU + " some_document.pdf_out.pdf"); + writer.println(" pdf-as " + PARAMETER_DEPLOY_DEFAULT_CONFIGURATION); + } + + /** + * Checks the value for correctness. + * + * @param mode + * The parameter's value. + * @return Returns true, if the value is correct, false otherwise. + */ + protected static boolean checkMode(String mode) + { + return mode.equals(VALUE_MODE_SIGN) || mode.equals(VALUE_MODE_VERIFY); + } + + /** + * Checks the value for correctness. + * + * @param signature_mode + * The parameter's value. + * @return Returns true, if the value is correct, false otherwise. + */ + protected static boolean checkSignatureMode(String signature_mode) + { + return signature_mode.equals(VALUE_SIGNATURE_MODE_BINARY) || signature_mode.equals(VALUE_SIGNATURE_MODE_TEXTUAL) + //|| signature_mode.equals(VALUE_SIGNATURE_MODE_DETACHED) + || signature_mode.equals(VALUE_SIGNATURE_MODE_DETACHED_TEXT); + } + + /** + * Checks the value for correctness. + * + * @param connector + * The parameter's value. + * @return Returns true, if the value is correct, false otherwise. + * @throws ConnectorFactoryException + * F.e. + */ + protected static boolean checkConnector(String connector) throws ConnectorFactoryException + { + return ConnectorFactory.isValidConnectorIdentifier(connector) && ConnectorFactory.isAvailableForCommandline(connector); + } + + /** + * Checks the value for correctness (meaning if it exists) + * + * @param signature_type + * The parameter's value. + * @return Returns true, if the value is correct, false otherwise. + */ + protected static boolean checkSignatureType(String signature_type) throws SignatureTypesException + { + return SignatureTypes.getInstance().getSignatureTypes().contains(signature_type); + } + + /** + * Translates the commandline argument to a PDF-AS-ID. + * + * @param signature_mode + * The signator mode commandline argument. + * @return Returns the corresponding PDFASID. + */ + protected static PdfASID translateSignatureModeToPdfASID(String signature_mode) + { + if (signature_mode.equals(VALUE_SIGNATURE_MODE_BINARY)) + { + return SignatorFactory.MOST_RECENT_BINARY_SIGNATOR_ID; + } + if (signature_mode.equals(VALUE_SIGNATURE_MODE_TEXTUAL)) + { + return SignatorFactory.MOST_RECENT_TEXTUAL_SIGNATOR_ID; + } + if (signature_mode.equals(VALUE_SIGNATURE_MODE_DETACHED)) + { + return SignatorFactory.MOST_RECENT_DETACHED_SIGNATOR_ID; + } + if (signature_mode.equals(VALUE_SIGNATURE_MODE_DETACHED_TEXT)) + { + return SignatorFactory.MOST_RECENT_DETACHEDTEXT_SIGNATOR_ID; + } + return null; + } + + /** + * Formats the verification results. + * + * @param results + * The List of SignatureResponse verification results. + * @param writer + * The output sink to write the formatted text to. + * @throws SettingNotFoundException + * Forwarded exception. + */ + protected static void formatVerifyResults(VerifyResults results, PrintWriter writer) throws SettingNotFoundException + { + Iterator it = results.getResults().iterator(); + while (it.hasNext()) + { + VerifyResult result = (VerifyResult) it.next(); + formatVerifyResult(result, writer); + + if (it.hasNext()) + { + writer.println(); + } + } + } + + /** + * Formats the verification results for debugging. Returns 0 if no error + * occurs or the sum of all error-codes. + * + * @param results + * + * @param writer + * The output sink to write the formatted text to. + * @throws SettingNotFoundException + * Forwarded exception. + */ + protected static int debugVerifyResults(VerifyResults results) throws SettingNotFoundException + { + int toreturn = 0; + Iterator it = results.getResults().iterator(); + while (it.hasNext()) + { + VerifyResult result = (VerifyResult) it.next(); + + toreturn += result.getValueCheckCode().getCode(); + } + return toreturn; + } + + public static void formatVerifyResult(VerifyResult result, PrintWriter writer) throws SettingNotFoundException + { + + if (result.isVerificationDone()) { + writer.println(" Zertifikat:"); + writer.println(" Signator: " + result.getSignerCertificate().getSubjectDN().toString()); + writer.println(" Aussteller: " + result.getSignerCertificate().getIssuerDN().toString()); + writer.println(" Seriennummer: " + result.getSignerCertificate().getSerialNumber()); + List public_properties = result.getPublicProperties(); + Iterator it = public_properties.iterator(); + while (it.hasNext()) + { + String public_property = (String) it.next(); + writer.println(" Eigenschaft: " + public_property); + } + + writer.println(" Zertifikat-Check:"); + writer.println(" " + result.getCertificateCheck().getCode() + " - " + result.getCertificateCheck().getMessage()); + writer.println(" Signatur-Check:"); + writer.println(" " + result.getValueCheckCode().getCode() + " - " + result.getValueCheckCode().getMessage()); + writer.println(" Manifest-Check:"); + writer.println(" " + result.getManifestCheckCode().getCode() + " - " + result.getManifestCheckCode().getMessage()); + } else { + PdfAsException ex = result.getVerificationException(); + writer.println("\n Signaturpruefung fuer diese Signatur nicht moeglich: " + ErrorCodeHelper.formErrorMessage(ex)); + } + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/ErrorCode.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/ErrorCode.java new file mode 100644 index 0000000..df321df --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/ErrorCode.java @@ -0,0 +1,101 @@ +/** + * 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.exceptions; + +/** + * Contains constants for the error codes. + * + *

+ * In Java 1.5 this would be an enum. + *

+ * + * @author wprinz + */ +public final class ErrorCode +{ + public static final int EXTERNAL_ERROR = 0; + public static final int UNKNOWN_ERROR = 6; + public static final int OUT_OF_MEMORY_ERROR = 7; + + public static final int SETTING_NOT_FOUND = 100; + public static final int SETTINGS_EXCEPTION = 101; + public static final int KZ_SETTING_NOT_FOUND = 102; + public static final int NO_EMBEDABLE_TTF_CONFIGURED_FOR_PDFA = 103; + public static final int INVALID_SIGNATURE_LAYOUT_IMPL_CONFIGURED = 104; + public static final int MISSING_HEADER_SERVER_USER_AGENT = 105; + + public static final int DOCUMENT_CANNOT_BE_READ = 201; + public static final int TEXT_EXTRACTION_EXCEPTION = 202; + public static final int CANNOT_WRITE_PDF = 205; + public static final int DOCUMENT_NOT_SIGNED = 206; + public static final int SIGNATURE_TYPES_EXCEPTION = 223; + public static final int FONT_NOT_FOUND = 230; + public static final int DOCUMENT_IS_PROTECTED = 231; + public static final int INVALID_SIGNATURE_DICTIONARY = 232; +//23.11.2010 changed by exthex - added error code for failed extraction + public static final int SIGNATURE_PLACEHOLDER_EXTRACTION_FAILED = 233; + + public static final int INVALID_SIGNATURE_POSITION = 224; + + public static final int SIGNATURE_COULDNT_BE_CREATED = 300; + public static final int SIGNED_TEXT_EMPTY = 301; + public static final int PROFILE_NOT_DEFINED = 302; + public static final int SERIAL_NUMBER_INVALID = 303; + public static final int SIG_CERTIFICATE_CANNOT_BE_READ = 304; + public static final int PROFILE_NOT_USABLE_FOR_TEXT = 305; + + public static final int COULDNT_VERIFY = 310; + + public static final int CERTIFICATE_NOT_FOUND = 313; + public static final int NOT_SEMANTICALLY_EQUAL = 314; + + public static final int MODIFIED_AFTER_SIGNATION = 316; + public static final int NON_BINARY_SIGNATURES_PRESENT = 317; + + public static final int UNSUPPORTED_REPLACES_NAME = 318; + public static final int UNSUPPORTED_SIGNATURE = 319; + + public static final int DETACHED_SIGNATURE_NOT_SUPPORTED = 370; + + public static final int SIGNATURE_VERIFICATION_NOT_SUPPORTED = 371; + public static final int INVALID_SIGNING_TIME = 372; + + public static final int BKU_NOT_SUPPORTED = 373; + + public static final int WEB_EXCEPTION = 330; + public static final int UNABLE_TO_RECEIVE_SUITABLE_RESPONSE = 340; + + + public static final int NORMALIZER_EXCEPTION = 400; + + public static final int SESSION_EXPIRED = 600; + + public static final int PLACEHOLDER_EXCEPTION = 700; + public static final int CAPTION_NOT_FOUND_EXCEPTION = 701; + + public static final int UNABLE_TO_PARSE_ID = 800; + public static final int CORRECTOR_EXCEPTION = 801; + public static final int EXTERNAL_CORRECTOR_TIMEOUT_REACHED = 802; + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/ErrorCodeHelper.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/ErrorCodeHelper.java new file mode 100644 index 0000000..25644cd --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/ErrorCodeHelper.java @@ -0,0 +1,119 @@ +/** + * 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.exceptions; + +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.exceptions.external.ExternalErrorException; +import at.gv.egiz.pdfas.exceptions.pdf.CaptionNotFoundException; +import at.knowcenter.wag.egov.egiz.cfg.SettingsReader; +import at.knowcenter.wag.egov.egiz.exceptions.PlaceholderException; +import at.knowcenter.wag.egov.egiz.exceptions.SettingNotFoundException; +import at.knowcenter.wag.egov.egiz.exceptions.SettingsException; + +/** + * @author wprinz + * + */ +public class ErrorCodeHelper +{ + /** + * The log. + */ + private static final Log log = LogFactory.getLog(ErrorCodeHelper.class); + + public static String getMessageForErrorCode(int errorCode) + { + try + { + SettingsReader settings = SettingsReader.getInstance(); + String message = settings.getSetting("error.code." + errorCode); + return message; + } + catch (SettingsException e) + { + log.warn(e.getMessage(), e); + } + catch (SettingNotFoundException e) + { + log.warn(e.getMessage(), e); + } + return null; + } + + /** + * Forms a speaking textual error message for the given PdfAsException. + * + * @param e + * The PdfAsException to be formed into a speaking text. + * @return Returns the speaking error message explaining the PdfAsException. + */ + public static String formErrorMessage(PdfAsException e) + { + String message = "Fehler " + e.getErrorCode() + ":"; + + if (e.getErrorCode() == ErrorCode.PLACEHOLDER_EXCEPTION) + { + PlaceholderException phe = null; + if (e instanceof PlaceholderException) + { + phe = (PlaceholderException) e; + } + else + { + phe = (PlaceholderException) e.getCause(); + } + + message += " Der Platzhalter des Feldes " + phe.getField() + " ist um " + phe.getMissing() + " Bytes zu kurz."; + } + + if (e.getErrorCode() == ErrorCode.CAPTION_NOT_FOUND_EXCEPTION) + { + CaptionNotFoundException cnfe = null; + if (e instanceof CaptionNotFoundException) + { + cnfe = (CaptionNotFoundException)e; + } + else + { + cnfe = (CaptionNotFoundException)e.getCause(); + } + + message += " Die Überschrift (Caption/Label) \"" + cnfe.getCaption() + "\" wurde nicht wiedergefunden."; + } + + message += " " + ErrorCodeHelper.getMessageForErrorCode(e.getErrorCode()); + + if (e instanceof ExternalErrorException) + { + ExternalErrorException eee = (ExternalErrorException) e; + message += " Externer Fehlergrund: " + eee.getExternalErrorCode() + ": " + eee.getExternalErrorMessage(); + } + + return message; + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/external/ExternalErrorException.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/external/ExternalErrorException.java new file mode 100644 index 0000000..56ae6b8 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/external/ExternalErrorException.java @@ -0,0 +1,66 @@ +/** + * 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.exceptions.external; + +import at.gv.egiz.pdfas.exceptions.ErrorCode; +import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException; + +public class ExternalErrorException extends ConnectorException +{ + + /** + * SVUID. + */ + private static final long serialVersionUID = 2108427722915583885L; + + protected String externalErrorCode; + + protected String externalErrorMessage; + + public ExternalErrorException(String externalErrorCode, String externalErrorMessage) + { + super(ErrorCode.EXTERNAL_ERROR, "External Error " + externalErrorCode + ": " + externalErrorMessage); + + this.externalErrorCode = externalErrorCode; + this.externalErrorMessage = externalErrorMessage; + } + + /** + * @return the externalErrorCode + */ + public String getExternalErrorCode() + { + return externalErrorCode; + } + + /** + * @return the externalErrorMessage + */ + public String getExternalErrorMessage() + { + return externalErrorMessage; + } + + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/framework/CorrectorException.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/framework/CorrectorException.java new file mode 100644 index 0000000..ed2329f --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/framework/CorrectorException.java @@ -0,0 +1,56 @@ +/** + * 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.exceptions.framework; + +import at.knowcenter.wag.egov.egiz.exceptions.PresentableException; + +/** + * Exceptions thrown by Correctors. + * + * @author wprinz + * + */ +public class CorrectorException extends PresentableException +{ + /** + * SVUID. + */ + private static final long serialVersionUID = -8646964226476111797L; + + public CorrectorException(int errorCode, String message, Throwable cause) + { + super(errorCode, message, cause); + } + + public CorrectorException(int errorCode, String message) + { + super(errorCode, message); + } + + public CorrectorException(int errorCode, Throwable cause) + { + super(errorCode, cause); + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/framework/PlaceholderExtractionException.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/framework/PlaceholderExtractionException.java new file mode 100644 index 0000000..62792c8 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/framework/PlaceholderExtractionException.java @@ -0,0 +1,79 @@ +/** + * 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.exceptions.framework; + +import at.gv.egiz.pdfas.exceptions.ErrorCode; +import at.knowcenter.wag.egov.egiz.exceptions.PresentableException; + +/** + * Exceptions thrown if STRICT matching mode for placeholder extraction is set and no placeholder could be found. + * + * @author exthex + * + */ +public class PlaceholderExtractionException extends PresentableException +{ + private static final long serialVersionUID = 0L; + + /** + * Constructor. + * + * @param errorCode the error code + * @param message the additional message + * @param cause the causing exception + * + * @see ErrorCode#SIGNATURE_PLACEHOLDER_EXTRACTION_FAILED + */ + public PlaceholderExtractionException(int errorCode, String message, Throwable cause) + { + super(errorCode, message, cause); + } + + /** + * Constructor. + * + * @param errorCode the error code + * @param message the additional message + * + * @see ErrorCode#SIGNATURE_PLACEHOLDER_EXTRACTION_FAILED + */ + public PlaceholderExtractionException(int errorCode, String message) + { + super(errorCode, message); + } + + /** + * Constructor. + * + * @param errorCode the error code + * @param cause the causing exception + * + * @see ErrorCode#SIGNATURE_PLACEHOLDER_EXTRACTION_FAILED + */ + public PlaceholderExtractionException(int errorCode, Throwable cause) + { + super(errorCode, cause); + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/framework/SignatorException.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/framework/SignatorException.java new file mode 100644 index 0000000..0e819eb --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/framework/SignatorException.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.exceptions.framework; + +import at.knowcenter.wag.egov.egiz.exceptions.PresentableException; + + +/** + * Exception thrown by the Signators. + * @author wprinz + */ +public class SignatorException extends PresentableException +{ + + /** + * SVUID. + */ + private static final long serialVersionUID = 5051232904560832089L; + + public SignatorException(int error_code, String message, Throwable cause) + { + super(error_code, message, cause); + } + + public SignatorException(int error_code, String message) + { + super(error_code, message); + } + + public SignatorException(int error_code, Throwable cause) + { + super(error_code, cause); + } + + public SignatorException(PresentableException pe) + { + super(pe.getErrorCode(), pe); + } +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/framework/VerificationFilterException.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/framework/VerificationFilterException.java new file mode 100644 index 0000000..92ef04d --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/framework/VerificationFilterException.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.exceptions.framework; + +import at.knowcenter.wag.egov.egiz.exceptions.PresentableException; + +/** + * Wrapper exception for the VerificationFilter. + * + * @author wprinz + */ +public class VerificationFilterException extends PresentableException +{ + /** + * SVUID. + */ + private static final long serialVersionUID = -3863253910537746742L; + + public VerificationFilterException(int errorCode, String message, Throwable cause) + { + super(errorCode, message, cause); + } + + public VerificationFilterException(int errorCode, String message) + { + super(errorCode, message); + } + + public VerificationFilterException(int errorCode, Throwable cause) + { + super(errorCode, cause); + } + + public VerificationFilterException(PresentableException cause) + { + super(cause.getErrorCode(), cause); + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/framework/VerificatorFactoryException.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/framework/VerificatorFactoryException.java new file mode 100644 index 0000000..93d26cc --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/framework/VerificatorFactoryException.java @@ -0,0 +1,69 @@ +/** + * 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.exceptions.framework; + +import at.gv.egiz.pdfas.exceptions.ErrorCode; +import at.knowcenter.wag.egov.egiz.exceptions.PresentableException; + +/** + * @author wprinz + * + */ +public class VerificatorFactoryException extends PresentableException +{ + + /** + * + */ + private static final long serialVersionUID = 8765156531863056335L; + + /** + * @param errorCode + * @param message + */ + public VerificatorFactoryException(String message) + { + super(ErrorCode.COULDNT_VERIFY, message); + } + + /** + * @param errorCode + * @param message + * @param cause + */ + public VerificatorFactoryException(String message, Throwable cause) + { + super(ErrorCode.COULDNT_VERIFY, message, cause); + } + + /** + * @param errorCode + * @param cause + */ + public VerificatorFactoryException(Throwable cause) + { + super(ErrorCode.COULDNT_VERIFY, cause); + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/pdf/CaptionNotFoundException.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/pdf/CaptionNotFoundException.java new file mode 100644 index 0000000..9a89269 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/pdf/CaptionNotFoundException.java @@ -0,0 +1,75 @@ +/** + * 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.exceptions.pdf; + +import at.gv.egiz.pdfas.exceptions.ErrorCode; +import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException; + +/** + * Exception thrown when a caption ("label") is not found in the content stream + * when determining the placeholders. + * + *

+ * This usually happens when the space for a caption is too small. Then the + * caption is wrapped into two lines and usually the separating whitespace is + * lost thus the BinarySignature is unable to find the caption String. + *

+ * + * @author wprinz + */ +public class CaptionNotFoundException extends PDFDocumentException +{ + + /** + * SVUID. + */ + private static final long serialVersionUID = -8959043531007857665L; + + /** + * The problematic caption. + */ + protected String caption = null; + + /** + * Constructor. + * + * @param caption + * The problematic caption. + */ + public CaptionNotFoundException(String caption) + { + super(ErrorCode.CAPTION_NOT_FOUND_EXCEPTION, "Caption not found in content stream. caption = " + caption); + this.caption = caption; + } + + /** + * Returns the problematic caption. + * + * @return Returns the problematic caption. + */ + public String getCaption() + { + return this.caption; + } +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/pdf/KZSettingNotFoundException.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/pdf/KZSettingNotFoundException.java new file mode 100644 index 0000000..81e52be --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/pdf/KZSettingNotFoundException.java @@ -0,0 +1,47 @@ +/** + * 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.exceptions.pdf; + +import at.gv.egiz.pdfas.exceptions.ErrorCode; +import at.knowcenter.wag.egov.egiz.exceptions.SettingNotFoundException; + +/** + * @author wprinz + * + */ +public class KZSettingNotFoundException extends SettingNotFoundException +{ + + /** + * SVUID. + */ + private static final long serialVersionUID = 2516636821733440462L; + + public KZSettingNotFoundException(String message) + { + super(ErrorCode.KZ_SETTING_NOT_FOUND, message); + } + + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/web/SessionExpiredException.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/web/SessionExpiredException.java new file mode 100644 index 0000000..d19ae8a --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/web/SessionExpiredException.java @@ -0,0 +1,68 @@ +/** + * 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.exceptions.web; + +import at.gv.egiz.pdfas.exceptions.ErrorCode; +import at.knowcenter.wag.egov.egiz.exceptions.PresentableException; + +/** + * @author wprinz + * + */ +public class SessionExpiredException extends PresentableException +{ + /** + * SVUID. + */ + private static final long serialVersionUID = -1877790545371341233L; + + /** + * @param errorCode + * @param message + */ + public SessionExpiredException(String message) + { + super(ErrorCode.SESSION_EXPIRED, message); + } + + /** + * @param errorCode + * @param message + * @param cause + */ + public SessionExpiredException(String message, Throwable cause) + { + super(ErrorCode.SESSION_EXPIRED, message, cause); + } + + /** + * @param errorCode + * @param cause + */ + public SessionExpiredException(Throwable cause) + { + super(ErrorCode.SESSION_EXPIRED, cause); + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/ConnectorFactory.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/ConnectorFactory.java new file mode 100644 index 0000000..c9b6238 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/ConnectorFactory.java @@ -0,0 +1,107 @@ +/** + * 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.framework; + +import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException; +import at.knowcenter.wag.egov.egiz.exceptions.ConnectorFactoryException; +import at.knowcenter.wag.egov.egiz.sig.connectors.Connector; +import at.knowcenter.wag.egov.egiz.sig.connectors.bku.EnvelopedBase64BKUConnector; +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.moa.EnvelopingBase64MOAConnector; +import at.knowcenter.wag.egov.egiz.sig.connectors.moa.MOASoapWithAttachmentConnector; + +/** + * @author wprinz + */ +public class ConnectorFactory +{ + // TODO the functionality of the connector should be split into template + // handling and the actualy hardware access + + public static String DETACHED_MULTIPART_BKU_CONNECTOR = "DetachedMultipartBKUConnector"; + + public static String ENVELOPING_BASE64_BKU_CONNECTOR = "EnvelopingBase64BKUConnector"; + + public static String OLD_ENVELOPING_BASE64_BKU_CONNECTOR = "OldEnvelopingBase64BKUConnector"; + + public static String DETACHED_LOCREF_MOA_CONNECTOR = "DetachedLocRefMOAConnector"; + + public static String ENVELOPING_BASE64_MOA_CONNECTOR = "EnvelopingBase64MOAConnector"; + + + + public static Connector createConnector (String connectorId, ConnectorParameters connectorParameters) throws ConnectorFactoryException, ConnectorException + { + if (connectorId.equals(DETACHED_MULTIPART_BKU_CONNECTOR)) + { + return new MultipartDetachedBKUConnector(connectorParameters); + } + + if (connectorId.equals(ENVELOPING_BASE64_BKU_CONNECTOR)) + { + return new EnvelopedBase64BKUConnector(connectorParameters.getProfileId()); + } + + if (connectorId.equals(OLD_ENVELOPING_BASE64_BKU_CONNECTOR)) + { + return new OldEnvelopingBase64BKUConnector(connectorParameters.getProfileId()); + } + + if (connectorId.equals(DETACHED_LOCREF_MOA_CONNECTOR)) + { +// TODO Hier wird der neue Connector verwendet +// return new DetachedLocRefMOAConnector(profile, locRef); + return new MOASoapWithAttachmentConnector(connectorParameters); + } + + if (connectorId.equals(ENVELOPING_BASE64_MOA_CONNECTOR)) + { +// TODO Hier wird NICHT der neue Connector verwendet + return new EnvelopingBase64MOAConnector(connectorParameters); +// return new MOASoapWithAttachmentConnector(profile); + } + + throw new ConnectorFactoryException("The connector Id " + connectorId + " couldn't be found by the ConnectorFactory."); + } + + public static boolean isMOA (String connectorId) + { + if (connectorId.equals(DETACHED_LOCREF_MOA_CONNECTOR) || connectorId.equals(ENVELOPING_BASE64_MOA_CONNECTOR)) + { + return true; + } + + return false; + } + +// public static Connector createConnectorForCommandline (String connectorId) throws ConnectorFactoryException +// { +// } +// +// public static Connector createConnectorForCommandline (String connectorId) throws ConnectorFactoryException +// { +// } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/ConnectorParameters.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/ConnectorParameters.java new file mode 100644 index 0000000..a0b7ceb --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/ConnectorParameters.java @@ -0,0 +1,118 @@ +/** + * 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.framework; + +import java.util.Date; + +/** + * Parameters passed to the constructor of the Connector. + * + *

+ * Each Connector must have a constructor accepting this parameter class as an + * argument. + *

+ * + * @author wprinz + */ +public class ConnectorParameters { + /** + * The profile Id to get the connector parameters from. + * + *

+ * The there are no explicit parameters for the connector in the profile, the + * default parameters are used. + *

+ */ + protected String profileId = null; + + /** + * The signature key identifier to be used or null if it should be read from + * the profile. + * + *

+ * Currently this is only used by MOA connectors and identifies the MOA key + * group to be used when signing. If null, the MOA connector reads the key + * from the profile. + *

+ */ + protected String signatureKeyIdentifier = null; + + /** + * Tells, if the connector should ask the device to return the hash input + * data. + * + *

+ * Note that not all connectors support to return the hash input data - so + * there is no guarantee that the hash value will actually be returned. + *

+ */ + protected boolean returnHashInputData = false; + + /** + * Allows to specify an explicit time of verification. + * + *

+ * If null, the device's default behaviour determines the time of + * verification, which is usually the current time. + *

+ *

+ * The time of verification usually influences the certificate check. E.g. + * the certificate may not be valid at the time of verification. + *

+ */ + protected Date verificationTime = null; + + public String getProfileId() { + return this.profileId; + } + + public void setProfileId(String profileId) { + this.profileId = profileId; + } + + public String getSignatureKeyIdentifier() { + return this.signatureKeyIdentifier; + } + + public void setSignatureKeyIdentifier(String signatureKeyIdentifier) { + this.signatureKeyIdentifier = signatureKeyIdentifier; + } + + public boolean isReturnHashInputData() { + return this.returnHashInputData; + } + + public void setReturnHashInputData(boolean returnHashInputData) { + this.returnHashInputData = returnHashInputData; + } + + public Date getVerificationTime() { + return this.verificationTime; + } + + public void setVerificationTime(Date verificationTime) { + this.verificationTime = verificationTime; + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/DataManager.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/DataManager.java new file mode 100644 index 0000000..4f0641a --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/DataManager.java @@ -0,0 +1,55 @@ +/** + * 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.framework; + +/** + * The DataManager is a mediator for all components that need to allocate large + * data elements. + * + *

+ * The DataManager uses a certain DataStrategy to perform the actual tasks. The + * strategy may be different in different environments. E.g. The commandline may + * implement a strategy to keep all data in memory, whereas the web might + * implement one that puts as many data onto the disk as possible to save + * memory. + *

+ * + * @author wprinz + * + */ +public class DataManager +{ + protected static DataStrategy dataStrategy = null; + + public static void initialize(DataStrategy ds) + { + dataStrategy = ds; + } + + public static DataStrategy getDataStrategy() + { + return dataStrategy; + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/DataSourceHolder.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/DataSourceHolder.java new file mode 100644 index 0000000..355da37 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/DataSourceHolder.java @@ -0,0 +1,45 @@ +/** + * 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.framework; + +import at.gv.egiz.pdfas.framework.input.DataSource; + +public class DataSourceHolder { + private DataSource dataSource; + + public DataSourceHolder(DataSource dataSource) { + this.dataSource = dataSource; + } + + public DataSource getDataSource() { + return dataSource; + } + + public void setDataSource(DataSource dataSource) { + this.dataSource = dataSource; + } + + + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/DataStrategy.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/DataStrategy.java new file mode 100644 index 0000000..659ba1d --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/DataStrategy.java @@ -0,0 +1,57 @@ +/** + * 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.framework; + +import java.io.InputStream; + +import at.gv.egiz.pdfas.framework.input.DataSource; +import at.gv.egiz.pdfas.framework.input.PdfDataSource; +import at.gv.egiz.pdfas.framework.input.TextDataSource; +import at.gv.egiz.pdfas.framework.output.DataSink; + +/** + * Factory for creating DataSources. + * + * @author wprinz + */ +public interface DataStrategy +{ + + public TextDataSource createTextDataSource (String text); + + public PdfDataSource createPdfDataSource (InputStream is); + + public PdfDataSource createPdfDataSource (DataSource other, int length); + + /** + * @deprecated - use streaming. + * @param pdf + * @return + */ + public PdfDataSource createPdfDataSource (byte [] pdf); + + public void destroyDataSource (DataSource dataSource); + + public DataSink createDataSink (); +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/SignatorFactory.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/SignatorFactory.java new file mode 100644 index 0000000..891551c --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/SignatorFactory.java @@ -0,0 +1,131 @@ +/** + * 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.framework; + +import at.knowcenter.wag.egov.egiz.PdfASID; +import at.knowcenter.wag.egov.egiz.exceptions.SignatorFactoryException; +import at.gv.egiz.pdfas.impl.signator.binary.BinarySignator_1_0_0; +import at.gv.egiz.pdfas.impl.signator.binary.BinarySignator_1_1_0; +import at.gv.egiz.pdfas.impl.signator.detached.DetachedTextualSignator_1_0_0; +import at.gv.egiz.pdfas.impl.signator.textual.TextualSignator_1_0_0; +import at.gv.egiz.pdfas.impl.signator.textual.TextualSignator_1_1_0; +import at.gv.egiz.pdfas.impl.signator.textual.TextualSignator_1_2_0; +import at.gv.egiz.pdfas.framework.signator.Signator; + +/** + * @author wprinz + * + */ +public class SignatorFactory +{ + /** + * The Vendor. + */ + public static final String VENDOR = "bka.gv.at"; //$NON-NLS-1$ + + /** + * The binary Signator algorithm. + */ + public static final String TYPE_BINARY = "binaer"; //$NON-NLS-1$ + + /** + * The textual Signator algorithm. + */ + public static final String TYPE_TEXTUAL = "text"; //$NON-NLS-1$ + + /** + * Detached Signator. + */ + public static final String TYPE_DETACHED_TEXTUAL = "detachedtext"; //$NON-NLS-1$ + + /** + * This application's current algorithm versions. + */ + public static final String VERSION_1_0_0 = "v1.0.0"; //$NON-NLS-1$ + + /** + * This application's current algorithm versions. + */ + public static final String VERSION_1_1_0 = "v1.1.0"; //$NON-NLS-1$ + + /** + * This application's current algorithm versions. + */ + public static final String VERSION_1_2_0 = "v1.2.0"; //$NON-NLS-1$ + + + public static Signator createSignator (PdfASID id) throws SignatorFactoryException + { + if (!id.getVendor().equals(VENDOR)) + { + throw new SignatorFactoryException("The vendor '" + id.getVendor() + "' is unrecognized by this SignatorFactory. (id='" + id + "')"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + + if (id.getType().equals(TYPE_BINARY)) + { + if (id.getVersion().equals(VERSION_1_0_0)) + { + return new BinarySignator_1_0_0(); + } + if (id.getVersion().equals(VERSION_1_1_0)) + { + return new BinarySignator_1_1_0(); + } + + throw new SignatorFactoryException("The version '" + id.getVersion() + "' of type '" + id.getType() + "' is not supported by this SignatorFactory. (id='" + id + "')"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + } + + if (id.getType().equals(TYPE_TEXTUAL)) + { + if (id.getVersion().equals(VERSION_1_0_0)) + { + return new TextualSignator_1_0_0(); + } + if (id.getVersion().equals(VERSION_1_1_0)) + { + return new TextualSignator_1_1_0(); + } + if (id.getVersion().equals(VERSION_1_2_0)) + { + return new TextualSignator_1_2_0(); + } + + + throw new SignatorFactoryException("The version '" + id.getVersion() + "' of type '" + id.getType() + "' is not supported by this SignatorFactory. (id='" + id + "')"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + } + + if (id.getType().equals(TYPE_DETACHED_TEXTUAL)) + { + if (id.getVersion().equals(VERSION_1_0_0)) + { + return new DetachedTextualSignator_1_0_0(); + } + + throw new SignatorFactoryException("The version '" + id.getVersion() + "' of type '" + id.getType() + "' is not supported by this SignatorFactory. (id='" + id + "')"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + } + + throw new SignatorFactoryException("The type '" + id.getType() + "' is not supported by this SignatorFactory. (id='" + id + "')"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/SignatureHolderHelper.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/SignatureHolderHelper.java new file mode 100644 index 0000000..7aaa285 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/SignatureHolderHelper.java @@ -0,0 +1,57 @@ +/** + * 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.framework; + +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import at.knowcenter.wag.egov.egiz.pdf.EGIZDate; +import at.knowcenter.wag.egov.egiz.pdf.SignatureHolder; + +public final class SignatureHolderHelper +{ + + /** + * Sorts the List of SignatureHolders by date. + * + * @param signatureHolders + * The List of SignatureHolders. + */ + public static void sortByDate(List signatureHolders) + { + Collections.sort(signatureHolders, new Comparator() { + public int compare(Object o1, Object o2) + { + SignatureHolder sh1 = (SignatureHolder) o1; + SignatureHolder sh2 = (SignatureHolder) o2; + + EGIZDate date1 = EGIZDate.parseFromString(sh1.getSignatureObject().getSignationDate()); + EGIZDate date2 = EGIZDate.parseFromString(sh2.getSignatureObject().getSignationDate()); + + return date1.compareTo(date2); + } + }); + } +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/VerificatorFactory.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/VerificatorFactory.java new file mode 100644 index 0000000..2cc964b --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/VerificatorFactory.java @@ -0,0 +1,65 @@ +/** + * 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.framework; + +import at.gv.egiz.pdfas.exceptions.framework.VerificatorFactoryException; +import at.gv.egiz.pdfas.framework.verificator.Verificator; +import at.gv.egiz.pdfas.impl.verificator.binary.BinaryVerificator_1_0_0; +import at.gv.egiz.pdfas.impl.verificator.binary.BinaryVerificator_1_1_0; +import at.knowcenter.wag.egov.egiz.PdfASID; +import at.knowcenter.wag.egov.egiz.framework.SignatorFactory; + +/** + * @author wprinz + * + */ +public class VerificatorFactory +{ + + public static Verificator createVerificator(PdfASID kz) throws VerificatorFactoryException + { + if (kz.getType().equals(SignatorFactory.TYPE_BINARY)) + { + return createBinaryVerificator(kz); + } + + return null; + } + + public static Verificator createBinaryVerificator(PdfASID kz) throws VerificatorFactoryException + { + assert kz.getType().equals(SignatorFactory.TYPE_BINARY); + + if (kz.equals(BinaryVerificator_1_0_0.MY_ID)) + { + return new BinaryVerificator_1_0_0(); + } + if (kz.equals(BinaryVerificator_1_1_0.MY_ID)) + { + return new BinaryVerificator_1_1_0(); + } + + throw new VerificatorFactoryException("kz is not a known binary signator " + kz); + } +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/config/SettingsHelper.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/config/SettingsHelper.java new file mode 100644 index 0000000..fc9860a --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/config/SettingsHelper.java @@ -0,0 +1,81 @@ +/** + * 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.framework.config; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.pdfas.framework.vfilter.VerificationFilterParameters; +import at.gv.egiz.pdfas.impl.vfilter.VerificationFilterParametersImpl; +import at.knowcenter.wag.egov.egiz.cfg.SettingsReader; +import at.knowcenter.wag.egov.egiz.exceptions.SettingsException; + +/** + * Contains helpful Settings functions. + * + * @author wprinz + */ +public final class SettingsHelper +{ + /** + * The log. + */ + private static final Log log = LogFactory.getLog(SettingsHelper.class); + + public static VerificationFilterParameters readVerificationFilterParametersFromSettings() throws SettingsException + { + boolean binaryOnly = getFlag("binary_only"); + boolean assumeOnlySB = getAssumeSB(); + boolean checkOld = getFlag("check_old_textual_sigs"); + + VerificationFilterParameters vfp = new VerificationFilterParametersImpl(binaryOnly, assumeOnlySB, checkOld); + return vfp; + } + + protected static boolean getFlag(String settingsKey) throws SettingsException + { + String flag = SettingsReader.getInstance().getSetting(settingsKey, "false"); + boolean b = true; + if (flag.equals("false")) + { + b = false; + } + return b; + } + + protected static boolean getAssumeSB() throws SettingsException + { + // backward compatibility for typo + String setting_with_typo = SettingsReader.getInstance().getSetting("assume_only_signauture_blocks", null); + if (setting_with_typo != null) + { + log.warn("You still have the typo in your configuration file. Please change 'assume_only_signauture_blocks' to 'assume_only_signature_blocks'. Thanks."); + boolean assumeOnlySB_typo = getFlag("assume_only_signauture_blocks"); + return assumeOnlySB_typo; + } + + boolean assumeOnlySB = getFlag("assume_only_signature_blocks"); + return assumeOnlySB; + } +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/input/DataSource.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/input/DataSource.java new file mode 100644 index 0000000..f834622 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/input/DataSource.java @@ -0,0 +1,70 @@ +/** + * 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.framework.input; + +import java.io.InputStream; + +/** + * The input document data source. + * + *

+ * Usually this is a PdfDataSource, but it may be a TextDataSource as well. + *

+ * + * @author wprinz + * + */ +public interface DataSource +{ + /** + * Creates a new InputStream that allows to read out the document's binary + * data from the beginning. + * + * @return Returns the InputStream with the binary data. + */ + public InputStream createInputStream(); + + /** + * Returns the length (number of bytes) of the stream. + * + * @return Returns the length (number of bytes) of the stream. + */ + public int getLength(); + + /** + * Returns the data of this DataSource as a byte array. + * + *

+ * Calling this method indicates that you need a byte array for random read access. + * The DataSource implementation should of course cache this byte array to avoid too much memory usage. + *

+ *

+ * Performance analysis has shown that the libraries internally convert the streams to byte arrays and + * that file system access is very slow. + *

+ * + * @return + */ + public byte [] getAsByteArray(); +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/input/ExtractionStage.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/input/ExtractionStage.java new file mode 100644 index 0000000..19065b0 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/input/ExtractionStage.java @@ -0,0 +1,90 @@ +/** + * 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.framework.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.exceptions.framework.VerificationFilterException; +import at.gv.egiz.pdfas.framework.DataSourceHolder; +import at.gv.egiz.pdfas.framework.vfilter.VerificationFilter; +import at.gv.egiz.pdfas.framework.vfilter.VerificationFilterParameters; +import at.gv.egiz.pdfas.impl.input.IncrementalUpdateParser; +import at.gv.egiz.pdfas.impl.vfilter.VerificationFilterImpl; +import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException; +import at.knowcenter.wag.egov.egiz.exceptions.PresentableException; + +/** + * Extracts all signatures from a given input DataSource. + * + * @author wprinz + */ +public class ExtractionStage +{ + /** + * The log. + */ + private static final Log log = LogFactory.getLog(ExtractionStage.class); + + public List extractSignatureHolders(final DataSourceHolder dataSource, VerificationFilterParameters parameters) throws PresentableException + { + if (dataSource.getDataSource() instanceof PdfDataSource) + { + PdfDataSource pdfDataSource = (PdfDataSource) dataSource.getDataSource(); + + PdfDataSourceHolder pdsh = new PdfDataSourceHolder(pdfDataSource); + List blocks = parsePdfIntoBlocks(pdsh); + dataSource.setDataSource(pdsh.getDataSource()); + parameters.setBeenCorrected(pdsh.hasChanged()); + + VerificationFilter vf = new VerificationFilterImpl(); + List signatures = vf.extractSignatureHolders(pdsh.getDataSource(), blocks, parameters); + + return signatures; + } + + if (dataSource.getDataSource() instanceof TextDataSource) + { + TextDataSource textDataSource = (TextDataSource) dataSource.getDataSource(); + + VerificationFilter vf = new VerificationFilterImpl(); + List signatures = vf.extractSignaturHolders(textDataSource, parameters); + + return signatures; + } + + String msg = "The input DataSource is neither pdf nor text. class.name = " + dataSource.getClass().getName(); + log.error(msg); + throw new VerificationFilterException(ErrorCode.DOCUMENT_CANNOT_BE_READ, msg); + } + + protected List parsePdfIntoBlocks(PdfDataSourceHolder pdfDataSource) throws PDFDocumentException + { + List blocks = IncrementalUpdateParser.parsePdfIntoIUBlocks(pdfDataSource); + return blocks; + } +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/input/PdfDataSource.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/input/PdfDataSource.java new file mode 100644 index 0000000..ce3d658 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/input/PdfDataSource.java @@ -0,0 +1,41 @@ +/** + * 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.framework.input; + + +/** + * Represents the binary data of a PDF document. + * + *

+ * This interface allows Pdf data to be handled in an abstract way so that the + * storage (byta array, disk etc.) of pdf documents can be separated from the + * algorithms. + *

+ * + * @author wprinz + */ +public interface PdfDataSource extends DataSource +{ + // jsut a marker interface +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/input/PdfDataSourceHolder.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/input/PdfDataSourceHolder.java new file mode 100644 index 0000000..14a4ff4 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/input/PdfDataSourceHolder.java @@ -0,0 +1,49 @@ +/** + * 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.framework.input; + +public class PdfDataSourceHolder { + private PdfDataSource dataSource; + private boolean hasChanged = false; + + public PdfDataSourceHolder(PdfDataSource dataSource) { + this.dataSource = dataSource; + } + + public PdfDataSource getDataSource() { + return dataSource; + } + + public void setDataSource(PdfDataSource dataSource) { + this.dataSource = dataSource; + this.hasChanged = true; + } + + public boolean hasChanged() { + return this.hasChanged; + } + + + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/input/TextDataSource.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/input/TextDataSource.java new file mode 100644 index 0000000..7623896 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/input/TextDataSource.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.framework.input; + +/** + * Represents a free-text input text to be processed. + * + * @author wprinz + */ +public interface TextDataSource extends DataSource +{ + /** + * Returns the text to be processed. + * @return Returns the text to be processed. + */ + public String getText(); + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/input/correction/Corrector.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/input/correction/Corrector.java new file mode 100644 index 0000000..71f3ded --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/input/correction/Corrector.java @@ -0,0 +1,61 @@ +/** + * 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.framework.input.correction; + +import at.gv.egiz.pdfas.exceptions.framework.CorrectorException; +import at.gv.egiz.pdfas.framework.input.PdfDataSource; + +/** + * Interface for PDF corretors. + * + *

+ * Often PDF documents generated by various document to PDF converters have an + * invalid structure that upsets PDF-AS. The correction mechanism allows these + * documents to be corrected before being signed. + *

+ *

+ * A PDF corrector takes an incorrect PDF document and transforms it into a + * correct one. + *

+ *

+ * Note that correcting a document destroys all signatures in that document, so + * never correct an already signed document. + *

+ * + * @author wprinz + */ +public interface Corrector +{ + /** + * Corrects the given PDF document to a form that PDF-AS can use. + * + * @param document + * The (incorrect) PDF document. + * @return Returns the corrected PDF document. + * @throws CorrectorException + * Exception thrown if the document couldn't be corrected. + */ + public PdfDataSource correctDocument(PdfDataSource document) throws CorrectorException; + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/input/correction/CorrectorFactory.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/input/correction/CorrectorFactory.java new file mode 100644 index 0000000..8c954f7 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/input/correction/CorrectorFactory.java @@ -0,0 +1,63 @@ +/** + * 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.framework.input.correction; + +import at.gv.egiz.pdfas.impl.input.correction.ExternalCorrector; +import at.gv.egiz.pdfas.impl.input.correction.InternalCorrector; +import at.knowcenter.wag.egov.egiz.cfg.SettingsReader; +import at.knowcenter.wag.egov.egiz.exceptions.SettingsException; + +/** + * Factory for creating Correctors. + * + * @author wprinz + */ +public class CorrectorFactory +{ + public static final String INTERNAL_CORRECTOR = "internal"; + + public static final String EXTERNAL_CORRECTOR = "external"; + + public static final String CORRECTOR_KEY = "corrector"; + + public static Corrector createCorrector(String id) throws SettingsException + { + if (id.equals(INTERNAL_CORRECTOR)) + { + return new InternalCorrector(); + } + if (id.equals(EXTERNAL_CORRECTOR)) + { + return new ExternalCorrector(); + } + throw new SettingsException("The connector id '" + id + "' is not a valid corrector id."); + } + + public static Corrector createCorrector() throws SettingsException + { + String id = SettingsReader.getInstance().getSetting(CORRECTOR_KEY, INTERNAL_CORRECTOR); + return createCorrector(id); + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/output/DataSink.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/output/DataSink.java new file mode 100644 index 0000000..52959a9 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/output/DataSink.java @@ -0,0 +1,42 @@ +/** + * 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.framework.output; + +import java.io.OutputStream; + +/** + * Output document data sink. + * + * @author wprinz + */ +public interface DataSink +{ + public OutputStream createOutputStream(String mimeType); + + public OutputStream createOutputStream(String mimeType, String characterEncoding); + + public String getMimeType(); + + public String getCharacterEncoding(); +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/sigdevice/SequentialSignatureDevice.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/sigdevice/SequentialSignatureDevice.java new file mode 100644 index 0000000..4edc435 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/sigdevice/SequentialSignatureDevice.java @@ -0,0 +1,45 @@ +/** + * 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.framework.sigdevice; + +/** + * A SignatureDevice that can be accessed in a sequential manner. + * + *

+ * A sequential device handles all necessary steps in sequence. E.g. all the + * data is transformed into a http request and sent to a server. The server + * processes the request and answers. The response from the server is then + * analyzed and returned. + *

+ * + * @author wprinz + */ +public interface SequentialSignatureDevice extends SignatureDevice +{ + // This is just a concept how it could be realized in future. + public void sign(); + + public void verify(); + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/sigdevice/SignatureDevice.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/sigdevice/SignatureDevice.java new file mode 100644 index 0000000..eb7656a --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/sigdevice/SignatureDevice.java @@ -0,0 +1,36 @@ +/** + * 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.framework.sigdevice; + +/** + * Performs the task of passing the signature XML and data from the application + * to an external signature device and return the response in an form that the + * application can use. + * + * @author wprinz + */ +public interface SignatureDevice +{ + // Marker interface +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/signator/Signator.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/signator/Signator.java new file mode 100644 index 0000000..073af4d --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/signator/Signator.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. + * + * $Id: Signator.java,v 1.1 2006/08/25 17:07:21 wprinz Exp $ + */ +package at.gv.egiz.pdfas.framework.signator; + +import at.gv.egiz.pdfas.api.timestamp.TimeStamper; +import at.gv.egiz.pdfas.exceptions.framework.SignatorException; +import at.gv.egiz.pdfas.framework.input.PdfDataSource; +import at.gv.egiz.pdfas.framework.output.DataSink; +import at.knowcenter.wag.egov.egiz.PdfASID; +import at.knowcenter.wag.egov.egiz.pdf.TablePos; + +/** + * The basic interface for signator algorithms. + * + * @author wprinz + */ +public interface Signator +{ + /** + * Returns the PdfASID of this Connector. + * + *

+ * This should always return the MY_ID static field of the connector. Dont't + * forget to override this. + *

+ *

+ * Within connector code always use this method so that code reuse through + * derivation can take place correctly. + *

+ * + * @return Returns the PdfASID of this Connector. + */ + public PdfASID getMyId(); + + /** + * Suppies encoding for text extraction + * @return + */ + public String getEncoding(); + + // dferbas no more has_SIG_ID + + public SignatorInformation prepareSign(PdfDataSource pdfDataSource, + String profile, TablePos pos, TimeStamper timestamper) throws SignatorException; + + + public void finishSign(SignatorInformation signatorInformation, DataSink dataSink) throws SignatorException; +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/signator/SignatorInformation.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/signator/SignatorInformation.java new file mode 100644 index 0000000..f9efcbe --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/signator/SignatorInformation.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.framework.signator; + +import java.util.List; + +import at.gv.egiz.pdfas.api.analyze.NonTextObjectInfo; +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; + +/** + * Encapsulates the Signator dependant information that needs to be passed from + * prepareSign to finishSign. + * + *

+ * This supersedes the IncrementalUpdateInformation. + *

+ * + * @author wprinz + */ +public interface SignatorInformation +{ + /** + * Returns the SignatureData to be signed. + *

+ * This is passed on to the Connector and signature device for signing. + *

+ * + * @return Returns the SignatureData to be signed. + */ + public SignatureData getSignatureData(); + + /** + * Sets the SignSignatureObject with the signature data. + * + *

+ * This is called by the framework to provide the finishSign with the + * signature data. + *

+ * + * @param signSignatureObject + * The SignSignatureObject. + */ + public void setSignSignatureObject(SignSignatureObject signSignatureObject); + + /** + * Returns the SignSignatureObject. + * + *

+ * After signation, this is used by the framework/API to get additional + * information about the signature. + *

+ * + * @return Returns the SignSignatureObject. + */ + public SignSignatureObject getSignSignatureObject(); + + /** + * Returns the position where the signature table was actually placed. + * + * @return Returns the position where the signature table was actually placed. + */ + public ActualTablePos getActualTablePos(); + + /** + * Returns a list<{@link NonTextObjectInfo} of non textual objects in the pdf document. + * Only available for textual signatures. Show this to the user who signed the textual content only! + * @return List<{@link NonTextObjectInfo} or null of not available (binary signature) + */ + public List getNonTextualObjects(); + + /** + * Set a list<{@link NonTextObjectInfo} of non textual objects in the pdf document. + * Only available for textual signatures. Show this to the user who signed the textual content only! + */ + public void setNonTextualObjects(List nonTextObjects); +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/verificator/Verificator.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/verificator/Verificator.java new file mode 100644 index 0000000..78d6a2a --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/verificator/Verificator.java @@ -0,0 +1,61 @@ +/** + * 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: Verificator.java,v 1.1 2006/08/25 17:07:21 wprinz Exp $ + */ +package at.gv.egiz.pdfas.framework.verificator; + +import java.util.List; + +import at.gv.egiz.pdfas.framework.input.PdfDataSource; +import at.knowcenter.wag.egov.egiz.exceptions.PresentableException; +import at.knowcenter.wag.exactparser.parsing.results.FooterParseResult; + + +/** + * Given an Incremental Update Block and the corresponding PDF, a verificator + * extracts all Signatures of its type and returns them as valitatable + * SignatureHolders. + * + * @author wprinz + */ +public interface Verificator +{ + /** + * Parses the given document/Block for signatures of this type. + * + * @param pdf + * The whole pdf document. A Verificator must only access the + * document up to its given block (block.next_index) and must not + * modify any byte in the pdf array. + * @param block + * The incremental update block. + * @param start_of_whole_block + * The start of the incremental update block (the end of the previous + * block) - If 0, this is the first block (the original Document). + * @return Returns the List of SignatureHolder objects found for this block. + */ + public List parseBlock(PdfDataSource pdfDataSource, byte [] pdf, final FooterParseResult block, + int start_of_whole_block) throws PresentableException; + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/vfilter/VerificationFilter.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/vfilter/VerificationFilter.java new file mode 100644 index 0000000..58422d2 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/vfilter/VerificationFilter.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.framework.vfilter; + +import java.util.List; + +import at.gv.egiz.pdfas.exceptions.framework.VerificationFilterException; +import at.gv.egiz.pdfas.framework.input.PdfDataSource; +import at.gv.egiz.pdfas.framework.input.TextDataSource; + +/** + * Extracts all signatures from a given PDF document or text. + * + * @see VerificationFilterParameters + * + * @author wprinz + */ +public interface VerificationFilter +{ + + /** + * Extracts the signatures from the given PDF. + * + * @param pdf + * The PDF. + * @param blocks + * The List of Incremental Update blocks. Usually this comes from a + * preprocessing step. + * @param parameters + * The algorithm parameters. + * @return Returns a List of SignatureHolders containing the signatures. May + * be empty in case no signatures have been found. + * @throws VerificationFilterException + * Thrown if something goes wrong. + */ + public List extractSignatureHolders(PdfDataSource pdf, List blocks, VerificationFilterParameters parameters) throws VerificationFilterException; + + /** + * Extracts the text signatures from the given free-text. + * + * @param text + * The free-text. + * @param parameters + * The algorithm parameters. + * @return Returns a List of SignatureHolders containing the signatures. May + * be empty in case no signatures have been found. + * @throws VerificationFilterException + * Thrown if something goes wrong. + */ + public List extractSignaturHolders(TextDataSource text, VerificationFilterParameters parameters) throws VerificationFilterException; +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/vfilter/VerificationFilterParameters.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/vfilter/VerificationFilterParameters.java new file mode 100644 index 0000000..cf99086 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/vfilter/VerificationFilterParameters.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.framework.vfilter; + +/** + * The parameters of the VerificationFilter algorithm. + * + * @author wprinz + */ +public interface VerificationFilterParameters +{ + + /** + * Tells the VerificationFilter to extract binary signatures only. + * + *

+ * Not scanning for textual signatures allows the algorithm to skip text + * extraction and signature extraction, which are both time and memory + * intensive processes. + *

+ * + * @return Returns true if the VerificationFilter should extract binary + * signatures only. + */ + public boolean extractBinarySignaturesOnly(); + + /** + * Tells the VerificationFilter to assume that there are only singatures (and + * their Incremental Update blocks) younger than the original document. + * + *

+ * This is equivalent to saying that the document was not updated using an + * Incremental update block other than a signature after being singed. The + * incremental update blocks after the original document contain only + * signatures (either text or binary). + *

+ *

+ * This is equivalent to saying that there exists no Incremental Update block + * that would render a text signature before it invalid. + *

+ *

+ * Under this assumption, the process of finding all text signatures + * simplifies to one text extraction of the whole document and one signature + * extraction. This is of course a massive performance gain. + *

+ *

+ * Actually the algorithm performs a text extraction of the whole document not + * including trailing binary signature Incremental Update blocks. This means + * that if a the last n Incremental Update blocks of a document are binary, + * there is no use extract text from them. + *

+ *

+ * Note that if there are Incremental Update blocks with text after a + * signature thus this assumption does not hold the signatures older than this + * block will break. + *

+ * + * @return Returns true if the Verification filter should assume that there + * are only signature blocks after the original document. + */ + public boolean assumeOnlySignatureUpdateBlocks(); + + /** + * Tells the VerificationFilter so scan for old signatures in the rest text. + * + *

+ * The rest text is the text of the oldest text signature or the original + * document text if there is no text signature. + *

+ * + * @return Returns true if the VerificationFilter should scan for old text + * signatures in the rest text. + */ + public boolean scanForOldSignatures(); + + /** + * Return value that tell if the document has been corrected before verification. + * + * @return + */ + public boolean hasBeenCorrected(); + + public void setBeenCorrected(boolean corrected); +} 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); + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/ByteArrayDataSink.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/ByteArrayDataSink.java new file mode 100644 index 0000000..03e7999 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/ByteArrayDataSink.java @@ -0,0 +1,107 @@ +/** + * 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.io; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import at.gv.egiz.pdfas.api.io.DataSink; + +/** + * @author wprinz + * + */ +public class ByteArrayDataSink implements DataSink +{ + /** + * The byte output stream. + */ + ByteArrayOutputStream baos = null; + + /** + * The mime type. + */ + protected String mimeType = null; + + /** + * The character encoding. + */ + protected String characterEncoding = null; + + /** + * @see at.gv.egiz.pdfas.api.io.DataSink#createOutputStream(java.lang.String) + */ + public OutputStream createOutputStream(String mimeType) throws IOException + { + return createOutputStream(mimeType, null); + } + + /** + * @see at.gv.egiz.pdfas.api.io.DataSink#createOutputStream(java.lang.String, + * java.lang.String) + */ + public OutputStream createOutputStream(String mimeType, String characterEncoding) throws IOException + { + this.mimeType = mimeType; + this.characterEncoding = characterEncoding; + this.baos = new ByteArrayOutputStream(); + return this.baos; + } + + /** + * @see at.gv.egiz.pdfas.api.io.DataSink#getMimeType() + */ + public String getMimeType() + { + return this.mimeType; + } + + /** + * @see at.gv.egiz.pdfas.api.io.DataSink#getCharacterEncoding() + */ + public String getCharacterEncoding() + { + return this.characterEncoding; + } + + /** + * Returns the byte data, or null if none available. + * + *

+ * Note that internally, this just calls the {@link ByteArrayOutputStream#toByteArray()} method. + *

+ * + * @return Returns the byte data, or null if none available. + */ + public byte [] getData() + { + if (this.baos == null) + { + return null; + } + return this.baos.toByteArray(); + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/ByteArrayDataSource.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/ByteArrayDataSource.java new file mode 100644 index 0000000..e00211a --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/ByteArrayDataSource.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.io; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +import at.gv.egiz.pdfas.api.io.DataSource; + +/** + * A byte array backed DataSource. + * + * @author wprinz + */ +public class ByteArrayDataSource implements DataSource +{ + + /** + * The byte array. + */ + protected byte[] data = null; + + /** + * The mime type. + */ + protected String mimeType = null; + + /** + * The character encoding. + */ + protected String characterEncoding = null; + + /** + * @param data + * @param mimeType + */ + public ByteArrayDataSource(byte[] data, String mimeType) + { + this(data, mimeType, null); + } + + /** + * @param data + * @param mimeType + * @param characterEncoding + */ + public ByteArrayDataSource(byte[] data, String mimeType, String characterEncoding) + { + this.data = data; + this.mimeType = mimeType; + this.characterEncoding = characterEncoding; + } + + /** + * @see at.gv.egiz.pdfas.api.io.DataSource#createInputStream() + */ + public InputStream createInputStream() + { + return new ByteArrayInputStream(this.data); + } + + /** + * @see at.gv.egiz.pdfas.api.io.DataSource#getAsByteArray() + */ + public byte[] getAsByteArray() + { + return this.data; + } + + /** + * @see at.gv.egiz.pdfas.api.io.DataSource#getCharacterEncoding() + */ + public String getCharacterEncoding() + { + return this.characterEncoding; + } + + /** + * @see at.gv.egiz.pdfas.api.io.DataSource#getMimeType() + */ + public String getMimeType() + { + return this.mimeType; + } + + /** + * @see at.gv.egiz.pdfas.api.io.DataSource#getLength() + */ + public int getLength() + { + return this.data.length; + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/FileBasedDataSink.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/FileBasedDataSink.java new file mode 100644 index 0000000..c93ad2a --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/FileBasedDataSink.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.io; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import at.gv.egiz.pdfas.api.io.DataSink; +import at.gv.egiz.pdfas.api.io.FileBased; + +/** + * @author wprinz + * + */ +public class FileBasedDataSink implements DataSink, FileBased +{ + protected File file = null; + + protected String mimeType = null; + + protected String characterEncoding = null; + + + + /** + * @param file + * @throws IOException + */ + 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.file = file; + } + + /** + * @throws FileNotFoundException + * @see at.gv.egiz.pdfas.api.io.DataSink#createOutputStream(java.lang.String) + */ + public OutputStream createOutputStream(String mimeType) throws FileNotFoundException + { + return createOutputStream(mimeType, null); + } + + /** + * @throws FileNotFoundException + * @see at.gv.egiz.pdfas.api.io.DataSink#createOutputStream(java.lang.String, + * java.lang.String) + */ + public OutputStream createOutputStream(String mimeType, String characterEncoding) throws FileNotFoundException + { + this.mimeType = mimeType; + this.characterEncoding = characterEncoding; + return new FileOutputStream(this.file); + } + + /** + * @see at.gv.egiz.pdfas.api.io.DataSink#getMimeType() + */ + public String getMimeType() + { + return this.mimeType; + } + + /** + * @see at.gv.egiz.pdfas.api.io.DataSink#getCharacterEncoding() + */ + public String getCharacterEncoding() + { + return this.characterEncoding; + } + + /** + * @see at.gv.egiz.pdfas.api.io.FileBased#getFile() + */ + public File getFile() + { + return this.file; + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/FileBasedDataSource.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/FileBasedDataSource.java new file mode 100644 index 0000000..7cb585d --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/FileBasedDataSource.java @@ -0,0 +1,141 @@ +/** + * 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.io; + +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 at.gv.egiz.pdfas.api.io.DataSource; +import at.gv.egiz.pdfas.api.io.FileBased; +import at.gv.egiz.pdfas.impl.input.helper.DataSourceHelper; + +/** + * A FileBased DataSource implementation. + * + * @author wprinz + */ +public class FileBasedDataSource implements DataSource, FileBased +{ + protected File file = null; + + protected String mimeType = null; + + protected String characterEncoding = null; + + protected byte[] cache = null; + + /** + * @param file + * @param mimeType + * @throws IOException + */ + public FileBasedDataSource(File file, String mimeType) throws IOException + { + this(file, mimeType, null); + } + + /** + * @param file + * @param mimeType + * @param characterEncoding + * @throws IOException + */ + public FileBasedDataSource(File file, String mimeType, String characterEncoding) throws IOException + { + if (file == null) + { + throw new IllegalArgumentException("The file must not be null."); + } + if (mimeType == null) + { + throw new IllegalArgumentException("The mimeType must not be null."); + } + 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.mimeType = mimeType; + this.characterEncoding = characterEncoding; + this.cache = DataSourceHelper.convertInputStreamToByteArrayIOEx(new FileInputStream(this.file)); + } + + /** + * @see at.gv.egiz.pdfas.api.io.DataSource#createInputStream() + */ + public InputStream createInputStream() + { + return new ByteArrayInputStream(this.cache); + } + + /** + * @see at.gv.egiz.pdfas.api.io.DataSource#getAsByteArray() + */ + public byte[] getAsByteArray() + { + return this.cache; + } + + /** + * @see at.gv.egiz.pdfas.api.io.DataSource#getLength() + */ + public int getLength() + { + return this.cache.length; + } + + /** + * @see at.gv.egiz.pdfas.api.io.DataSource#getMimeType() + */ + public String getMimeType() + { + return this.mimeType; + } + + /** + * @see at.gv.egiz.pdfas.api.io.DataSource#getCharacterEncoding() + */ + public String getCharacterEncoding() + { + return this.characterEncoding; + } + + /** + * @see at.gv.egiz.pdfas.api.io.FileBased#getFile() + */ + public File getFile() + { + return this.file; + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/FileBasedTextBasedDataSource.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/FileBasedTextBasedDataSource.java new file mode 100644 index 0000000..aaf99ea --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/FileBasedTextBasedDataSource.java @@ -0,0 +1,123 @@ +/** + * 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.io; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; + +import at.gv.egiz.pdfas.api.io.TextBased; + +/** + * FileBased DataSource that is TextBased. + * + * @author wprinz + */ +public class FileBasedTextBasedDataSource extends FileBasedDataSource implements TextBased +{ + protected String text = null; + + /** + * @param file + * @param mimeType + * @param characterEncoding + * @throws IOException + */ + public FileBasedTextBasedDataSource(File file, String mimeType, String characterEncoding) throws IOException + { + super(file, mimeType, characterEncoding); + if (characterEncoding == null) + { + throw new IllegalArgumentException("The characterEncoding must not be null."); + } + } + + /** + * @see at.gv.egiz.pdfas.api.io.DataSource#createInputStream() + */ + public InputStream createInputStream() + { + return new ByteArrayInputStream(this.cache); + } + + /** + * @see at.gv.egiz.pdfas.api.io.DataSource#getAsByteArray() + */ + public byte[] getAsByteArray() + { + return this.cache; + } + + /** + * @see at.gv.egiz.pdfas.api.io.DataSource#getLength() + */ + public int getLength() + { + return this.cache.length; + } + + /** + * @see at.gv.egiz.pdfas.api.io.DataSource#getMimeType() + */ + public String getMimeType() + { + return this.mimeType; + } + + /** + * @see at.gv.egiz.pdfas.api.io.DataSource#getCharacterEncoding() + */ + public String getCharacterEncoding() + { + return this.characterEncoding; + } + + /** + * @see at.gv.egiz.pdfas.api.io.FileBased#getFile() + */ + public File getFile() + { + return this.file; + } + + public String getText() + { + if (this.text == null) + { + try + { + this.text = new String(this.cache, this.characterEncoding); + } + catch (UnsupportedEncodingException e) + { + e.printStackTrace(); + throw new RuntimeException(e); + } + } + return this.text; + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/StringTextBasedDataSource.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/StringTextBasedDataSource.java new file mode 100644 index 0000000..8fe0dd6 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/StringTextBasedDataSource.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.io; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; + +import at.gv.egiz.pdfas.api.io.DataSource; +import at.gv.egiz.pdfas.api.io.TextBased; + +/** + * A String TextBased DataSource. + * + * @author wprinz + * + */ +public class StringTextBasedDataSource implements DataSource, TextBased +{ + /** + * The text. + */ + protected String text = null; + + protected byte[] cache = null; + + /** + * @param text + */ + public StringTextBasedDataSource(String text) + { + this.text = text; + } + + /** + * @see at.gv.egiz.pdfas.api.io.DataSource#createInputStream() + */ + public InputStream createInputStream() + { + return new ByteArrayInputStream(getAsByteArray()); + } + + /** + * @see at.gv.egiz.pdfas.api.io.DataSource#getAsByteArray() + */ + public byte[] getAsByteArray() + { + if (cache == null) + { + try + { + this.cache = this.text.getBytes("UTF-8"); + } + catch (UnsupportedEncodingException e) + { + e.printStackTrace(); + throw new RuntimeException(e); + } + } + return this.cache; + } + + /** + * @see at.gv.egiz.pdfas.api.io.DataSource#getLength() + */ + public int getLength() + { + return getAsByteArray().length; + } + + /** + * @see at.gv.egiz.pdfas.api.io.DataSource#getMimeType() + */ + public String getMimeType() + { + return "text/plain"; + } + + /** + * @see at.gv.egiz.pdfas.api.io.DataSource#getCharacterEncoding() + */ + public String getCharacterEncoding() + { + return "UTF-8"; + } + + /** + * @see at.gv.egiz.pdfas.api.io.TextBased#getText() + */ + public String getText() + { + return this.text; + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/performance/PerformanceCounter.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/performance/PerformanceCounter.java new file mode 100644 index 0000000..d03187c --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/performance/PerformanceCounter.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.performance; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * @author wprinz + */ +public class PerformanceCounter +{ + /** + * The log. + */ + private static Log log = LogFactory.getLog(PerformanceCounter.class); + + protected String name = null; + + protected long counter = 0; + + public PerformanceCounter(String name) + { + this.name = name; + reset(); + } + + public PerformanceCounter(Class clazz) + { + this(clazz.getName()); + } + + public void increment() + { + this.counter++; + log.trace(this.name + ": incremented to " + this.counter); + } + + public void reset() + { + this.counter = 0; + log.trace(this.name + ": reset to 0"); + } + + /** + * @return the name + */ + public String getName() + { + return this.name; + } + + /** + * @return the counter + */ + public long getCounter() + { + return this.counter; + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/performance/PerformanceCounters.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/performance/PerformanceCounters.java new file mode 100644 index 0000000..831c7c2 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/performance/PerformanceCounters.java @@ -0,0 +1,42 @@ +/** + * 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.performance; + +/** + * Contains various global PerformanceCounters that provide information about the system. + * + * @author wprinz + */ +public final class PerformanceCounters +{ + /** + * Keeps track of the number of text extractions done so far. + */ + public static PerformanceCounter textExtractions = new PerformanceCounter("TextExtractions"); + + /** + * Keeps track of the number of large byte array allocations. + */ + public static PerformanceCounter byteArrays = new PerformanceCounter("ByteArrays"); +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/performance/PerformanceTimer.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/performance/PerformanceTimer.java new file mode 100644 index 0000000..c405383 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/performance/PerformanceTimer.java @@ -0,0 +1,68 @@ +/** + * 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.performance; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * @author wprinz + * + */ +public class PerformanceTimer +{ + /** + * The log. + */ + private static Log log = LogFactory.getLog(PerformanceTimer.class); + + protected String name = null; + + protected long startTime = -1; + + protected long stopTime = -1; + + public PerformanceTimer(String name) + { + this.name = name; + } + + public void start() + { + this.startTime = System.currentTimeMillis(); + log.trace(this.name + ": started at " + this.startTime); + } + + public void stop() + { + this.stopTime = System.currentTimeMillis(); + log.trace(this.name + ": stopped at " + this.stopTime); + log.trace(this.name + ": time elapsed = " + getTimeElapsed()); + } + + public long getTimeElapsed() + { + return this.stopTime - this.startTime; + } +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/placeholder/SignaturePlaceholderContext.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/placeholder/SignaturePlaceholderContext.java new file mode 100644 index 0000000..0636304 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/placeholder/SignaturePlaceholderContext.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.placeholder; + +/** + * Store and retrieve {@link SignaturePlaceholderData} in/from a thread local context. + * + * @author exthex + * + */ +public class SignaturePlaceholderContext { + + private ThreadLocal sigHolder = new ThreadLocal(); + + private static SignaturePlaceholderContext instance = new SignaturePlaceholderContext(); + + /** + * Constructor. Private because this is a singleton. + */ + private SignaturePlaceholderContext() { + + } + + /** + * Get the {@link SignaturePlaceholderData} which is currently bound to this thread. + * Might be null. + * + * @return + */ + public static SignaturePlaceholderData getSignaturePlaceholderData(){ + return (SignaturePlaceholderData)instance.sigHolder.get(); + } + + /** + * + * @return true if there is currently a {@link SignaturePlaceholderData} bound to this thread, false otherwise. + */ + public static boolean isSignaturePlaceholderDataSet() { + return instance.sigHolder.get() != null; + } + + /** + * Bind a {@link SignaturePlaceholderData} to this thread. + * If the given data is null, the context will be cleared. + * + * @param data if null, clears the ThreadLocal, else binds the data to the current thread. + */ + public static void setSignaturePlaceholderData(SignaturePlaceholderData data) { + instance.sigHolder.set(data); + } +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/placeholder/SignaturePlaceholderData.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/placeholder/SignaturePlaceholderData.java new file mode 100644 index 0000000..ec42d75 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/placeholder/SignaturePlaceholderData.java @@ -0,0 +1,152 @@ +/** + * 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.placeholder; + +import at.knowcenter.wag.egov.egiz.pdf.TablePos; + +/** + * This class represents all the data which can be extracted from a placeholder image. + * + * @author exthex + * + */ +public class SignaturePlaceholderData { + + public static final String ID_KEY = "id"; + + public static final String PROFILE_KEY = "profile"; + + public static final String TYPE_KEY = "type"; + + public static final String SIG_KEY_KEY = "key"; + + private String profile; + + private String type; + + private String key; + + private String id; + + private TablePos tablePos; + + private String placeholderName; + + /** + * + * @param profile + * @param type + * @param sigKey + * @param id + */ + public SignaturePlaceholderData(String profile, String type, String sigKey, String id) { + this.profile = profile; + this.type = type; + this.key = sigKey; + this.id = id; + } + + /** + * Get the table position for the signature block.
+ * The table position is created from the page number, the upper left corner and the width of the placeholder image. + * + * @return + */ + public TablePos getTablePos() { + return tablePos; + } + + void setTablePos(TablePos tablePos) { + this.tablePos = tablePos; + } + + /** + * The profile name. Might be null if not included in the qr-code. + * + * @return + */ + public String getProfile() { + return profile; + } + + void setProfile(String profile) { + this.profile = profile; + } + + /** + * The signature type: "textual" or "binary". Might be null if not included in the qr-code. + * @return + */ + public String getType() { + return type; + } + + void setType(String type) { + this.type = type; + } + + /** + * The key identifier for MOA signature. Might be null if not included in the qr-code. + * + * @return + */ + public String getKey() { + return key; + } + + void setKey(String key) { + this.key = key; + } + + public String toString() { + return getClass().toString() + ": profile=" + profile + "; type=" + type + "; sigKey=" + key + "; table pos=" + tablePos; + } + + void setPlaceholderName(String name) { + this.placeholderName = name; + } + + /** + * The name of the placeholder image. + * + * @return + */ + public String getPlaceholderName() { + return placeholderName; + } + + /** + * The id associated with this placeholder. + * + * @return + */ + public String getId() { + return id; + } + + void setId(String id) { + this.id = id; + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/placeholder/SignaturePlaceholderExtractor.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/placeholder/SignaturePlaceholderExtractor.java new file mode 100644 index 0000000..8abe516 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/placeholder/SignaturePlaceholderExtractor.java @@ -0,0 +1,350 @@ +/** + * 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.placeholder; + +import java.awt.geom.AffineTransform; +import java.awt.geom.NoninvertibleTransformException; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.InputStream; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Vector; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.pdfbox.cos.COSName; +import org.apache.pdfbox.exceptions.WrappedIOException; +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.pdmodel.PDPage; +import org.apache.pdfbox.pdmodel.graphics.xobject.PDXObject; +import org.apache.pdfbox.pdmodel.graphics.xobject.PDXObjectImage; +import org.apache.pdfbox.util.Matrix; +import org.apache.pdfbox.util.PDFOperator; +import org.apache.pdfbox.util.PDFStreamEngine; +import org.apache.pdfbox.util.ResourceLoader; + +import at.gv.egiz.pdfas.api.commons.Constants; +import at.gv.egiz.pdfas.exceptions.ErrorCode; +import at.gv.egiz.pdfas.exceptions.framework.PlaceholderExtractionException; +import at.gv.egiz.pdfas.utils.PDFASUtils; +import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException; +import at.knowcenter.wag.egov.egiz.pdf.TablePos; + +import com.google.zxing.BarcodeFormat; +import com.google.zxing.BinaryBitmap; +import com.google.zxing.DecodeHintType; +import com.google.zxing.LuminanceSource; +import com.google.zxing.MultiFormatReader; +import com.google.zxing.NotFoundException; +import com.google.zxing.ReaderException; +import com.google.zxing.Result; +import com.google.zxing.client.j2se.BufferedImageLuminanceSource; +import com.google.zxing.common.HybridBinarizer; + +////// + + + +/** + * Extract all relevant information from a placeholder image. + * + * @author exthex + * + */ +public class SignaturePlaceholderExtractor extends PDFStreamEngine { + /** + * The log. + */ + private static Log log = LogFactory.getLog(SignaturePlaceholderExtractor.class); + + private List placeholders = new Vector(); + private int currentPage = 0; + + private SignaturePlaceholderExtractor(String placeholderId, int placeholderMatchMode) throws IOException { + super(ResourceLoader.loadProperties("at/gv/egiz/pdfas/placeholder/pdfbox-reader.properties", + true)); + } + + /** + * Search the document for placeholder images and possibly included + * additional info.
+ * Searches only for the first placeholder page after page from top. + * + * @param inputStream + * @return all available info from the first found placeholder. + * @throws PDFDocumentException if the document could not be read. + * @throws PlaceholderExtractionException if STRICT matching mode was requested and no suitable placeholder could be found. + */ + public static SignaturePlaceholderData extract(InputStream inputStream, String placeholderId, int matchMode) + throws PDFDocumentException, PlaceholderExtractionException { + SignaturePlaceholderContext.setSignaturePlaceholderData(null); + PDDocument doc = null; + try + { + try { + doc = PDDocument.load(inputStream); + } catch (IOException e) { + throw new PDFDocumentException(ErrorCode.DOCUMENT_CANNOT_BE_READ, e); + } + PDFASUtils.checkDocumentPermissions(doc); + SignaturePlaceholderExtractor extractor; + try + { + extractor = new SignaturePlaceholderExtractor(placeholderId, matchMode); + } catch (IOException e2) { + throw new PDFDocumentException(ErrorCode.DOCUMENT_CANNOT_BE_READ, e2); + } + List pages = doc.getDocumentCatalog().getAllPages(); + Iterator iter = pages.iterator(); + int pageNr = 0; + while (iter.hasNext()) { + pageNr++; + PDPage page = (PDPage) iter.next(); + try { + extractor.setCurrentPage(pageNr); + extractor.processStream( page, page.findResources(), page.getContents().getStream() ); + SignaturePlaceholderData ret = matchPlaceholderPage(extractor.placeholders, placeholderId, matchMode); + if (ret != null){ + SignaturePlaceholderContext.setSignaturePlaceholderData(ret); + return ret; + } + } catch (IOException e1) { + throw new PDFDocumentException(ErrorCode.DOCUMENT_CANNOT_BE_READ, e1); + } + + } + if (extractor.placeholders.size() > 0){ + SignaturePlaceholderData ret = matchPlaceholderDocument(extractor.placeholders, placeholderId, matchMode); + SignaturePlaceholderContext.setSignaturePlaceholderData(ret); + return ret; + } + // no placeholders found, apply strict mode if set + if (matchMode == Constants.PLACEHOLDER_MATCH_MODE_STRICT) { + throw new PlaceholderExtractionException(ErrorCode.SIGNATURE_PLACEHOLDER_EXTRACTION_FAILED, "no suitable placeholder found and STRICT matching mode requested."); + } + + return null; + } finally { + if (doc != null) + try { + doc.close(); + } catch (IOException e) { + log.debug("Could not close document.", e); + } + } + + } + + private static SignaturePlaceholderData matchPlaceholderDocument( + List placeholders, String placeholderId, int matchMode) throws PlaceholderExtractionException { + + if (matchMode == Constants.PLACEHOLDER_MATCH_MODE_STRICT) + throw new PlaceholderExtractionException(ErrorCode.SIGNATURE_PLACEHOLDER_EXTRACTION_FAILED, "no suitable placeholder found and STRICT matching mode requested."); + + if (placeholders.size() == 0) + return null; + + for (int i = 0; i < placeholders.size(); i++) + { + SignaturePlaceholderData spd = (SignaturePlaceholderData)placeholders.get(i); + if (spd.getId() == null) + return spd; + } + + if (matchMode == Constants.PLACEHOLDER_MATCH_MODE_LENIENT) + return (SignaturePlaceholderData)placeholders.get(0); + + return null; + } + + private static SignaturePlaceholderData matchPlaceholderPage(List placeholders, + String placeholderId, int matchMode) { + if (placeholders.size() == 0) + return null; + for (int i = 0; i < placeholders.size(); i++) + { + SignaturePlaceholderData data = (SignaturePlaceholderData)placeholders.get(i); + if (placeholderId != null && placeholderId.equals(data.getId())) + return data; + if (placeholderId == null && data.getId() == null) + return data; + } + return null; + } + + private void setCurrentPage(int pageNr) { + this.currentPage = pageNr; + } + + protected void processOperator( PDFOperator operator, List arguments ) throws IOException + { + String operation = operator.getOperation(); + if( operation.equals( "Do" ) ) + { + COSName objectName = (COSName)arguments.get( 0 ); + Map xobjects = getResources().getXObjects(); + PDXObject xobject = (PDXObject)xobjects.get( objectName.getName() ); + if( xobject instanceof PDXObjectImage ) + { + try + { + PDXObjectImage image = (PDXObjectImage)xobject; + SignaturePlaceholderData data = checkImage(image); + if (data != null) + { + PDPage page = getCurrentPage(); + Matrix ctm = getGraphicsState().getCurrentTransformationMatrix(); + double rotationInRadians = (page.findRotation() * Math.PI)/180; + + AffineTransform rotation = new AffineTransform(); + rotation.setToRotation( rotationInRadians ); + AffineTransform rotationInverse = rotation.createInverse(); + Matrix rotationInverseMatrix = new Matrix(); + rotationInverseMatrix.setFromAffineTransform( rotationInverse ); + Matrix rotationMatrix = new Matrix(); + rotationMatrix.setFromAffineTransform( rotation ); + + Matrix unrotatedCTM = ctm.multiply( rotationInverseMatrix ); + + float x = unrotatedCTM.getXPosition(); + float y = unrotatedCTM.getYPosition() + unrotatedCTM.getYScale(); + float w = unrotatedCTM.getXScale(); + + String posString = "p:" + currentPage + ";x:" + x + ";y:" + y + ";w:" + w; + try + { + data.setTablePos(new TablePos(posString)); + data.setPlaceholderName(objectName.getName()); + placeholders.add(data); + } catch (PDFDocumentException e) { + throw new WrappedIOException(e); + } + } + } + catch( NoninvertibleTransformException e ) + { + throw new WrappedIOException( e ); + } + } + } + else + { + super.processOperator( operator, arguments ); + } + } + + /** + * Checks an image if it is a placeholder for a signature. + * + * @param image + * @return + * @throws IOException + */ + private SignaturePlaceholderData checkImage(PDXObjectImage image) throws IOException { + BufferedImage bimg = image.getRGBImage(); + if (bimg == null) { + String type = image.getSuffix(); + if (type != null) { + type = type.toUpperCase() + " images"; + } else { + type = "Image type"; + } + log.info("Unable to extract image for QRCode analysis. " + type + " not supported. Add additional JAI Image filters to your classpath. Refer to https://jai.dev.java.net. Skipping image."); + return null; + } + if(bimg.getHeight() < 10 || bimg.getWidth() < 10) { + log.debug("Image too small for QRCode. Skipping image."); + return null; + } + + LuminanceSource source = new BufferedImageLuminanceSource(bimg); + BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); + Result result; + long before = System.currentTimeMillis(); + try { + Hashtable hints = new Hashtable(); + Vector formats = new Vector(); + formats.add(BarcodeFormat.QR_CODE); + hints.put(DecodeHintType.POSSIBLE_FORMATS, formats); + result = new MultiFormatReader().decode(bitmap, hints); + + String text = result.getText(); + String profile = null; + String type = null; + String sigKey = null; + String id = null; + if (text != null) { + if (text.startsWith(Constants.QR_PLACEHOLDER_IDENTIFIER)) { + String[] data = text.split(";"); + if (data.length > 1) { + for (int i = 1; i < data.length; i++) { + String kvPair = data[i]; + String[] kv = kvPair.split("="); + if (kv.length != 2) { + log.debug("Invalid parameter in placeholder data: " + kvPair); + } else { + if (kv[0].equalsIgnoreCase(SignaturePlaceholderData.ID_KEY)) { + id = kv[1]; + } else if (kv[0].equalsIgnoreCase(SignaturePlaceholderData.PROFILE_KEY)) { + profile = kv[1]; + } else if (kv[0] + .equalsIgnoreCase(SignaturePlaceholderData.SIG_KEY_KEY)) { + sigKey = kv[1]; + } else if (kv[0] + .equalsIgnoreCase(SignaturePlaceholderData.TYPE_KEY)) { + type = kv[1]; + } + } + } + } + return new SignaturePlaceholderData(profile, type, sigKey, id); + } else { + log.warn("QR-Code found but does not start with \"" + Constants.QR_PLACEHOLDER_IDENTIFIER + "\". Ignoring QR placeholder."); + } + } + } catch (ReaderException re) { + re.printStackTrace(); + if (log.isDebugEnabled()) { + log.debug("Could not decode - not a placeholder. needed: " + + (System.currentTimeMillis() - before)); + } + if (!(re instanceof NotFoundException)){ + if (log.isInfoEnabled()) { + log.info("Failed to decode image", re); + } + } + } catch(ArrayIndexOutOfBoundsException e){ + if (log.isInfoEnabled()) { + log.info("Failed to decode image. Probably a zxing bug", e); + } + } + return null; + } + +} + + diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/test/JarExtractTest.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/test/JarExtractTest.java new file mode 100644 index 0000000..d804b64 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/test/JarExtractTest.java @@ -0,0 +1,51 @@ +/** + * 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.test; + +import at.gv.egiz.pdfas.api.commons.Constants; +import at.gv.egiz.pdfas.utils.ConfigUtils; + +public final class JarExtractTest { + + private JarExtractTest() { + } + + public static void main(String[] args) { + try { + + String sysProp = System.getProperty(Constants.CONFIG_DIR_SYSTEM_PROPERTY); + System.out.println("System property \"" + Constants.CONFIG_DIR_SYSTEM_PROPERTY + "\" = " + (sysProp != null ? ("\"" + sysProp + "\"") : null)); + + String deployedTo = ConfigUtils.deployDefaultConfiguration(); + if (deployedTo != null) { + System.out.println("Configuration successfully deployed to \"" + deployedTo + "\"."); + } else { + System.out.println("Configuration was NOT deployed. Maybe a configuration already exists."); + } + + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/ConfigUtils.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/ConfigUtils.java new file mode 100644 index 0000000..bbc64b1 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/ConfigUtils.java @@ -0,0 +1,318 @@ +/** + * 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.utils; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.SystemUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.log4j.PropertyConfigurator; + +import at.gv.egiz.pdfas.api.commons.Constants; +import at.gv.egiz.pdfas.api.exceptions.ConfigUtilsException; +import at.knowcenter.wag.egov.egiz.cfg.SettingsReader; +import at.knowcenter.wag.egov.egiz.pdf.Utils; + +/** + * @author Thomas Knall + */ +public final class ConfigUtils { + + private ConfigUtils() { + } + + /** + * The log. + */ + private static final Log logger_ = LogFactory.getLog(ConfigUtils.class); + + /** + * Deploys the default configuration with apache commons vfs. + * + * @param destination The destination folder. + * @param overwriteExisting If set true an already existing configuration is overwritten. If false nothing is being copied if the destination folder already exists. + * @return true if the configuration has been deployed, false if not. + * @throws ConfigUtilsException Thrown if there was an error during the deployment of the configuration. + */ + /* + private static boolean deployWithCommonsVFS(String destination, boolean overwriteExisting) throws ConfigUtilsException { + try { + FileSystemManager fsManager = VFS.getManager(); + FileObject defaultConfigurationFile = fsManager.resolveFile("res:DefaultConfiguration"); + FileObject destinationFile = fsManager.resolveFile(destination); + + if (destinationFile.exists() && !overwriteExisting) { + return false; + } + + destinationFile.copyFrom(defaultConfigurationFile, new AllFileSelector()); + return true; + } catch (FileSystemException e) { + throw new ConfigUtilsException(e); + } + } + */ + + + /** + * Deploys the default configuration from an included zip file. + * + * @param destination The destination folder. + * @param overwriteExisting If set true an already existing configuration is overwritten. If false nothing is being copied if the destination folder already exists. + * @return true if the configuration has been deployed, false if not. + * @throws ConfigUtilsException Thrown if there was an error during the deployment of the configuration. + */ + private static boolean deployFromZIP(String destination, boolean overwriteExisting) throws ConfigUtilsException { + try { + if (!overwriteExisting) { + if (configurationAlreadyExists(destination)) { + logger_.debug("There is at least one file or folder that would be overwritten at destination path \"" + destination + "\". Skipping extraction."); + return false; + } + } + InputStream in = ConfigUtils.class.getClassLoader().getResourceAsStream(Constants.DEFAULT_CONFIGURATION_ZIP_RESOURCE); + if (in == null) { + throw new ConfigUtilsException("Unable to find default configuration resource \"" + Constants.DEFAULT_CONFIGURATION_ZIP_RESOURCE + "\"."); + } + return deployFromZIP(in, destination, overwriteExisting); + } catch (IOException e) { + throw new ConfigUtilsException(e); + } + } + + /** + * Deploys the contents of a ZIP file to a certain location. + * + * @param inputStream The inputStream of a ZIP container. + * @param destination The destination folder. + * @param overwriteExisting If set true an already existing configuration is overwritten. If false nothing is being copied if the destination folder already exists. + * @return true if the configuration has been deployed, false if not. + * @throws ConfigUtilsException Thrown if there was an error during the deployment of the configuration. + */ + public static boolean deployFromZIP(InputStream inputStream, String destination, boolean overwriteExisting) throws ConfigUtilsException { + try { + if (!overwriteExisting) { + if (configurationAlreadyExists(destination)) { + logger_.debug("There is at least one file or folder that would be overwritten at destination path \"" + destination + "\". Skipping extraction."); + return false; + } + } + if (inputStream == null) { + throw new ConfigUtilsException("Unable to deploy ZIP file. InputStream is null."); + } + ZipInputStream zis = new ZipInputStream(inputStream); + ZipEntry ze; + File destinationFolder = new File(destination); + destinationFolder.mkdirs(); + logger_.debug("Extracting ZIP contents to folder \"" + destinationFolder.getCanonicalPath() + "\"."); + while ((ze = zis.getNextEntry()) != null) { + if (ze.isDirectory()) { + File newFolder = new File(destinationFolder, ze.getName()); + logger_.debug("Extracting folder \"" + newFolder.getPath() + "\"."); + newFolder.mkdirs(); + } else { + File destFile = new File(destinationFolder, ze.getName()); + logger_.trace("Extracting file \"" + destFile.getName() + "\"."); + PDFASUtils.toFile(zis, destFile); + } + zis.closeEntry(); + } + zis.close(); + return true; + } catch (IOException e) { + throw new ConfigUtilsException(e); + } + } + + private static boolean configurationAlreadyExists(String destination) throws ConfigUtilsException, IOException { + logger_.debug("Checking configuration \"" + destination + "\" already exists (resp. if there are any directories or files that would be overwritten)."); + File destinationFolder = new File(destination); + if (destinationFolder == null || !destinationFolder.exists()) { + return false; + } + InputStream in = ConfigUtils.class.getClassLoader().getResourceAsStream(Constants.DEFAULT_CONFIGURATION_ZIP_RESOURCE); + if (in == null) { + throw new ConfigUtilsException("Unable to find default configuration resource \"" + Constants.DEFAULT_CONFIGURATION_ZIP_RESOURCE + "\"."); + } + ZipInputStream zis = new ZipInputStream(in); + ZipEntry ze; + while ((ze = zis.getNextEntry()) != null) { + if (ze.isDirectory()) { + File newFolder = new File(destinationFolder, ze.getName()); + logger_.debug("Checking if folder \"" + newFolder.getPath() + "\" already exists."); + if (newFolder.exists()) { + logger_.debug("YES !"); + return true; + } else { + logger_.debug("no"); + } + } else { + File destFile = new File(destinationFolder, ze.getName()); + logger_.trace("Checking if file \"" + destFile.getName() + "\" already exists."); + if (destFile.exists()) { + logger_.trace("YES !"); + return true; + } else { + logger_.trace("no"); + } + } + zis.closeEntry(); + } + zis.close(); + return false; + } + + /** + * Deploys the default configuration to the given destination folder. + * + * @param destination The destination folder. + * @param overwriteExisting If set true an already existing configuration is overwritten. If false nothing is being copied if the destination folder already exists. + * @return The folder the configuration has been extracted to or null if the configuration has NOT been deployed. + * @throws ConfigUtilsException Thrown if there was an error during the deployment of the configuration. + */ + public static String deployDefaultConfiguration(String destination, boolean overwriteExisting) throws ConfigUtilsException { + if (destination == null) { + throw new NullPointerException("Destination must not be null."); + } + if (destination.length() == 0) { + throw new IllegalArgumentException("Destination must not be empty."); + } + return deployFromZIP(destination, overwriteExisting) ? destination : null; + } + + /** + * Deploys the default configuration to the user's home directory to the subdirectory specified by + * Constants.Constants.USERHOME_CONFIG_FOLDER. + * + * @param overwriteExisting If set true an already existing configuration is overwritten. If false nothing is being copied if the destination folder already exists. + * @return The folder the configuration has been extracted to or null if the configuration has NOT been deployed. + * @throws ConfigUtilsException Thrown if there was an error during the deployment of the configuration. + * @see Constants#USERHOME_CONFIG_FOLDER + */ + public static String deployDefaultConfiguration(boolean overwriteExisting) throws ConfigUtilsException { + String configdir = System.getProperty(Constants.CONFIG_DIR_SYSTEM_PROPERTY); + if (configdir == null) { + configdir = System.getProperty("user.home"); + if (configdir != null) { + configdir = configdir + File.separator + Constants.USERHOME_CONFIG_FOLDER; + } + } + if (configdir == null || configdir.length() == 0) { + return null; + } + return deployDefaultConfiguration(configdir, overwriteExisting); + } + + /** + * Deploys the default configuration to the user's home directory to the subdirectory specified by + * Constants.Constants.USERHOME_CONFIG_FOLDER. + * + * @return The folder the configuration has been extracted to or null if the configuration has NOT been deployed. + * @throws ConfigUtilsException Thrown if there was an error during the deployment of the configuration. + * @see Constants#USERHOME_CONFIG_FOLDER + */ + public static String deployDefaultConfiguration() throws ConfigUtilsException { + return deployDefaultConfiguration(false); + } + + public static void writeInputStreamToOutputStream(InputStream inputStream, OutputStream outputStream) throws IOException { + final int bufferSize = 1024; + byte[] buffer = new byte[bufferSize]; + int len = -1; + while ((len = inputStream.read(buffer)) != -1) { + outputStream.write(buffer, 0, len); + } + outputStream.flush(); + } + + public static String assertFileSeparator(String path) { + if (path == null) { + throw new NullPointerException("Path must not be null."); + } + if (path.endsWith(File.separator) || path.endsWith("/") || path.endsWith("\\")) { + return path; + } else { + return (path + File.separator); + } + } + + public static void initializeLogger() { + String loggerConfiguration = System.getProperty("log4j.configuration"); + if (loggerConfiguration != null) { + logger_.info("No PDF-AS logger configured because a configuration has already been set via system property \"log4j.configuration\" (=\"" + loggerConfiguration + "\")."); + return; + } + loggerConfiguration = assertFileSeparator(SettingsReader.CONFIG_PATH) + "log4j.properties"; + File loggerConfigFile = new File(loggerConfiguration); + if (!loggerConfigFile.exists()) { + logger_.info("No PDF-AS logger configured because there is no log4j.properties within the pdf-as work dir. Maybe the logger configuration is handled by an outside application (e.g. a web application)."); + return; + } + logger_.info("Initializing PDF-AS logger (configuration = \"" + loggerConfiguration + "\")."); + PropertyConfigurator.configure(loggerConfiguration); + } + + public static void printConfigInfo(Log logger) { + int length = Utils.max(new int[] { SettingsReader.RESOURCES_PATH.length(), SettingsReader.TMP_PATH.length(), SettingsReader.CONFIG_PATH.length(), SettingsReader.CERT_PATH.length() }); + + String separator = StringUtils.repeat("*", length + 25); + String infoResources = " resources path = \"" + SettingsReader.RESOURCES_PATH + "\""; + String infoConfiguration = " configuration path = \"" + SettingsReader.CONFIG_PATH + "\""; + String infoCertStore = " certstore path = \"" + SettingsReader.CERT_PATH + "\""; + String infoTempPath = " temporary path = \"" + SettingsReader.TMP_PATH + "\""; + String encoding = " file.encoding = \"" + System.getProperty("file.encoding") + "\""; + + if (logger != null) { + logger.info(separator); + logger.info(infoResources); + logger.info(infoConfiguration); + logger.info(infoCertStore); + logger.info(infoTempPath); + logger.info(encoding); + logger.info(separator); + } else { + StringBuffer buffer = new StringBuffer(); + buffer.append(separator).append(SystemUtils.LINE_SEPARATOR); + buffer.append(infoResources).append(SystemUtils.LINE_SEPARATOR); + buffer.append(infoConfiguration).append(SystemUtils.LINE_SEPARATOR); + buffer.append(infoCertStore).append(SystemUtils.LINE_SEPARATOR); + buffer.append(infoTempPath).append(SystemUtils.LINE_SEPARATOR); + buffer.append(encoding).append(SystemUtils.LINE_SEPARATOR); + buffer.append(separator); + System.out.println(buffer.toString()); + } + } + + public static void printConfigInfo() { + printConfigInfo(null); + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/DataHashUtils.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/DataHashUtils.java new file mode 100644 index 0000000..4b26ada --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/DataHashUtils.java @@ -0,0 +1,156 @@ +/** + * 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.utils; + +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.security.DigestInputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +import org.apache.commons.codec.binary.Base64; + +import at.knowcenter.wag.egov.egiz.pdf.BinarySignatureHolder; +import at.knowcenter.wag.egov.egiz.pdf.SignatureHolder; +import at.knowcenter.wag.egov.egiz.pdf.TextualSignatureHolder; + +/** + * Contains helpful methods for building data hashed. + * + *

+ * Data hashes are useful for summarizing the signed data of signatures for + * debugging and testing purposes. Do not use these hashes for signatures. + *

+ *

+ * A data hash is always a Base64 encoded String. + *

+ * + * @author wprinz + * + */ +public final class DataHashUtils +{ + + /** + * + * @param text + * @return + */ + public static String buildDataHash(String text) + { + try + { + MessageDigest md = getMessageDigest(); + // probable performance leak for very large texts + md.update(text.getBytes("UTF-8")); + byte[] rawDigest = md.digest(); + + return encodeDigest(rawDigest); + } + catch (UnsupportedEncodingException e) + { + throw new RuntimeException(e); + } + } + + public static String buildDataHash(byte[] data) + { + MessageDigest md = getMessageDigest(); + md.update(data); + byte[] rawDigest = md.digest(); + + return encodeDigest(rawDigest); + } + + public static String buildDataHash(InputStream is) + { + try + { + MessageDigest md = getMessageDigest(); + + DigestInputStream dis = new DigestInputStream(is, md); + + byte[] temp = new byte[1024]; + int i = 0; + while (dis.read(temp) >= 0) + { + // this just keeps the compiler from optimizing this loop away + i++; + } + dis.close(); + + byte[] rawDigest = md.digest(); + + return encodeDigest(rawDigest); + } + catch (IOException e) + { + throw new RuntimeException(e); + } + } + + public static String buildDataHash(SignatureHolder sh) + { + if (sh instanceof TextualSignatureHolder) + { + TextualSignatureHolder tsh = (TextualSignatureHolder) sh; + String signedText = tsh.getSignedText(); + return buildDataHash(signedText); + } + + { + BinarySignatureHolder bsh = (BinarySignatureHolder) sh; + InputStream is = bsh.getSignedPdf().createInputStream(); + return buildDataHash(is); + } + } + + protected static MessageDigest getMessageDigest() + { + try + { + MessageDigest sha1 = MessageDigest.getInstance("SHA-1"); + return sha1; + } + catch (NoSuchAlgorithmException e) + { + throw new RuntimeException(e); + } + } + + protected static String encodeDigest(byte[] rawDigest) + { + try + { + byte[] encoded = Base64.encodeBase64(rawDigest); + String str = new String(encoded, "US-ASCII"); + return str; + } + catch (UnsupportedEncodingException e) + { + throw new RuntimeException(e); + } + } +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/OgnlUtil.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/OgnlUtil.java new file mode 100644 index 0000000..69b30f8 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/OgnlUtil.java @@ -0,0 +1,209 @@ +/** + * 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.utils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import ognl.Ognl; +import ognl.OgnlException; + +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; + +/** + * Utility class for ognl evaluation. + * ognl website + * @author dferbas + * @author mhiess + * + */ +public class OgnlUtil { + + private static final String EXP_END = "}"; + + private static final String EXP_START = "${"; + + private static final Logger log = Logger.getLogger(OgnlUtil.class); + + private Map context = new HashMap(); + private Object root = null; + + public OgnlUtil() { + this.init(null); + } + + public OgnlUtil(Map context) { + this.init(context); + } + + public OgnlUtil(Object root) { + this.root = root; + this.init(null); + } + + /** + * Adds the default utils to the context + * + * @param context1 + */ + private void init(Map context1) { + if (context1 != null) { + this.context = context1; + } + } + + private List extractExpressions(String text) { + + List expressions = new ArrayList(); + + int indexStart = 0; + int indexEnd = 0; + String exp; + + while (indexStart != -1) { + indexStart = text.indexOf(EXP_START, indexStart); + indexEnd = text.indexOf(EXP_END, indexStart); + + if (indexStart != -1 && indexEnd != -1) { + + exp = text.substring(indexStart + 2, indexEnd); + log.debug("Found expression in template: " + exp); + if (!exp.equals("") && exp != null) { + if (!expressions.contains(exp)) { + expressions.add(exp); + } else { + log.debug("Duplicated expression '" + exp + "' found"); + } + } + + indexStart = indexEnd; + } + } + + return expressions; + } + + public boolean containsExpression(String template) { + return template != null && StringUtils.contains(template,"${") && StringUtils.contains(template, "}"); + } + + /** + * Compile/evaluate a message with ognl expressions marked with ${expression} + * + * @param template + * @return + */ + public String compileMessage(String template) { + + if (this.context != null) { + String compiledMsg = template; + List expressions = this.extractExpressions(template); + + String value; + for (Iterator it = expressions.iterator(); it.hasNext();) { + String expr = (String) it.next(); + + try { + if (this.root != null) { + value = String.valueOf(Ognl.getValue(expr, this.root)); + } else { + value = String.valueOf(Ognl.getValue(expr, this.context)); + } + log.debug("Found value: '" + value + "' for expression: '" + expr + "'"); + + if (value == null) { + value = ""; + log.debug("Set value for expression to: empty string"); + } + + compiledMsg = StringUtils.replace(compiledMsg, EXP_START + expr + EXP_END, value); + } catch (OgnlException e) { + log.error(e.getMessage(), e); + } + } + log.debug("Returning compiled message: " + compiledMsg); + return compiledMsg; + } + return null; + } + + /** + * Evaluate an expression as ognl, returning result as object. No placeholders ${ } allowed. + * @param ognlExp + * @return + */ + public Object evaluate(String ognlExp) { + + if (this.context != null) { + + Object value = null; + try { + value = Ognl.getValue(ognlExp, this.context); + log.debug("Found value: '" + value + "' for expression: '" + ognlExp + "'"); + + } catch (OgnlException e) { + log.error(e.getMessage(), e); + } + return value; + } else return null; + } + + /** + * This method compiles a map of ognl expression to a map with entries + * + * @param toCompile + * @return + */ + public Map compileExpressions(Map toCompile) { + if (this.context != null) { + Map result = new HashMap(); + + for (Iterator it = result.entrySet().iterator(); it.hasNext();) { + Entry entry = (Entry) it.next(); + try { + result.put(entry.getKey(), Ognl.getValue(entry.getValue(), this.context)); + } catch (OgnlException e) { + result.put(entry.getKey(), null); + log.warn(e.getMessage(), e); + } + } + return result; + + } + return null; + } + + public Map getContext() { + return this.context; + } + + public void mergeOgnlContext(OgnlUtil ognlUtil) { + this.context.putAll(ognlUtil.getContext()); + } +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/PDFASUtils.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/PDFASUtils.java new file mode 100644 index 0000000..4cd3bd5 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/PDFASUtils.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.utils; + +import java.io.BufferedOutputStream; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.pdfbox.pdmodel.PDDocument; + +import at.gv.egiz.pdfas.exceptions.ErrorCode; +import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException; + +import com.lowagie.text.pdf.PdfReader; + +/** + * @author tknall + */ +public class PDFASUtils { +//23.11.2010 changed by exthex - added checkDocumentPermissions(PDDocument doc) + + private PDFASUtils() { + } + + /** + * Verifies that a document could be opened with full permissions. + * @param pdfReader The PdfReader + * @throws PDFDocumentException Thrown if document has not been opened with full permissions. + */ + public static void checkReaderPermissions(PdfReader pdfReader) throws PDFDocumentException { + if (pdfReader.isEncrypted()) { + throw new PDFDocumentException(ErrorCode.DOCUMENT_IS_PROTECTED, "Document is encrypted."); + } + if (!pdfReader.isOpenedWithFullPermissions()) { + throw new PDFDocumentException(ErrorCode.DOCUMENT_IS_PROTECTED, "Document is protected."); + } + } + + public static boolean toFile(byte[] data, File file) throws IOException { + return PDFASUtils.toFile(new ByteArrayInputStream(data), file); + } + + public static boolean toFile(InputStream inputStream, File file) throws IOException { + boolean result = false; + BufferedOutputStream bufferedOutputStream = null; + try { + bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(file)); + ConfigUtils.writeInputStreamToOutputStream(inputStream, bufferedOutputStream); + } finally { + if (bufferedOutputStream != null) { + try { + bufferedOutputStream.close(); + result = true; + } catch (IOException e) { + result = false; + } + } + } + return result; + } + + public static void checkDocumentPermissions(PDDocument doc) throws PDFDocumentException { + if (doc.isEncrypted()) { + throw new PDFDocumentException(ErrorCode.DOCUMENT_IS_PROTECTED, "Document is encrypted."); + } + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/PdfAUtil.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/PdfAUtil.java new file mode 100644 index 0000000..e741bca --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/PdfAUtil.java @@ -0,0 +1,66 @@ +/** + * 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.utils; + +/** + * PDF/A utility class + * @author dferbas + * + */ +public class PdfAUtil { + /** + * dferbas: Text representation of pdfa version string + */ + private static final String PDFA_PREFIX = "ISO 19005-1:2005 PDF/A-"; + /** + * Extract pdfa version from pdf metadata + * @param pdfMetadata + * @return + */ + public static String findPdfAVersion(String pdfMetadata) { + + String inf = pdfMetadata; + String pdfaNsMark = "http://www.aiim.org/pdfa/ns/id/"; + String partMark = ""; + String confMark = ""; + int pdfaI = inf.indexOf(pdfaNsMark); + + if (pdfaI > -1) { + int part = inf.indexOf(partMark); + StringBuffer version = new StringBuffer(PDFA_PREFIX); + part = part + partMark.length(); + version.append(inf.substring(part, part + 1)); + int conf = inf.indexOf(confMark); + + conf = conf + confMark.length(); + version.append(inf.substring(conf, conf + 1).toLowerCase()); + + return version.toString(); + } else { + return null; + + } + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/StreamUtils.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/StreamUtils.java new file mode 100644 index 0000000..3dce5b1 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/StreamUtils.java @@ -0,0 +1,66 @@ +/** + * 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.utils; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +public class StreamUtils +{ + + public static void writeInputStreamToOutputStream (InputStream is, OutputStream os) throws IOException + { + byte [] buffer = new byte [2048]; + + int read = -1; + while ((read = is.read(buffer)) > 0) + { + os.write(buffer, 0, read); + } + os.flush(); + is.close(); + os.close(); + } + + // The InputStream should be self- delimited. +// public static void writeInputStreamToOutputStream(InputStream is, OutputStream os, int length) throws IOException +// { +// byte [] buffer = new byte [2048]; +// +// int bytes_to_write = length; +// +// int read = -1; +// while ((read = is.read(buffer, 0, (bytes_to_write >= buffer.length) ? buffer.length : bytes_to_write)) > 0) +// { +// os.write(buffer, 0, read); +// bytes_to_write -= read; +// } +// is.close(); +// os.close(); +// +// assert bytes_to_write == 0; +// } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/TempDirHelper.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/TempDirHelper.java new file mode 100644 index 0000000..bccc67b --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/TempDirHelper.java @@ -0,0 +1,377 @@ +/** + * 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.utils; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStreamWriter; +import java.text.DecimalFormat; +import java.text.NumberFormat; +import java.util.Iterator; +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.pdfas.framework.input.DataSource; +import at.gv.egiz.pdfas.framework.input.PdfDataSource; +import at.gv.egiz.pdfas.framework.input.TextDataSource; +import at.gv.egiz.pdfas.framework.output.DataSink; +import at.gv.egiz.pdfas.impl.input.ByteArrayPdfDataSourceImpl; +import at.gv.egiz.pdfas.impl.input.FileBased; +import at.gv.egiz.pdfas.impl.input.FileBasedTextDataSourceImpl; +import at.gv.egiz.pdfas.impl.input.TextDataSourceImpl; +import at.gv.egiz.pdfas.impl.input.helper.DataSourceHelper; +import at.gv.egiz.pdfas.impl.output.ByteArrayDataSink; +import at.knowcenter.wag.egov.egiz.cfg.SettingsReader; +import at.knowcenter.wag.egov.egiz.pdf.SignatureHolder; +import at.knowcenter.wag.egov.egiz.pdf.TextualSignatureHolder; + +/** + * @author wprinz + * + */ +public class TempDirHelper +{ + /** + * The log. + */ + private static Log log = LogFactory.getLog(TempDirHelper.class); + + protected static long runningIndex = 0; + + /** + * Assembles the File of the temporary directory without checking if it really + * exists. + */ + public static File assembleTemporaryDirectoryFile() + { + File temp_dir = new File(SettingsReader.TMP_PATH); + return temp_dir; + } + + /** + * Returns the directory where temporary files should be stored. + * + *

+ * If the directory doesn't exist, it is created. + *

+ * + * @return Returns the directory where temporary files should be stored. + */ + public static File getTemporaryDirectory() + { + File temp_dir = assembleTemporaryDirectoryFile(); + if (!temp_dir.exists()) + { + temp_dir.mkdirs(); + } + return temp_dir; + } + + /** + * Deletes all files in the temporary directory, if it exists. + * + *

+ * This should be used to clear temporary files when the application shuts + * down. + *

+ */ + public static void clearTemporaryDirectory() + { + File temp_dir = assembleTemporaryDirectoryFile(); + log.debug("Clearing temporary directory: " + temp_dir); + + if (!temp_dir.exists()) + { + return; + } + + File[] files = temp_dir.listFiles(); + for (int i = 0; i < files.length; i++) + { + // added by tknall: do not try to remove svn-metadata + if (files[i].getName().endsWith(".svn")) { + continue; + } + log.debug(" Clearing temporary file: " + files[i]); + boolean delete_success = files[i].delete(); + if (!delete_success) + { + log.error("Couldn't delete the temporary file: " + files[i]); + } + } + } + + public static void storeTextSignatureHoldersIfApplicable(List shs, String fileNameSuffix) throws IOException + { + Iterator it = shs.iterator(); + while (it.hasNext()) + { + SignatureHolder sh = (SignatureHolder) it.next(); + if (sh instanceof TextualSignatureHolder) + { + TextualSignatureHolder tsh = (TextualSignatureHolder) sh; + if (!(tsh.getDataSource() instanceof FileBased)) + { + TextDataSource tds = (TextDataSource) tsh.getDataSource(); + if (isReasonableToStore(tds.getText().length())) + { + TextDataSource fbtds = placeTextIntoTempDir(tds.getText(), fileNameSuffix); + tsh.exchangeDataSource(fbtds); + } + } + } + } + } + + /** + * Places the text into the temp dir if reasonable. + * + *

+ * Reasonable means that the text is longer than a certain threshold. + * Otherwise a short text is simply held in memory. + *

+ * + * @param text + * The text to be stored. + * @param fileNameSuffix + * A file name suffix so that the temp file gets a more "readable" + * name. + * @return Returns the TextDataSource. + * @throws IOException + * F.e. + */ + public static TextDataSource placeTextIntoTempDir(String text, String fileNameSuffix) throws IOException + { + if (isReasonableToStore(text.length())) + { + String fileName = formatFileName(fileNameSuffix); + + File tmpFile = createTempFileInDir(fileName); + + FileOutputStream fos = new FileOutputStream(tmpFile); + OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8"); + osw.write(text); + osw.close(); + + FileBasedTextDataSourceImpl textDataSource = new FileBasedTextDataSourceImpl(tmpFile, "UTF-8"); + return textDataSource; + } + else + { + return new TextDataSourceImpl(text); + } + } + + /** + * Tells, if it is reasonable to store the text of the given length onto the + * disk. + * + * @param textLength + * The length of the text under question. + * @return Returns true if the text should be stored on the disk. + */ + public static boolean isReasonableToStore(int textLength) + { + return false; +// return textLength >= 10000; + } + + public static PdfDataSource placePdfIntoTempDir(InputStream pdfInput, String fileNameSuffix) throws IOException + { + log.debug("PERF: placing pdf into memory cache"); + + byte [] pdfData = DataSourceHelper.convertInputStreamToByteArray(pdfInput); + PdfDataSource pdfDataSource = new ByteArrayPdfDataSourceImpl(pdfData); + +// File pdfFile = placeInputIntoTempDirFile(pdfInput, fileNameSuffix); +// +// FileBasedPdfDataSourceImpl pdfDataSource = new FileBasedPdfDataSourceImpl(pdfFile, (int) pdfFile.length()); + return pdfDataSource; + } + + public static File placeInputIntoTempDirFile(InputStream input, String fileNameSuffix) throws IOException + { + String fileName = formatFileName(fileNameSuffix); + + File tmpFile = createTempFileInDir(fileName); + + FileOutputStream fos = new FileOutputStream(tmpFile); + + byte[] buffer = new byte[2048]; + int read = -1; + while ((read = input.read(buffer)) > 0) + { + fos.write(buffer, 0, read); + } + fos.close(); + input.close(); + + return tmpFile; + } + + public static File formTempFile(String fileNameSuffix) + { + String fileName = formatFileName(fileNameSuffix); + File tmpFile = getFileInTempDir(fileName); + + return tmpFile; + } + + protected static File getFileInTempDir (String fileName) + { +// File tempDir = new File(new File(SettingsReader.RESOURCES_PATH), "pdfastmp"); + File tempDir = assembleTemporaryDirectoryFile(); + + File tmpFile = new File(tempDir, fileName); + + return tmpFile; + } + + protected static String formatFileName(String fileNameSuffix) + { + // double check so that file name is always correct. + fileNameSuffix = extractFileNameSuffix(fileNameSuffix); + String fileName = "tmp" + formatIndex(runningIndex) + "_" + fileNameSuffix; + runningIndex++; + + return fileName; + } + + protected static String formatIndex(long index) + { + NumberFormat nf = new DecimalFormat("00000000"); + + return nf.format(index); + } + + protected static File createTempFileInDir(String fileName) throws IOException + { + File tmpFile = getFileInTempDir(fileName); + + tmpFile.createNewFile(); + + tmpFile.deleteOnExit(); + + return tmpFile; + } + + public static DataSink createTempDataSink(String fileNameSuffix) throws IOException + { + log.debug("PERF: placing pdf into memory cache"); + + DataSink ds = new ByteArrayDataSink(); + +// String fileName = formatFileName(fileNameSuffix); +// +// File tmpFile = createTempFileInDir(fileName); +// +// FileBasedDataSink ds = new FileBasedDataSink(tmpFile); + + return ds; + } + +// public static void writeDataSinkToHttpResponse(DataSink ds, HttpServletResponse response) throws IOException +// { +// +// response.setContentType(ds.getMimeType()); +// response.setCharacterEncoding(ds.getCharacterEncoding()); +// +// OutputStream os = response.getOutputStream(); +// +// if (ds instanceof FileBasedDataSink) +// { +// FileBasedDataSink fbds = (FileBasedDataSink)ds; +// byte[] buffer = new byte[2048]; +// FileInputStream fis = new FileInputStream(fbds.getFile()); +// int n = -1; +// while ((n = fis.read(buffer)) > 0) +// { +// os.write(buffer, 0, n); +// } +// fis.close(); +// } +// else +// { +// ByteArrayDataSink bads = (ByteArrayDataSink)ds; +// os.write(bads.getByteArray()); +// os.flush(); +// +// } +// +// os.close(); +//} + + /** + * Deletes the underlying file of the FileBased DataSource. + * + *

+ * If the DataSource is not FileBased, nothing is done. + *

+ *

+ * This is usually used by the application to delete temporary files. + *

+ * + * @param dataSource + */ + public static void deleteDataSourceIfFileBased(DataSource dataSource) + { + if (dataSource instanceof FileBased) + { + FileBased fb = (FileBased) dataSource; + log.debug("Deleting temp file " + fb.getFile()); + boolean deleted = fb.getFile().delete(); + log.debug("deleted = " + deleted); + } + } + + public static void deleteDataSinkIfFileBased(DataSink dataSink) + { + if (dataSink instanceof FileBased) + { + FileBased fb = (FileBased) dataSink; + log.debug("Deleting temp file " + fb.getFile()); + boolean deleted = fb.getFile().delete(); + log.debug("deleted = " + deleted); + } + } + + /** + * Given a file (maybe with path), extracts the file name suffix. + * @param file The file and maybe path. + * @return Returns the file name. + */ + public static String extractFileNameSuffix (String file) + { + if (file == null || file.trim().length() == 0) + { + return "nofilename"; + } + File f = new File(file); + return f.getName(); + } +} -- cgit v1.2.3