aboutsummaryrefslogtreecommitdiff
path: root/pdf-as-lib/src/main
diff options
context:
space:
mode:
authortknall <tknall@7b5415b0-85f9-ee4d-85bd-d5d0c3b42d1c>2013-01-09 15:41:29 +0000
committertknall <tknall@7b5415b0-85f9-ee4d-85bd-d5d0c3b42d1c>2013-01-09 15:41:29 +0000
commit535a04fa05f739ec16dd81666e3b0f82dfbd442d (patch)
tree0804f301c1a9ceb303a8441b7b29244fc8eb7ff0 /pdf-as-lib/src/main
parent1efaf6fd5619dfa95c9d7e8c71eda4c2ffba4998 (diff)
downloadpdf-as-3-535a04fa05f739ec16dd81666e3b0f82dfbd442d.tar.gz
pdf-as-3-535a04fa05f739ec16dd81666e3b0f82dfbd442d.tar.bz2
pdf-as-3-535a04fa05f739ec16dd81666e3b0f82dfbd442d.zip
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
Diffstat (limited to 'pdf-as-lib/src/main')
-rw-r--r--pdf-as-lib/src/main/assembly/assemble_distribution_brz.xml44
-rw-r--r--pdf-as-lib/src/main/assembly/assemble_distribution_cl.xml66
-rw-r--r--pdf-as-lib/src/main/assembly/assemble_distribution_ws.xml203
-rw-r--r--pdf-as-lib/src/main/assembly/assemble_libraries.xml16
-rw-r--r--pdf-as-lib/src/main/assembly/assemble_repository.xml19
-rw-r--r--pdf-as-lib/src/main/distribution/brz/pdf-as.bat8
-rw-r--r--pdf-as-lib/src/main/distribution/cl/pdf-as.bat8
-rw-r--r--pdf-as-lib/src/main/distribution/cl/pdf-as.sh8
-rw-r--r--pdf-as-lib/src/main/distribution/cl/sign.bat1
-rw-r--r--pdf-as-lib/src/main/distribution/cl/sign.sh3
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/PdfAsFactory.java124
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/algorithmSuite/AlgorithmMapper.java143
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/algorithmSuite/AlgorithmSuiteObject.java183
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/algorithmSuite/AlgorithmSuiteUtil.java230
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/PdfAs.java285
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/analyze/AnalyzeParameters.java107
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/analyze/AnalyzeResult.java63
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/analyze/NonTextObjectInfo.java99
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/Constants.java185
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/DynamicSignatureLifetimeEnum.java72
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/DynamicSignatureProfile.java125
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/DynamicSignatureProfileImpl.java215
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/SignatureInformation.java129
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/commons/SignatureProfile.java76
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/exceptions/ConfigUtilsException.java122
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/exceptions/PdfAsException.java98
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/internal/LocalBKUParams.java64
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/internal/PdfAsInternal.java163
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/internal/SignatureEntry.java137
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/io/DataSink.java98
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/io/DataSource.java94
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/io/FileBased.java51
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/io/TextBased.java50
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/SignParameters.java393
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/SignResult.java84
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/SignatureDetailInformation.java147
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/SignaturePosition.java72
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/SignaturePositioning.java296
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/axis/AbsoluteAxisAlgorithm.java62
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/axis/AutoAxisAlgorithm.java41
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/axis/AxisAlgorithm.java41
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/AbsolutePageAlgorithm.java64
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/AutoPageAlgorithm.java47
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/NewPageAlgorithm.java41
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/sign/pos/page/PageAlgorithm.java41
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/timestamp/DummyTimeStamper.java62
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/timestamp/TimeStamper.java41
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/verify/SignatureCheck.java51
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyAfterAnalysisParameters.java166
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyAfterReconstructXMLDsigParameters.java169
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyParameters.java249
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyResult.java179
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/verify/VerifyResults.java48
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/xmldsig/ExtendedSignatureInformation.java69
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/xmldsig/ReconstructXMLDsigAfterAnalysisParameters.java86
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/xmldsig/ReconstructXMLDsigParameters.java218
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/xmldsig/ReconstructXMLDsigResult.java74
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/api/xmldsig/XMLDsigData.java83
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/commandline/CommandlineConnectorChooser.java199
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/commandline/Main.java1275
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/ErrorCode.java101
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/ErrorCodeHelper.java119
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/external/ExternalErrorException.java66
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/framework/CorrectorException.java56
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/framework/PlaceholderExtractionException.java79
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/framework/SignatorException.java60
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/framework/VerificationFilterException.java60
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/framework/VerificatorFactoryException.java69
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/pdf/CaptionNotFoundException.java75
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/pdf/KZSettingNotFoundException.java47
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/exceptions/web/SessionExpiredException.java68
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/ConnectorFactory.java107
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/ConnectorParameters.java118
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/DataManager.java55
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/DataSourceHolder.java45
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/DataStrategy.java57
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/SignatorFactory.java131
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/SignatureHolderHelper.java57
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/VerificatorFactory.java65
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/config/SettingsHelper.java81
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/input/DataSource.java70
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/input/ExtractionStage.java90
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/input/PdfDataSource.java41
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/input/PdfDataSourceHolder.java49
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/input/TextDataSource.java39
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/input/correction/Corrector.java61
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/input/correction/CorrectorFactory.java63
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/output/DataSink.java42
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/sigdevice/SequentialSignatureDevice.java45
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/sigdevice/SignatureDevice.java36
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/signator/Signator.java71
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/signator/SignatorInformation.java99
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/verificator/Verificator.java61
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/vfilter/VerificationFilter.java72
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/framework/vfilter/VerificationFilterParameters.java105
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/CheckHelper.java284
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/PdfAsObject.java865
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/PosHelper.java99
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/analyze/AnalyzeResultImpl.java116
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/DataSinkAdapter.java103
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/DataSourceApiAdapter.java105
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/PdfDataSourceAdapter.java72
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/SignatureInformationAdapter.java133
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/SignatureProfileImpl.java158
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/TextBasedDataSourceApiAdapter.java92
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/TextDataSourceAdapter.java72
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/internal/PdfAsInternalObject.java362
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/sign/ActualSignaturePositionAdapter.java93
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/sign/SignResultImpl.java115
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/sign/SignatureDetailInformationImpl.java190
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/verify/SignatureCheckImpl.java71
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/verify/VerifyResultAdapter.java205
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/verify/VerifyResultsImpl.java60
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/ByteArrayPdfDataSourceImpl.java85
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/CompoundPdfDataSourceImpl.java85
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/DelimitedInputStream.java125
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/DelimitedPdfDataSource.java82
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/FileBased.java40
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/FileBasedPdfDataSourceImpl.java150
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/FileBasedTextDataSourceImpl.java160
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/IncrementalUpdateParser.java92
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/TextDataSourceImpl.java120
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/correction/ExternalCorrector.java283
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/correction/InternalCorrector.java82
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/helper/DataSourceHelper.java148
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/output/ByteArrayDataSink.java106
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/output/FileBasedDataSink.java145
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/IncrementalUpdateHelper.java74
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/SignatorInformationImpl.java40
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/binary/BinarySignatorInformation.java104
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/binary/BinarySignator_1_0_0.java598
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/binary/BinarySignator_1_1_0.java77
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/detached/DetachedTextualSignator_1_0_0.java150
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/textual/TextualSignatorInformation.java96
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/textual/TextualSignator_1_0_0.java212
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/textual/TextualSignator_1_1_0.java53
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/textual/TextualSignator_1_2_0.java53
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/verificator/binary/BinaryVerificator_1_0_0.java453
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/verificator/binary/BinaryVerificator_1_1_0.java44
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/Partition.java29
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/VerificationFilterImpl.java964
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/VerificationFilterParametersImpl.java98
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/helper/VerificationFilterBinaryHelper.java190
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/helper/VerificationFilterHelper.java162
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/helper/VerificationFilterTextHelper.java35
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/partition/BinaryPartition.java39
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/partition/TextPartition.java40
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/xmldsig/XMLDsigReconstructor.java76
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/ByteArrayDataSink.java107
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/ByteArrayDataSource.java115
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/FileBasedDataSink.java116
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/FileBasedDataSource.java141
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/FileBasedTextBasedDataSource.java123
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/io/StringTextBasedDataSource.java116
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/performance/PerformanceCounter.java82
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/performance/PerformanceCounters.java42
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/performance/PerformanceTimer.java68
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/placeholder/SignaturePlaceholderContext.java72
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/placeholder/SignaturePlaceholderData.java152
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/placeholder/SignaturePlaceholderExtractor.java350
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/test/JarExtractTest.java51
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/ConfigUtils.java318
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/DataHashUtils.java156
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/OgnlUtil.java209
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/PDFASUtils.java92
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/PdfAUtil.java66
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/StreamUtils.java66
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/TempDirHelper.java377
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/PdfAS.java1575
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/PdfASID.java222
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/ConfigLogger.java79
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/OverridePropertyHolder.java86
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/PropertyTree.java358
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/Settings.java63
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/SettingsReader.java905
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/commandline/Main.java1149
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/ConnectorException.java72
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/ConnectorFactoryException.java74
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/ErrorCodeException.java318
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/InvalidIDException.java55
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/NormalizeException.java62
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/OutOfMemoryException.java42
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/PDFDocumentException.java70
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/PlaceholderException.java66
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/PresentableException.java68
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/SettingNotFoundException.java77
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/SettingsException.java74
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/SignatorFactoryException.java47
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/SignatureException.java79
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/SignatureTypesException.java75
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/WebException.java72
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/FoundBlock.java230
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/FoundKey.java104
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/SignResult.java104
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/Signator.java93
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/SignatorFactory.java226
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/VerificationFilter.java569
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/Verificator.java62
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/BinarySignator_1_0_0.java285
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/BinarySignator_1_1_0.java83
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/DetachedSignator_1_0_0.java125
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/DetachedfTextualSignator_1_0_0.java133
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/TextualSignator_1_0_0.java136
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/TextualSignator_1_1_0.java53
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/verificators/BinaryVerificator_1_0_0.java396
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/verificators/BinaryVerificator_1_1_0.java44
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/verificators/TextualVerificator_1_0_0.java147
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/verificators/TextualVerificator_pdfasold.java106
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/api/LDAPAPIException.java77
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/api/LDAPAPIFactory.java55
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/api/LDAPAPIFactoryImpl.java92
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/api/LDAPAPIImpl.java148
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/client/LDAPClient.java88
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/client/LDAPClientFactory.java102
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/client/LDAPClientFactoryImpl.java118
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/client/LDAPClientImpl.java214
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/client/LDAPException.java50
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/client/LDAPIssuerNameFilter.java43
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/client/LDAPMapping.java181
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/client/LDAPMappingStore.java102
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/AbsoluteTextSignature.java956
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/ActualTablePos.java42
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/AdobeSignatureHelper.java272
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/BinaryBlockInfo.java61
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/BinarySignature.java2145
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/BinarySignatureHolder.java185
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/EGIZDate.java284
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/IncrementalUpdateInformation.java252
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/NoSignatureHolder.java84
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/ObjectExtractor.java233
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFPage.java377
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFSignatureCreation.java176
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFSignatureObject.java56
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFSignatureObjectIText.java618
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFUtilities.java148
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/Placeholder.java572
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/Pos.java70
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PositioningInstruction.java139
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/ReplaceInfo.java93
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/SignatureHolder.java76
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/SplitStrings.java177
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/StringInfo.java106
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/StructContentHelper.java716
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/TablePos.java262
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/TextualSignature.java282
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/TextualSignatureHolder.java153
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/Utils.java124
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/Connector.java67
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/ConnectorFactory.java372
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/ConnectorInformation.java97
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/DummyLDAPAPI.java100
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/LDAPAPI.java50
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/LocalConnector.java127
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureBlock.java316
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureData.java82
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureDataImpl.java130
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureEntry.java163
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureFieldDefinition.java88
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureObject.java2108
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureResponse.java559
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureSeparator.java146
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureTypeDefinition.java605
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureTypes.java515
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/X509Cert.java490
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/A1Connector.java63
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/BKUConnector.java896
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/BKUPostConnection.java157
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/Connector.java77
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/ConnectorChooser.java353
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/ConnectorConfigurationKeys.java55
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/ConnectorEnvironment.java52
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/LocalConnector.java91
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/MOAConnector.java921
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/TemplateReplaces.java172
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUHelper.java695
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUPostConnection.java179
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/DetachedBKUConnector.java823
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/EnvelopedBase64BKUConnector.java666
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/LocRefDetachedBKUConnector.java46
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/MultipartDetachedBKUConnector.java42
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/OldEnvelopingBase64BKUConnector.java135
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/SignSignatureObject.java272
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/SignSignatureObjectHelper.java76
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/DetachedLocRefMOAConnector.java661
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/EnvelopingBase64MOAConnector.java638
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/FilePartMR.java152
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOAHelper.java228
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapConnection.java277
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapWithAttachmentConnector.java745
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MultipartRelatedEntity.java79
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/StringPartMR.java189
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/LocRefDetachedMOCCAConnector.java623
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/MOCCAHelper.java223
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigid/DetachedIdFormatter.java101
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigid/DetachedLocRefMOAIdFormatter.java80
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigid/DetachedMOCIdFormatter.java78
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigid/HotfixIdFormatter.java74
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigid/IdFormatter.java34
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigid/OldMOAIdFormatter.java42
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigid/SimpleIdFormatter.java48
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigkz/SigKZIDHelper.java262
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/SignatureLayoutHandler.java45
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/SignatureLayoutHandlerFactory.java147
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/atrust/ATrustSignatureLayoutHandler.java47
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/mocca/MOCCASignatureLayout10Handler.java48
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/mocca/OldMOCCASignatureLayoutHandler.java48
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/td/TrustDeskSignatureLayoutHandler.java46
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signatureobject/AdditionalSignatureInformation.java41
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signatureobject/AlgorithmSignatureInformation.java33
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signatureobject/ConnectorSignatureInformation.java34
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signatureobject/MandatorySignatureInformation.java40
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signatureobject/SignatureObjectHelper.java81
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/table/Entry.java235
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/table/Style.java630
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/table/Table.java223
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/tools/CodingHelper.java301
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/tools/DebugHelper.java90
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/tools/FileHelper.java125
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/tools/Normalize.java55
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/tools/NormalizeV01.java184
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/tools/Normalizer.java280
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/ByteArrayUtils.java148
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/ParseDocument.java272
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/IndirectObjectReference.java57
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/PDFNames.java184
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/PDFUtils.java1405
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/ArrayParseResult.java42
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/BooleanParseResult.java38
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/ContainerParseResult.java45
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/DictionaryParseResult.java41
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/EOFParseResult.java47
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/FooterParseResult.java53
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/HeaderParseResult.java48
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/HexStringParseResult.java36
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/IndirectObjectReferenceParseResult.java44
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/IntegerParseResult.java36
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/LiteralStringParseResult.java37
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/NameParseResult.java35
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/NullParseResult.java34
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/NumberParseResult.java41
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/ObjectHeaderParseResult.java51
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/ObjectParseResult.java50
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/ParseResult.java50
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/StartXRefParseResult.java36
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/StreamParseResult.java41
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/TrailerParseResult.java84
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/XRefLineParseResult.java40
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/XRefSectionParseResult.java66
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/XRefSubSectionParseResult.java59
-rw-r--r--pdf-as-lib/src/main/java/demo/ExtractNonTextualObjectsDemo.java83
-rw-r--r--pdf-as-lib/src/main/java/demo/SignatureCreationDemo.java130
-rw-r--r--pdf-as-lib/src/main/java/demo/SignatureCreationWithDynamicProfilesDemo.java140
-rw-r--r--pdf-as-lib/src/main/java/demo/SignatureVerificationDemo.java265
-rw-r--r--pdf-as-lib/src/main/resources/DefaultConfiguration.zipbin0 -> 957949 bytes
-rw-r--r--pdf-as-lib/src/main/resources/at/gv/egiz/pdfas/algorithmSuite/supportedAlgorithms.txt32
-rw-r--r--pdf-as-lib/src/main/resources/at/gv/egiz/pdfas/itext/DejaVuSansCondensed.ttfbin0 -> 541104 bytes
-rw-r--r--pdf-as-lib/src/main/resources/at/gv/egiz/pdfas/itext/srgb.profilebin0 -> 3144 bytes
-rw-r--r--pdf-as-lib/src/main/resources/at/gv/egiz/pdfas/placeholder/empty.jpgbin0 -> 631 bytes
-rw-r--r--pdf-as-lib/src/main/resources/at/gv/egiz/pdfas/placeholder/pdfbox-reader.properties23
-rw-r--r--pdf-as-lib/src/main/resources/config/help_text.properties102
-rw-r--r--pdf-as-lib/src/main/resources/config/pdf-as.properties294
-rw-r--r--pdf-as-lib/src/main/resources/config/templates/default.bku.sign.detached.xml14
-rw-r--r--pdf-as-lib/src/main/resources/config/templates/default.bku.sign.enveloping.xml14
-rw-r--r--pdf-as-lib/src/main/resources/config/templates/default.bku.verify.request.detached.xml15
-rw-r--r--pdf-as-lib/src/main/resources/config/templates/default.bku.verify.request.enveloping.xml9
-rw-r--r--pdf-as-lib/src/main/resources/config/templates/default.bku.verify.template.detached.xml13
-rw-r--r--pdf-as-lib/src/main/resources/config/templates/default.bku.verify.template.enveloping.old.xml6
-rw-r--r--pdf-as-lib/src/main/resources/config/templates/default.bku.verify.template.enveloping.xml6
-rw-r--r--pdf-as-lib/src/main/resources/config/templates/default.moa.sign.detached.xml19
-rw-r--r--pdf-as-lib/src/main/resources/config/templates/default.moa.sign.enveloping.xml19
-rw-r--r--pdf-as-lib/src/main/resources/config/templates/default.moa.verify.request.detached.xml17
-rw-r--r--pdf-as-lib/src/main/resources/config/templates/default.moa.verify.request.enveloping.xml12
-rw-r--r--pdf-as-lib/src/main/resources/config/templates/default.moa.verify.template.detached.xml1
-rw-r--r--pdf-as-lib/src/main/resources/config/templates/default.moa.verify.template.enveloping.xml11
-rw-r--r--pdf-as-lib/src/main/resources/config/templates/default.moc.sign.detached.xml14
-rw-r--r--pdf-as-lib/src/main/resources/config/templates/default.moc.verify.template.detached.xml1
-rw-r--r--pdf-as-lib/src/main/resources/config/templates/etsi-bka-atrust-1.0.verify.template.detached.xml1
-rw-r--r--pdf-as-lib/src/main/resources/config/templates/moc.etsi-moc-1.0.sign.request.xml14
-rw-r--r--pdf-as-lib/src/main/resources/config/templates/moc.etsi-moc-1.0.verify.template.xml1
-rw-r--r--pdf-as-lib/src/main/resources/config/templates/moc.etsi-moc-1.1.verify.template.xml1
380 files changed, 63294 insertions, 0 deletions
diff --git a/pdf-as-lib/src/main/assembly/assemble_distribution_brz.xml b/pdf-as-lib/src/main/assembly/assemble_distribution_brz.xml
new file mode 100644
index 0000000..76ae2b5
--- /dev/null
+++ b/pdf-as-lib/src/main/assembly/assemble_distribution_brz.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+ <!-- http://maven.apache.org/plugins/maven-assembly-plugin/assembly.html -->
+<assembly xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/assembly-1.0.0.xsd">
+ <id>distribution_brz</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+ <includeBaseDirectory>true</includeBaseDirectory>
+
+ <dependencySets>
+ <dependencySet>
+ <unpack>false</unpack>
+ <scope>runtime</scope>
+ <outputDirectory>lib</outputDirectory>
+ <excludes>
+ <exclude>*:${project.artifactId}:jar</exclude>
+ </excludes>
+ </dependencySet>
+ </dependencySets>
+
+ <files>
+ <file>
+ <source>src/main/distribution/brz/pdf-as.bat</source>
+ <outputDirectory />
+ <filtered>true</filtered>
+ </file>
+ </files>
+ <fileSets>
+ <fileSet>
+ <directory>target</directory>
+ <outputDirectory />
+ <includes>
+ <include>${project.build.finalName}.jar</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>dok</directory>
+ <outputDirectory>doc</outputDirectory>
+ <includes>
+ <include>*.pdf</include>
+ </includes>
+ </fileSet>
+ </fileSets>
+</assembly>
diff --git a/pdf-as-lib/src/main/assembly/assemble_distribution_cl.xml b/pdf-as-lib/src/main/assembly/assemble_distribution_cl.xml
new file mode 100644
index 0000000..e33a6e3
--- /dev/null
+++ b/pdf-as-lib/src/main/assembly/assemble_distribution_cl.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- http://maven.apache.org/plugins/maven-assembly-plugin/assembly.html -->
+<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>distribution_cl</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+ <baseDirectory>pdf-as</baseDirectory>
+ <includeBaseDirectory>true</includeBaseDirectory>
+ <dependencySets>
+ <dependencySet>
+ <unpack>false</unpack>
+ <scope>runtime</scope>
+ <outputDirectory>lib</outputDirectory>
+ <excludes>
+ <exclude>*:${project.artifactId}:jar</exclude>
+ </excludes>
+ </dependencySet>
+ </dependencySets>
+ <fileSets>
+ <fileSet>
+ <directory>src/main/distribution/cl</directory>
+ <filtered>true</filtered>
+ <outputDirectory/>
+ <includes>
+ <include>*.bat</include>
+ <include>*.sh</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>target</directory>
+ <outputDirectory/>
+ <includes>
+ <include>${project.build.finalName}.jar</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>dok/Anwendungsbeschreibung</directory>
+ <outputDirectory>doc</outputDirectory>
+ <includes>
+ <include>PDF-AS-${project.version}-Anwendungsbeschreibung.pdf</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>dok/Anwendungsbeschreibung/Platzhalter-Beispiele</directory>
+ <outputDirectory>doc/Platzhalter-Beispiele</outputDirectory>
+ <includes>
+ <include>*.jpg</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>dok/Konfiguration</directory>
+ <outputDirectory>doc</outputDirectory>
+ <includes>
+ <include>*.pdf</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>dok/Spezifikation/Spezifikation-Layout-Amtssignatur-las-v1.4.0</directory>
+ <outputDirectory>doc</outputDirectory>
+ <includes>
+ <include>Spezifikation-Layout-Amtssignatur-las-v1.4.0.pdf</include>
+ </includes>
+ </fileSet>
+ </fileSets>
+</assembly>
diff --git a/pdf-as-lib/src/main/assembly/assemble_distribution_ws.xml b/pdf-as-lib/src/main/assembly/assemble_distribution_ws.xml
new file mode 100644
index 0000000..ff73f9d
--- /dev/null
+++ b/pdf-as-lib/src/main/assembly/assemble_distribution_ws.xml
@@ -0,0 +1,203 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- http://maven.apache.org/plugins/maven-assembly-plugin/assembly.html -->
+<assembly>
+ <id>distribution-ws</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+ <includeBaseDirectory>false</includeBaseDirectory>
+ <fileSets>
+ <fileSet>
+ <directory>distribution/tomcat/tomcat-5.5.20-standalone</directory>
+ <outputDirectory>/pdf-as-ws/tomcat</outputDirectory>
+ <includes>
+ <include>**/*</include>
+ </includes>
+ <excludes>
+ <exclude>.svn</exclude>
+ </excludes>
+ </fileSet>
+ <fileSet>
+ <directory>distribution/jdk/1.5.0_06/</directory>
+ <outputDirectory>/pdf-as-ws/jsdk</outputDirectory>
+ <includes>
+ <include>**/*</include>
+ </includes>
+ <excludes>
+ <exclude>.svn</exclude>
+ </excludes>
+ </fileSet>
+ <fileSet>
+ <directory>webapp</directory>
+ <outputDirectory>/pdf-as-ws/tomcat/webapps/pdf-as</outputDirectory>
+ <includes>
+ <include>**/*</include>
+ </includes>
+ <excludes>
+ <exclude>.svn</exclude>
+ </excludes>
+ </fileSet>
+ <fileSet>
+ <directory>target</directory>
+ <outputDirectory>/pdf-as-ws/tomcat/webapps/pdf-as/WEB-INF/lib</outputDirectory>
+ <includes>
+ <include>pdf-as*.jar</include>
+ </includes>
+ <excludes>
+ <exclude>.svn</exclude>
+ </excludes>
+ </fileSet>
+ <fileSet>
+ <directory>distribution/cfg</directory>
+ <outputDirectory>/pdf-as-ws/tomcat/conf/pdf-as/cfg</outputDirectory>
+ <includes>
+ <include>*.properties</include>
+ </includes>
+ <excludes>
+ <exclude>.svn</exclude>
+ </excludes>
+ </fileSet>
+ <fileSet>
+ <directory>distribution/tomcat</directory>
+ <outputDirectory>/pdf-as-ws/tomcat/conf/catalina/localhost</outputDirectory>
+ <includes>
+ <include>pdf-as.xml</include>
+ </includes>
+ <excludes>
+ <exclude>.svn</exclude>
+ </excludes>
+ </fileSet>
+
+ <fileSet>
+ <directory>distribution/certificates</directory>
+ <outputDirectory>/pdf-as-ws/tomcat/conf/pdf-as/certificates</outputDirectory>
+ <includes>
+ <include>**/*</include>
+ </includes>
+ <excludes>
+ <exclude>.svn</exclude>
+ </excludes>
+ </fileSet>
+ <fileSet>
+ <directory>distribution/pdfastmp</directory>
+ <outputDirectory>/pdf-as-ws/tomcat/conf/pdf-as/pdfastmp</outputDirectory>
+ <includes>
+ <include>**/*</include>
+ </includes>
+ <excludes>
+ <exclude>.svn</exclude>
+ </excludes>
+ </fileSet>
+ <fileSet>
+ <directory>distribution/images</directory>
+ <outputDirectory>/pdf-as-ws/tomcat/conf/pdf-as/images</outputDirectory>
+ <includes>
+ <include>**/*</include>
+ </includes>
+ <excludes>
+ <exclude>.svn</exclude>
+ </excludes>
+ </fileSet>
+ <fileSet>
+ <directory>work/templates</directory>
+ <outputDirectory>/pdf-as-ws/tomcat/conf/pdf-as/templates</outputDirectory>
+ <includes>
+ <include>**/*</include>
+ </includes>
+ <excludes>
+ <exclude>.svn</exclude>
+ </excludes>
+ </fileSet>
+ <fileSet>
+ <directory>work/licenses</directory>
+ <outputDirectory>/pdf-as-ws/tomcat/conf/pdf-as/licenses</outputDirectory>
+ <includes>
+ <include>**/*</include>
+ </includes>
+ <excludes>
+ <exclude>.svn</exclude>
+ </excludes>
+ </fileSet>
+
+ <fileSet>
+ <directory>distribution/moaspss/moa-spss-1.4.2beta1</directory>
+ <outputDirectory>/pdf-as-ws/tomcat/webapps</outputDirectory>
+ <includes>
+ <include>moa-spss.war</include>
+ </includes>
+ <excludes>
+ <exclude>.svn</exclude>
+ </excludes>
+ </fileSet>
+ <fileSet>
+ <directory>distribution/moaspss/moa-spss-1.4.2beta1/conf</directory>
+ <outputDirectory>/pdf-as-ws/tomcat/conf</outputDirectory>
+ <includes>
+ <include>**/*</include>
+ </includes>
+ <excludes>
+ <exclude>.svn</exclude>
+ </excludes>
+ </fileSet>
+ <fileSet>
+ <directory>distribution/moaspss/moa-spss-1.4.2beta1/endorsed</directory>
+ <outputDirectory>/pdf-as-ws/tomcat/common/endorsed</outputDirectory>
+ <includes>
+ <include>**/*</include>
+ </includes>
+ <excludes>
+ <exclude>.svn</exclude>
+ </excludes>
+ </fileSet>
+ <fileSet>
+ <directory>distribution/moaspss/moa-spss-1.4.2beta1/ext</directory>
+ <outputDirectory>/pdf-as-ws/tomcat/common/lib</outputDirectory>
+ <includes>
+ <include>**/*</include>
+ </includes>
+ <excludes>
+ <exclude>.svn</exclude>
+ </excludes>
+ </fileSet>
+
+
+ <fileSet>
+ <directory>distribution/tomcat</directory>
+ <outputDirectory>/pdf-as-ws/tomcat</outputDirectory>
+ <includes>
+ <include>startTomcat.bat</include>
+ <include>stopTomcat.bat</include>
+ <include>favicon.ico</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>distribution/</directory>
+ <outputDirectory>/pdf-as-ws/tomcat</outputDirectory>
+ <includes>
+ <include>Starten PDF-Amtssignatur.bat</include>
+ <include>Beenden PDF-Amtssignatur.bat</include>
+ </includes>
+ </fileSet>
+ <!--fileSet>
+ <directory>distribution/doc</directory>
+ <outputDirectory>/pdf-as-cl</outputDirectory>
+ <includes>
+ <include>Demotext.pdf</include>
+ </includes>
+ </fileSet-->
+ </fileSets>
+ <!--files>
+ <file>
+ <source>distribution/scripts/pdf-as.bat</source>
+ <outputDirectory>/pdf-as-cl</outputDirectory>
+ <filtered>true</filtered>
+ </file>
+ </files-->
+ <dependencySets>
+ <dependencySet>
+ <unpack>false</unpack>
+ <scope>runtime</scope>
+ <outputDirectory>/pdf-as-ws/tomcat/webapps/pdf-as/WEB-INF/lib</outputDirectory>
+ </dependencySet>
+ </dependencySets>
+</assembly>
diff --git a/pdf-as-lib/src/main/assembly/assemble_libraries.xml b/pdf-as-lib/src/main/assembly/assemble_libraries.xml
new file mode 100644
index 0000000..446e9ba
--- /dev/null
+++ b/pdf-as-lib/src/main/assembly/assemble_libraries.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- http://maven.apache.org/plugins/maven-assembly-plugin/assembly.html -->
+<assembly>
+ <id>libraries</id>
+ <formats>
+ <format>dir</format>
+ </formats>
+ <includeBaseDirectory>false</includeBaseDirectory>
+ <dependencySets>
+ <dependencySet>
+ <unpack>false</unpack>
+ <scope>compile</scope>
+ <outputDirectory>/</outputDirectory>
+ </dependencySet>
+ </dependencySets>
+</assembly>
diff --git a/pdf-as-lib/src/main/assembly/assemble_repository.xml b/pdf-as-lib/src/main/assembly/assemble_repository.xml
new file mode 100644
index 0000000..cbfe790
--- /dev/null
+++ b/pdf-as-lib/src/main/assembly/assemble_repository.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- http://maven.apache.org/plugins/maven-assembly-plugin/assembly.html -->
+<assembly>
+ <id>maven2-repository</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <repositories>
+
+ <repository>
+ <includeMetadata>false</includeMetadata>
+ <outputDirectory>/</outputDirectory>
+ </repository>
+
+ </repositories>
+
+</assembly>
diff --git a/pdf-as-lib/src/main/distribution/brz/pdf-as.bat b/pdf-as-lib/src/main/distribution/brz/pdf-as.bat
new file mode 100644
index 0000000..059b977
--- /dev/null
+++ b/pdf-as-lib/src/main/distribution/brz/pdf-as.bat
@@ -0,0 +1,8 @@
+@echo off
+
+rem Deploy embedded default configuration to current folder
+rem Note: Configuration is not deployed if it already exists.
+rem java -Dpdf-as.work-dir=. -jar ${project.build.finalName}.jar -ddc
+
+rem Start commandline
+java -Xms128m -Xmx786m -XX:MaxPermSize=256m -Dpdf-as.work-dir=. -jar ${project.build.finalName}.jar %*
diff --git a/pdf-as-lib/src/main/distribution/cl/pdf-as.bat b/pdf-as-lib/src/main/distribution/cl/pdf-as.bat
new file mode 100644
index 0000000..0cadb9a
--- /dev/null
+++ b/pdf-as-lib/src/main/distribution/cl/pdf-as.bat
@@ -0,0 +1,8 @@
+@echo off
+
+rem Deploys embedded default configuration to USER_HOME/PDF-AS.
+rem Note: Configuration is not deployed if it already exists.
+java -jar ${project.build.finalName}.jar -ddc
+
+rem Start commandline
+java -Xms128m -Xmx786m -XX:MaxPermSize=256m -jar ${project.build.finalName}.jar %*
diff --git a/pdf-as-lib/src/main/distribution/cl/pdf-as.sh b/pdf-as-lib/src/main/distribution/cl/pdf-as.sh
new file mode 100644
index 0000000..f47bc5f
--- /dev/null
+++ b/pdf-as-lib/src/main/distribution/cl/pdf-as.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+# Deploys embedded default configuration to USER_HOME/PDF-AS.
+# Note: Configuration is not deployed if it already exists.
+java -jar ${project.build.finalName}.jar -ddc
+
+# Start commandline
+java -Xms128m -Xmx786m -XX:MaxPermSize=256m -jar ${project.build.finalName}.jar $@
diff --git a/pdf-as-lib/src/main/distribution/cl/sign.bat b/pdf-as-lib/src/main/distribution/cl/sign.bat
new file mode 100644
index 0000000..e25213b
--- /dev/null
+++ b/pdf-as-lib/src/main/distribution/cl/sign.bat
@@ -0,0 +1 @@
+call pdf-as.bat -mode sign -sigmode textual -connector bku %1 %2 %3 %4 %5 %6 %7 %8 %9
diff --git a/pdf-as-lib/src/main/distribution/cl/sign.sh b/pdf-as-lib/src/main/distribution/cl/sign.sh
new file mode 100644
index 0000000..410b3fe
--- /dev/null
+++ b/pdf-as-lib/src/main/distribution/cl/sign.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+./pdf-as.sh -mode sign -sigmode textual -connector bku $@
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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas;
+
+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 <code>null</code> 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 <code>null</code> the configuration is assumed to be located
+ * within the user's home directory.
+ *
+ * @param registerProvider <code>true</code>: automatically registers IAIK JCE and ECC Provider;
+ * <code>false</code>: providers will NOT be automatically registered, providers
+ * needed have to be registered by the API user
+ * @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 <code>true</code>: automatically registers IAIK JCE and ECC Provider;
+ * <code>false</code>: providers will NOT be automatically registered, providers
+ * needed have to be registered by the API user
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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.<br>
+ * Supported algorithms are defined in external resource {@value #SUPPORTED_ALGORITHMS_RESOURCE}<br>
+ *
+ * e.g. <code>sha1 <-> http://www.w3.org/2000/09/xmldsig#sha1</code>
+ *
+ * @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<br>
+ *
+ * e.g. <code>sha1 from http://www.w3.org/2000/09/xmldsig#sha1</code>
+ *
+ * @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<br>
+ *
+ * e.g. <code>http://www.w3.org/2000/09/xmldsig#sha1 from sha1</code>
+ *
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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}.<br>
+ *
+ * This structured object is representing a string like
+ * <code>ecdsa-sha256:sha256:sha256:ripemd160</code><br>
+ * meaning
+ * <code>signatureMethod:dataDigestMethod:propertiesDigestMethod:certDigestMethod</code>
+ *
+ * @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
+ * <code>etsi-moc-1.2:ecdsa-sha1:ripemd160@207c44ff</code>
+ * Prefix included
+ *
+ * @param parameterString
+ */
+ public AlgorithmSuiteObject(String parameterString) {
+ parseFrom(parameterString, true);
+ }
+
+ /**
+ * Create object from parameter string like <br>
+ * <code>etsi-moc-1.2:ecdsa-sha1:ripemd160@207c44ff</code> hasPrefix=true <br>
+ * <code>ecdsa-sha1:ripemd160@207c44ff</code> 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
+ * <code>etsi-moc-1.2:ecdsa-sha1:ripemd160@207c44ff</code> hasPrefix=true <br>
+ * <code>ecdsa-sha1:ripemd160@207c44ff</code> 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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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 <code>out-param</code> 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 <code>CreateXMLSignatureResponse<code>
+ *
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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.
+ *
+ * <p>
+ * Create an Object implementing this interface using the proper factory.
+ * </p>
+ *
+ * @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.<br/>
+ * 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 <xmldsig:Signature> 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 <xmldsig:Signature> 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.
+ *
+ * <p>
+ * Note: Currently the profile information consists of the profile Id and the
+ * MOA Key Id only.
+ * </p>
+ * <p>
+ * 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.
+ * </p>
+ *
+ * @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}.
+ * <br>
+ * 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}.
+ * <br>
+ * 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 <code>null</code> 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.<br/>
+ * 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.<br/>
+ * 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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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.
+ *
+ * <p>
+ * 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).
+ * </p>
+ */
+ 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 <tt>false</tt>
+ *
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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
+ * <code>correct_document_on_verify_if_necessary</code>). 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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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.
+ *
+ * <p>
+ * The document text is signed, but instead of returning the pdf with the signature block,
+ * the sign result XML of the connector is returned.
+ * </p>
+ */
+ 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.
+ *
+ * <p>
+ * This mode of operation tries to minimize the numbers of text extractions,
+ * which are very time intensive, at the cost of some rare cases, in which some
+ * signatures may not be found.
+ * </p>
+ */
+ 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.<br/>
+ * If the placeholder with the given id is not found in the document, an exception will be thrown.
+ */
+ public static final int PLACEHOLDER_MATCH_MODE_STRICT = 0;
+
+ /**
+ * A moderate matching mode for placeholder extraction.<br/>
+ * If the placeholder with the given id is not found in the document, the first placeholder without an id will be taken.<br/>
+ * If there is no such placeholder, the signature will be placed as usual, according to the pos parameter of the signature profile used.
+ */
+ public static final int PLACEHOLDER_MATCH_MODE_MODERATE = 1;
+
+ /**
+ * A more lenient matching mode for placeholder extraction.<br/>
+ * If the placeholder with the given id is not found in the document, the first found placeholder will be taken, regardless if it has an id set, or not.<br/>
+ * If there is no placeholder at all, the signature will be placed as usual, according to the pos parameter of the signature profile used.
+ */
+ public static final int PLACEHOLDER_MATCH_MODE_LENIENT = 2;
+
+ /**
+ * Identifier for QR based placeholders.
+ */
+ public static final String QR_PLACEHOLDER_IDENTIFIER = "PDF-AS-POS";
+
+}
+
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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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)}.<br>
+ * 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()}.<br>
+ * Depending on the {@link DynamicSignatureLifetimeEnum} the profile can be alive and usable till you {@link #dispose()} it manually.
+ * <p>
+ * Sample usage:<br>
+ * <pre>
+ 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());
+ * </pre>
+ * </p>
+ *
+ * @author exthex
+ *
+ */
+public interface DynamicSignatureProfile {
+
+ /**
+ * Get the name of the dynamic signature profile. Equals the <b>SignatureProfileId</b>
+ * @return
+ */
+ public abstract String getName();
+
+ /**
+ * Set a field value for the profile. Use {@link #setPropertyRaw(String, String)} for setting any property.<br>
+ * For example to set <code>sig_obj.MEIN_DYN_SIGNATURBLOCK.value.SIG_META</code> just use <code>SIG_META</code> 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 <code>sig_obj.MEIN_DYN_SIGNATURBLOCK.key.SIG_META</code> use <code>key.SIG_META</code>
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $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).
+ *
+ * <p>
+ * May be {@link Constants#SIGNATURE_TYPE_BINARY} or
+ * {@link Constants#SIGNATURE_TYPE_TEXTUAL}.
+ * </p>
+ *
+ * @return Returns the type of this signature (binary/textual).
+ */
+ public String getSignatureType();
+
+ /**
+ * Returns the DataSource providing the data that was signed.
+ *
+ * <p>
+ * 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).
+ * </p>
+ *
+ * @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.
+ *
+ * <p>
+ * Information like subject name, issuer name or serial number can be
+ * retrieved form this certificate.
+ * </p>
+ *
+ * @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.
+ *
+ * <p>
+ * 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.
+ * </p>
+ *
+ * @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 <tt>null</tt> of not available (binary signature)
+ */
+ public List getNonTextualObjects();
+
+ public void setNonTextualObjects(List nonTextualObjects);
+
+ /**
+ * Returns <code>true</code> if non textual objects have been found, <code>false</code> if not.
+ * @return <code>true</code> if non textual objects have been found, <code>false</code> 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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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.<br/>
+ * e.g. properties starting with <code>sig_obj.PROFILE.key.</code> and
+ * properties of the form <code>sig_obj.PROFILE.table.TABLENAME.NUMBER</code>
+ * where <code>PROFILE</code> is the name of the current profile,
+ * <code>TABLENAME</code> is the name of a table and <code>NUMBER</code>
+ * is the number of the specific row within the table <code>TABLENAME</code>.
+ *
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.api.exceptions;
+
+/**
+ * @author <a href="mailto:thomas.knall@egiz.gv.at">Thomas Knall</a>
+ */
+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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.api.exceptions;
+
+/**
+ * This exception is the base for all PDF-AS exceptions.
+ *
+ * <p>
+ * Every PDF-AS Exception has an error code.
+ * </p>
+ *
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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.<br/>
+ * 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.<br/>
+ * 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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $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 <code>SignatureEntry</code> 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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.api.io;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Output document data sink.
+ *
+ * <p>
+ * 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.).
+ * </p>
+ *
+ * @author wprinz
+ */
+public interface DataSink
+{
+ /**
+ * Creates an OutputStream for binary data.
+ *
+ * <p>
+ * Note that the stream may be written only once. Creating another stream
+ * overwrites the existing one.
+ * </p>
+ *
+ * @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.
+ *
+ * <p>
+ * This is basically the same as {@link #createOutputStream(String)}, but
+ * allows to specify the character encoding.
+ * </p>
+ *
+ * @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.
+ *
+ * <p>
+ * This is only valid after a stream has been created.
+ * </p>
+ *
+ * @return Returns the mime type of the data stream.
+ */
+ public String getMimeType();
+
+ /**
+ * Returns the character encoding of the data stream.
+ *
+ * <p>
+ * 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).
+ * </p>
+ *
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.api.io;
+
+import java.io.InputStream;
+
+/**
+ * Input document data source.
+ *
+ * <p>
+ * 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).
+ * </p>
+ *
+ * @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.
+ *
+ * <p>
+ * Calling this method indicates that you need a byte array for random
+ * <strong>read only</strong> access. The DataSource implementation should of
+ * course cache this byte array to avoid too much memory usage.
+ * </p>
+ * <p>
+ * Performance analysis has shown that the libraries internally convert the
+ * streams to byte arrays and that file system access is very slow.
+ * </p>
+ * <p>
+ * Never write to this byte array!
+ * </p>
+ *
+ * @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.
+ *
+ * <p>
+ * This makes only sense for character based mime types.
+ * </p>
+ *
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.api.io;
+
+import java.io.File;
+
+/**
+ * Tells that the IO element (DataSink or DataSource) is backed by a file in the local file system.
+ *
+ * <p>
+ * This is a hint that may be used by PDF-AS to optimize data access.
+ * </p>
+ *
+ * @author wprinz
+ */
+public interface FileBased
+{
+
+ /**
+ * Returns the File "behind" this io element.
+ *
+ * <p>
+ * This is usually used to determine the file name itself.
+ * </p>
+ *
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.api.io;
+
+/**
+ * Tells, that the IO Element (DataSink - but mostly DataSource) is based upon
+ * character data.
+ *
+ * <p>
+ * This can be used to retrieve the character text directly with the correct
+ * encoding etc.
+ * </p>
+ * <p>
+ * This makes most sense for text DataSources.
+ * </p>
+ *
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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.
+ *
+ * <p>
+ * 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
+ * </p>
+ */
+ protected DataSource document = null;
+
+ /**
+ * The type of the signature.
+ *
+ * <p>
+ * May be {@link Constants#SIGNATURE_TYPE_BINARY} or
+ * {@link Constants#SIGNATURE_TYPE_TEXTUAL}.
+ * </p>
+ */
+ protected String signatureType = Constants.DEFAULT_SIGNATURE_TYPE;
+
+ /**
+ * The signature device to perform the actual signature.
+ *
+ * <p>
+ * May be {@link Constants#SIGNATURE_DEVICE_MOA} or
+ * {@link Constants#SIGNATURE_DEVICE_BKU}.
+ * </p>
+ */
+ protected String signatureDevice = Constants.SIGNATURE_DEVICE_MOA;
+
+ /**
+ * The signature profile identifier identifying the profile to be used in the
+ * config file.
+ *
+ * <p>
+ * Note: In near future it will be possible to provide a full specified
+ * profile here instead of the profile id.
+ * </p>
+ */
+ protected String signatureProfileId = null;
+
+ /**
+ * The signature key identifier specifying which signature key should be used
+ * by the signature device to perform the signature.
+ *
+ * <p>
+ * Providing a null value (default) means that no explicit signature key
+ * identifier is provided. The selected signature device will then use its
+ * default mechanism for retrieving this information (which is usually to read
+ * the key from the provided signature profile).
+ * </p>
+ * <p>
+ * Note that not all signature devices may support this parameter.
+ * If a signature device doesn't support this parameter the value should be null.
+ * </p>
+ * <p>
+ * This key is usually passed straight through to the signature device and
+ * thereby has to contain an appropriate value for the signature device
+ * chosen.
+ * </p>
+ * <p>
+ * 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.
+ * </p>
+ */
+ 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.<br/>
+ * 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.
+ * <br/>
+ * 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.
+ * <p>
+ * Sample usage:
+ * <pre>
+ 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);
+ </pre>
+ * </p>
+ * @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.<br/>
+ * Exactly matching meaning:<br/>
+ * <ul><li>If a placeholderId is set: a placeholder which has exactly this id embedded</li>
+ * <li>If no placeholderId is set: a placeholder without an embedded id is found</li></ul>
+ *
+ * @see Constants#PLACEHOLDER_MATCH_MODE_LENIENT
+ * @see Constants#PLACEHOLDER_MATCH_MODE_MODERATE
+ * @see Constants#PLACEHOLDER_MATCH_MODE_STRICT
+ *
+ * Defaults to {@link Constants#PLACEHOLDER_MATCH_MODE_MODERATE}.
+ *
+ * @param placeholderMatchMode
+ */
+ public void setPlaceholderMatchMode(int placeholderMatchMode) {
+ 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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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.
+ *
+ * <p>
+ * This information can be useful for post-processing the document.
+ * </p>
+ *
+ * <p>
+ * Consult the PDF-AS documentation section Commandline for further
+ * information about positioning.
+ * </p>
+ *
+ * @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 <tt>null</tt> 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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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 <tt>null</tt> 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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.api.sign.pos;
+
+/**
+ * Holds the actual, absolute signature position where a signature was placed.
+ *
+ * <p>
+ * This is usually returned after signing.
+ * </p>
+ *
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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.
+ *
+ * <p>
+ * This positioning allows to select the location where the signature block is
+ * placed in the document.
+ * </p>
+ *
+ * @author wprinz
+ */
+public class SignaturePositioning implements Serializable
+{
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * The x axis algorithm.
+ *
+ * <p>
+ * May be {@link AutoAxisAlgorithm} or {@link AbsoluteAxisAlgorithm}
+ * </p>
+ */
+ protected AxisAlgorithm xAlgorithm = new AutoAxisAlgorithm();
+
+ /**
+ * The y axis algorithm.
+ *
+ * <p>
+ * May be {@link AutoAxisAlgorithm} or {@link AbsoluteAxisAlgorithm}
+ * </p>
+ */
+ protected AxisAlgorithm yAlgorithm = new AutoAxisAlgorithm();
+
+ /**
+ * The width algorithm.
+ *
+ * <p>
+ * May be {@link AutoAxisAlgorithm} or {@link AbsoluteAxisAlgorithm}
+ * </p>
+ */
+ protected AxisAlgorithm widthAlgorithm = new AutoAxisAlgorithm();
+
+ /**
+ * The page algorithm.
+ *
+ * <p>
+ * May be {@link AutoPageAlgorithm}, {@link AbsolutePageAlgorithm} or
+ * {@link NewPageAlgorithm}
+ * </p>
+ */
+ protected PageAlgorithm pageAlgorithm = new AutoPageAlgorithm();
+
+ /**
+ * Provides the position of the footline.
+ *
+ * <p>
+ * Only used if the pageAlgorithm is {@link AutoPageAlgorithm} and the
+ * yAlgorithm is {@link AutoAxisAlgorithm}
+ * </p>
+ */
+ 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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.api.sign.pos.page;
+
+import java.io.Serializable;
+
+/**
+ * The page for placing the signature is selected automatically.
+ *
+ * <p>
+ * 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.
+ * </p>
+ *
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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.
+ *
+ * <p>
+ * May be {@link Constants#SIGNATURE_DEVICE_MOA} or
+ * {@link Constants#SIGNATURE_DEVICE_BKU}.
+ * </p>
+ */
+ 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).
+ *
+ * <p>
+ * 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.
+ * </p>
+ */
+ 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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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.
+ *
+ * <p>
+ * May be {@link Constants#SIGNATURE_DEVICE_MOA} or
+ * {@link Constants#SIGNATURE_DEVICE_BKU}.
+ * </p>
+ */
+ 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).
+ *
+ * <p>
+ * 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.
+ * </p>
+ */
+ 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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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.
+ *
+ * <p>
+ * May be {@link Constants#SIGNATURE_DEVICE_MOA} or
+ * {@link Constants#SIGNATURE_DEVICE_BKU}.
+ * </p>
+ */
+ protected String signatureDevice = Constants.SIGNATURE_DEVICE_MOA;
+
+ /**
+ * The mode of operation how the document is analyzed.
+ *
+ * <p>
+ * 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).
+ * </p>
+ */
+ protected String verifyMode = Constants.VERIFY_MODE_FULL_CONSERVATIVE;
+
+ /**
+ * The (zero based) index of the signature to verify.
+ *
+ * <p>
+ * This allows to verify only one found signature instead of all. {@link Constants#VERIFY_ALL} means to
+ * verify all found signatures.
+ * </p>
+ */
+ protected int signatureToVerify = Constants.VERIFY_ALL;
+
+ /**
+ * Allows to pass a VerificationTime to the verification device.
+ *
+ * <p>
+ * Note that the actual usage of this parameter depends on the verification device.
+ * </p>
+ */
+ 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).
+ *
+ * <p>
+ * 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.
+ * </p>
+ */
+ 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 <tt>false</tt>
+ *
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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.
+ *
+ * <p>
+ * 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".
+ * </p>
+ *
+ * @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.
+ *
+ * <p>
+ * 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.
+ * </p>
+ * <p>
+ * 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()}).
+ * </p>
+ *
+ * @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.
+ *
+ * <p>
+ * This will only return a value other than null if the corresponding
+ * {@link VerifyParameters} has been set to true.
+ * </p>
+ * <p>
+ * Note that the HashInputData does not necessarily have to be exactly the
+ * same as the signed data return by the
+ * {@link SignatureInformation#getSignedData()} method.
+ * </p>
+ *
+ * @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 <tt>null</tt> of not available (binary signature)
+ */
+ public List getNonTextualObjects();
+
+
+ /**
+ * Returns <code>true</code> if non textual objects have been found, <code>false</code> if not.
+ * @return <code>true</code> if non textual objects have been found, <code>false</code> 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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.api.verify;
+
+import java.util.List;
+
+/**
+ * The result of the verification of a document.
+ *
+ * <p>
+ * 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.
+ * </p>
+ *
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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.
+ *
+ * <p>
+ * May be {@link Constants#SIGNATURE_DEVICE_MOA} or
+ * {@link Constants#SIGNATURE_DEVICE_BKU}.
+ * </p>
+ */
+ 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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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.
+ *
+ * <p>
+ * May be {@link Constants#SIGNATURE_DEVICE_MOA} or
+ * {@link Constants#SIGNATURE_DEVICE_BKU}.
+ * </p>
+ */
+ protected String signatureDevice = Constants.SIGNATURE_DEVICE_MOA;
+
+ /**
+ * The mode of operation how the document is analyzed.
+ *
+ * <p>
+ * 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).
+ * </p>
+ */
+ protected String verifyMode = Constants.VERIFY_MODE_FULL_CONSERVATIVE;
+
+ /**
+ * The (zero based) index of the signature to verify.
+ *
+ * <p>
+ * This allows to verify only one found signature instead of all. {@link Constants#VERIFY_ALL} means to
+ * verify all found signatures.
+ * </p>
+ */
+ protected int signatureToVerify = Constants.VERIFY_ALL;
+
+ /**
+ * Allows to pass a VerificationTime to the verification device.
+ *
+ * <p>
+ * Note that the actual usage of this parameter depends on the verification device.
+ * </p>
+ */
+ 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).
+ *
+ * <p>
+ * 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.
+ * </p>
+ */
+ 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 <tt>false</tt>
+ *
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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.<br/>
+ * 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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $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.
+ *
+ * <p>
+ * The commandline uses the PDF-AS API.
+ * </p>
+ *
+ * @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.
+ *
+ * <p>
+ * The extension of a file name is whatever text follows the last '.'.
+ * </p>
+ *
+ * @param file_name
+ * The file name.
+ * @return Returns the extension. If the file name ends with the '.', then an
+ * 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] <input file> [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 + " <user_name> ... [optional] the user name");
+ writer.println(" " + PARAMETER_USER_PASSWORD + " <password> ... [optional] the user password");
+
+ writer.println(" " + PARAMETER_POS + " <position> ... [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 + " <true|false> ... [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 + " <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 <moderate>.");
+ 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 + " <number> ... [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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.exceptions;
+
+/**
+ * Contains constants for the error codes.
+ *
+ * <p>
+ * In Java 1.5 this would be an enum.
+ * </p>
+ *
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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.
+ *
+ * <p>
+ * 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.
+ * </p>
+ *
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.framework;
+
+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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.framework;
+
+import java.util.Date;
+
+/**
+ * Parameters passed to the constructor of the Connector.
+ *
+ * <p>
+ * Each Connector must have a constructor accepting this parameter class as an
+ * argument.
+ * </p>
+ *
+ * @author wprinz
+ */
+public class ConnectorParameters {
+ /**
+ * The profile Id to get the connector parameters from.
+ *
+ * <p>
+ * The there are no explicit parameters for the connector in the profile, the
+ * default parameters are used.
+ * </p>
+ */
+ protected String profileId = null;
+
+ /**
+ * The signature key identifier to be used or null if it should be read from
+ * the profile.
+ *
+ * <p>
+ * 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.
+ * </p>
+ */
+ protected String signatureKeyIdentifier = null;
+
+ /**
+ * Tells, if the connector should ask the device to return the hash input
+ * data.
+ *
+ * <p>
+ * 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.
+ * </p>
+ */
+ protected boolean returnHashInputData = false;
+
+ /**
+ * Allows to specify an explicit time of verification.
+ *
+ * <p>
+ * If null, the device's default behaviour determines the time of
+ * verification, which is usually the current time.
+ * </p>
+ * <p>
+ * The time of verification usually influences the certificate check. E.g.
+ * the certificate may not be valid at the time of verification.
+ * </p>
+ */
+ 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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.framework;
+
+/**
+ * The DataManager is a mediator for all components that need to allocate large
+ * data elements.
+ *
+ * <p>
+ * 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.
+ * </p>
+ *
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.framework;
+
+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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.framework;
+
+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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.framework;
+
+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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.framework;
+
+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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.framework;
+
+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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.framework.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.framework.input;
+
+import java.io.InputStream;
+
+/**
+ * The input document data source.
+ *
+ * <p>
+ * Usually this is a PdfDataSource, but it may be a TextDataSource as well.
+ * </p>
+ *
+ * @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.
+ *
+ * <p>
+ * Calling this method indicates that you need a byte array for random <strong>read</strong> access.
+ * The DataSource implementation should of course cache this byte array to avoid too much memory usage.
+ * </p>
+ * <p>
+ * Performance analysis has shown that the libraries internally convert the streams to byte arrays and
+ * that file system access is very slow.
+ * </p>
+ *
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.framework.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.framework.input;
+
+
+/**
+ * Represents the binary data of a PDF document.
+ *
+ * <p>
+ * 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.
+ * </p>
+ *
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.framework.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.framework.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.framework.input.correction;
+
+import at.gv.egiz.pdfas.exceptions.framework.CorrectorException;
+import at.gv.egiz.pdfas.framework.input.PdfDataSource;
+
+/**
+ * Interface for PDF corretors.
+ *
+ * <p>
+ * 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.
+ * </p>
+ * <p>
+ * A PDF corrector takes an incorrect PDF document and transforms it into a
+ * correct one.
+ * </p>
+ * <p>
+ * Note that correcting a document destroys all signatures in that document, so
+ * never correct an already signed document.
+ * </p>
+ *
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.framework.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.framework.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.framework.sigdevice;
+
+/**
+ * A SignatureDevice that can be accessed in a sequential manner.
+ *
+ * <p>
+ * 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.
+ * </p>
+ *
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.framework.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $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.
+ *
+ * <p>
+ * This should always return the MY_ID static field of the connector. Dont't
+ * forget to override this.
+ * </p>
+ * <p>
+ * Within connector code always use this method so that code reuse through
+ * derivation can take place correctly.
+ * </p>
+ *
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.framework.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.
+ *
+ * <p>
+ * This supersedes the IncrementalUpdateInformation.
+ * </p>
+ *
+ * @author wprinz
+ */
+public interface SignatorInformation
+{
+ /**
+ * Returns the SignatureData to be signed.
+ * <p>
+ * This is passed on to the Connector and signature device for signing.
+ * </p>
+ *
+ * @return Returns the SignatureData to be signed.
+ */
+ public SignatureData getSignatureData();
+
+ /**
+ * Sets the SignSignatureObject with the signature data.
+ *
+ * <p>
+ * This is called by the framework to provide the finishSign with the
+ * signature data.
+ * </p>
+ *
+ * @param signSignatureObject
+ * The SignSignatureObject.
+ */
+ public void setSignSignatureObject(SignSignatureObject signSignatureObject);
+
+ /**
+ * Returns the SignSignatureObject.
+ *
+ * <p>
+ * After signation, this is used by the framework/API to get additional
+ * information about the signature.
+ * </p>
+ *
+ * @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 <tt>null</tt> 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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.framework.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.framework.vfilter;
+
+/**
+ * The parameters of the VerificationFilter algorithm.
+ *
+ * @author wprinz
+ */
+public interface VerificationFilterParameters
+{
+
+ /**
+ * Tells the VerificationFilter to extract binary signatures only.
+ *
+ * <p>
+ * Not scanning for textual signatures allows the algorithm to skip text
+ * extraction and signature extraction, which are both time and memory
+ * intensive processes.
+ * </p>
+ *
+ * @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.
+ *
+ * <p>
+ * 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).
+ * </p>
+ * <p>
+ * This is equivalent to saying that there exists no Incremental Update block
+ * that would render a text signature before it invalid.
+ * </p>
+ * <p>
+ * 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.
+ * </p>
+ * <p>
+ * 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.
+ * </p>
+ * <p>
+ * 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.
+ * </p>
+ *
+ * @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.
+ *
+ * <p>
+ * The rest text is the text of the oldest text signature or the original
+ * document text if there is no text signature.
+ * </p>
+ *
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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 <code>true</code>: automatically registers IAIK JCE and ECC Provider;
+ * <code>false</code>: providers will NOT be automatically registered, providers
+ * needed have to be registered by the API user
+ * @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 <code>true</code>: automatically registers IAIK JCE and ECC Provider;
+ * <code>false</code>: providers will NOT be automatically registered, providers
+ * needed have to be registered by the API user
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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
+ * <code>correct_document_on_verify_if_necessary</code>). 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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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.<br/>
+ * e.g. properties starting with <code>sig_obj.PROFILE.key.</code> and
+ * properties of the form <code>sig_obj.PROFILE.table.TABLENAME.NUMBER</code>
+ * where <code>PROFILE</code> is the name of the current profile,
+ * <code>TABLENAME</code> is the name of a table and <code>NUMBER</code>
+ * is the number of the specific row within the table <code>TABLENAME</code>.
+ *
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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.
+ *
+ * <p>
+ * Note that holding the data in a byte array is very memory consuming for large
+ * documents.
+ * </p>
+ *
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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.
+ *
+ * <p>
+ * 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.
+ * </p>
+ *
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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.
+ *
+ * <p>
+ * Process.destroy after a certain timeout does not work if the executable is a
+ * Windows batch file.
+ * </p>
+ *
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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.
+ *
+ * <p>
+ * Note that this function is very memory intensive. Use the Streams whereever
+ * possible.
+ * </p>
+ *
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $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.
+ *
+ * <p>
+ * In prepareSign, an Incremental Update is created that contains the Signature
+ * block and the egiz dictionary. For formatting the layout, variable values are
+ * filled with placeholders. After the layout has been fixed, all variable
+ * fields (all holes in the byte ranges) are replaced with 0. This document is
+ * then base64 encoded and signed.
+ * </p>
+ * <p>
+ * In finishSign, the variable fields (values, /Cert) are replaced with the
+ * values according to the encoding.
+ * </p>
+ *
+ * @author wprinz
+ */
+public class BinarySignator_1_0_0 implements Signator {
+ // 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("&#252;")
+ || ri.value.contains("&#228;")
+ || ri.value.contains("&#246;")
+ || ri.value.contains("&#225;")
+ || ri.value.contains("&#223;")
+ || ri.value.contains("&#214;")
+ || ri.value.contains("&#224;")
+ || ri.value.contains("&#233;")
+ || ri.value.contains("&#250;") || ri.value
+ .contains("&#231;"))
+ && (ri.sfd.field_name
+ .equals(SignatureTypes.SIG_SUBJECT))) {
+ if (ri.value.contains("&#252;")) {
+ ri.sfd.value = ri.sfd.value.replace("&#252;", "�");
+ ri.value = ri.value.replace("&#252;", "�");
+ }
+ if (ri.value.contains("&#228;")) {
+ ri.sfd.value = ri.sfd.value.replace("&#228;", "�");
+ ri.value = ri.value.replace("&#228;", "�");
+ }
+ if (ri.value.contains("&#246;")) {
+ ri.sfd.value = ri.sfd.value.replace("&#246;", "�");
+ ri.value = ri.value.replace("&#246;", "�");
+ }
+ if (ri.value.contains("&#225;")) {
+ ri.sfd.value = ri.sfd.value.replace("&#225;", "�");
+ ri.value = ri.value.replace("&#225;", "�");
+ }
+ if (ri.value.contains("&#223;")) {
+ ri.sfd.value = ri.sfd.value.replace("&#223;", "�");
+ ri.value = ri.value.replace("&#223;", "�");
+ }
+ if (ri.value.contains("&#214;")) {
+ ri.sfd.value = ri.sfd.value.replace("&#214;", "�");
+ ri.value = ri.value.replace("&#214;", "�");
+ }
+ if (ri.value.contains("&#224;")) {
+ ri.sfd.value = ri.sfd.value.replace("&#224;", "�");
+ ri.value = ri.value.replace("&#224;", "�");
+ }
+ if (ri.value.contains("&#233;")) {
+ ri.sfd.value = ri.sfd.value.replace("&#233;", "�");
+ ri.value = ri.value.replace("&#233;", "�");
+ }
+ if (ri.value.contains("&#250;")) {
+ ri.sfd.value = ri.sfd.value.replace("&#250;", "�");
+ ri.value = ri.value.replace("&#250;", "�");
+ }
+ if (ri.value.contains("&#231;")) {
+ ri.sfd.value = ri.sfd.value.replace("&#231;", "�");
+ ri.value = ri.value.replace("&#231;", "�");
+ }
+ }*/
+ 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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $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.
+ *
+ * <p>
+ * 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.
+ * </p>
+ *
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $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.
+ *
+ * <p>
+ * In prepareSign, the document text is extracted and normalized.
+ * </p>
+ * <p>
+ * In finishSign, the signed SignatureObject is transformed into a Signature
+ * block, which is then written as an Incremental Update.
+ * </p>
+ *
+ * @author wprinz
+ */
+public class DetachedTextualSignator_1_0_0 extends TextualSignator_1_0_0
+{
+ /**
+ * 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;
+ }
+
+ // /**
+ // * <p>
+ // * The parameter has_SIG_ID is not used by this Signator because it doesn't
+ // * pre-format the signature block.
+ // * </p>
+ // *
+ // * @see at.knowcenter.wag.egov.egiz.framework.Signator#prepareSign(byte[],
+ // * String, TablePos, boolean)
+ // */
+ // 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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $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.
+ *
+ * <p>
+ * In prepareSign, the document text is extracted and normalized.
+ * </p>
+ * <p>
+ * In finishSign, the signed SignatureObject is transformed into a Signature
+ * block, which is then written as an Incremental Update.
+ * </p>
+ *
+ * @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.
+ }
+
+ /**
+ * <p>
+ * The parameter has_SIG_ID is not used by this Signator because it doesn't
+ * pre-format the signature block.
+ * </p>
+ *
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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<oldList.size(); j++) {
+
+ SignatureHolder currentOldSh = (SignatureHolder)oldList.get(j);
+
+ if(currentNewSh.getSignatureObject().getSignationValue().equals(currentOldSh.getSignatureObject().getSignationValue())) {
+
+ shAlreadyPresentInOldList = true;
+ pos = j;
+ }
+ }
+
+ if(!shAlreadyPresentInOldList) {
+
+ // signature holder has not been found earlier -> add
+ result.add(currentNewSh);
+ }
+
+ }
+
+
+ return;
+ }
+
+
+ protected List flattenOutTextPartitions (List partitions, List blocks)
+ {
+
+ List blockPartitions = new ArrayList(blocks.size());
+ Iterator it = partitions.iterator();
+ while (it.hasNext())
+ {
+ 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.
+ *
+ * <p>
+ * IU blocks without an egiz dict are not considered.
+ * </p>
+ *
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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.
+ *
+ * <p>
+ * According to definition, if a block is a binary block, it must/cannot
+ * contain other signatures than this one.
+ * </p>
+ *
+ * @param block
+ * The incremental update block.
+ * @return Returns true, if this block is a binary signature block, false
+ * 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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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.
+ *
+ * <p>
+ * A partition is a sequence of Incremental Update blocks of the same type.
+ * </p>
+ * <p>
+ * 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".
+ * </p>
+ *
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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.
+ *
+ * <p>
+ * Note that internally, this just calls the {@link ByteArrayOutputStream#toByteArray()} method.
+ * </p>
+ *
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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.<br/>
+ * 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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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.<br/>
+ * Searches only for the first placeholder page after page from top.
+ *
+ * @param inputStream
+ * @return all available info from the first found placeholder.
+ * @throws PDFDocumentException if the document could not be read.
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.utils;
+
+import 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 <a href="mailto:thomas.knall@egiz.gv.at">Thomas Knall</a>
+ */
+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 <code>true</code> an already existing configuration is overwritten. If <code>false</code> nothing is being copied if the destination folder already exists.
+ * @return <code>true</code> if the configuration has been deployed, <code>false</code> 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 <code>true</code> an already existing configuration is overwritten. If <code>false</code> nothing is being copied if the destination folder already exists.
+ * @return <code>true</code> if the configuration has been deployed, <code>false</code> 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 <code>true</code> an already existing configuration is overwritten. If <code>false</code> nothing is being copied if the destination folder already exists.
+ * @return <code>true</code> if the configuration has been deployed, <code>false</code> 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 <code>true</code> an already existing configuration is overwritten. If <code>false</code> nothing is being copied if the destination folder already exists.
+ * @return The folder the configuration has been extracted to or <code>null</code> 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
+ * <code>Constants.Constants.USERHOME_CONFIG_FOLDER</code>.
+ *
+ * @param overwriteExisting If set <code>true</code> an already existing configuration is overwritten. If <code>false</code> nothing is being copied if the destination folder already exists.
+ * @return The folder the configuration has been extracted to or <code>null</code> 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
+ * <code>Constants.Constants.USERHOME_CONFIG_FOLDER</code>.
+ *
+ * @return The folder the configuration has been extracted to or <code>null</code> 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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.utils;
+
+import 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.
+ *
+ * <p>
+ * Data hashes are useful for summarizing the signed data of signatures for
+ * debugging and testing purposes. Do not use these hashes for signatures.
+ * </p>
+ * <p>
+ * A data hash is always a Base64 encoded String.
+ * </p>
+ *
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.utils;
+
+import 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.
+ * <a href="http://www.opensymphony.com/ognl/">ognl website</a>
+ * @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 <tt>${expression}</tt>
+ *
+ * @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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.utils;
+
+import 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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.utils;
+
+/**
+ * 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 = "<pdfaid:part>";
+ String confMark = "<pdfaid:conformance>";
+ 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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.utils;
+
+import 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> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.utils;
+
+import 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.
+ *
+ * <p>
+ * If the directory doesn't exist, it is created.
+ * </p>
+ *
+ * @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.
+ *
+ * <p>
+ * This should be used to clear temporary files when the application shuts
+ * down.
+ * </p>
+ */
+ 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.
+ *
+ * <p>
+ * Reasonable means that the text is longer than a certain threshold.
+ * Otherwise a short text is simply held in memory.
+ * </p>
+ *
+ * @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.
+ *
+ * <p>
+ * If the DataSource is not FileBased, nothing is done.
+ * </p>
+ * <p>
+ * This is usually used by the application to delete temporary files.
+ * </p>
+ *
+ * @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();
+ }
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/PdfAS.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/PdfAS.java
new file mode 100644
index 0000000..c222259
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/PdfAS.java
@@ -0,0 +1,1575 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: PdfAS.java,v 1.5 2006/10/31 08:04:50 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
+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.analyze.NonTextObjectInfo;
+import at.gv.egiz.pdfas.api.commons.DynamicSignatureProfileImpl;
+import at.gv.egiz.pdfas.api.commons.SignatureInformation;
+import at.gv.egiz.pdfas.api.timestamp.TimeStamper;
+import at.gv.egiz.pdfas.api.verify.VerifyParameters;
+import at.gv.egiz.pdfas.api.xmldsig.ExtendedSignatureInformation;
+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.CorrectorException;
+import at.gv.egiz.pdfas.framework.ConnectorParameters;
+import at.gv.egiz.pdfas.framework.input.PdfDataSource;
+import at.gv.egiz.pdfas.framework.input.correction.Corrector;
+import at.gv.egiz.pdfas.framework.input.correction.CorrectorFactory;
+import at.gv.egiz.pdfas.framework.output.DataSink;
+import at.gv.egiz.pdfas.framework.signator.SignatorInformation;
+import at.gv.egiz.pdfas.impl.api.commons.PdfDataSourceAdapter;
+import at.gv.egiz.pdfas.impl.input.ByteArrayPdfDataSourceImpl;
+import at.gv.egiz.pdfas.impl.input.helper.DataSourceHelper;
+import at.gv.egiz.pdfas.utils.PDFASUtils;
+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.ConnectorFactoryException;
+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.framework.FoundBlock;
+import at.knowcenter.wag.egov.egiz.framework.FoundKey;
+import at.knowcenter.wag.egov.egiz.pdf.AbsoluteTextSignature;
+import at.knowcenter.wag.egov.egiz.pdf.BinarySignatureHolder;
+import at.knowcenter.wag.egov.egiz.pdf.ObjectExtractor;
+import at.knowcenter.wag.egov.egiz.pdf.PDFSignatureCreation;
+import at.knowcenter.wag.egov.egiz.pdf.PDFSignatureObject;
+import at.knowcenter.wag.egov.egiz.pdf.PDFUtilities;
+import at.knowcenter.wag.egov.egiz.pdf.PositioningInstruction;
+import at.knowcenter.wag.egov.egiz.pdf.SignatureHolder;
+import at.knowcenter.wag.egov.egiz.pdf.TablePos;
+import at.knowcenter.wag.egov.egiz.pdf.TextualSignature;
+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.SignatureObject;
+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.ConnectorChooser;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject;
+import at.knowcenter.wag.egov.egiz.sig.signatureobject.SignatureObjectHelper;
+import at.knowcenter.wag.egov.egiz.tools.Normalizer;
+import at.knowcenter.wag.exactparser.ParseDocument;
+import at.knowcenter.wag.exactparser.parsing.PDFUtils;
+import at.knowcenter.wag.exactparser.parsing.results.HeaderParseResult;
+
+import com.lowagie.text.Rectangle;
+import com.lowagie.text.pdf.PdfPTable;
+import com.lowagie.text.pdf.PdfReader;
+
+/**
+ * This class contains the major methods used by both, the commandline and the
+ * webapp, to perform signation and verification.
+ *
+ * @author wprinz
+ * @author mruhmer
+ */
+public abstract class PdfAS
+{
+//23.11.2010 changed by exthex - added method: verifyExtendedSignatureHolders(List extended_signature_info, String connectorType, boolean returnHashInputData, Date verificationTime)
+
+ /**
+ * The current version of the pdf-as library. This version string is logged on every invocation
+ * of the api or the web application.
+ */
+ public static final String PDFAS_VERSION = "3.2";
+
+ /**
+ * The key of the strict mode setting.
+ */
+ public static final String STRICT_MODE_KEY = "strict_mode";
+
+ /**
+ * The left/right border.
+ */
+ public static final float SIGNATURE_BORDER = 100f;
+
+ /**
+ * The top/bottom border.
+ */
+ public static final float SIGNATURE_MARGIN = 20f;
+
+ /**
+ * The Mime Type of a PDF document.
+ */
+ public static final String PDF_MIME_TYPE = "application/pdf";
+
+ public static final String CORRECT_DOCUMENT_IF_NECESSARY_KEY = "correct_document_if_necessary";
+
+ /**
+ * The logger definition.
+ */
+ private static final Log log = LogFactory.getLog(PdfAS.class);
+
+ /**
+ * Tells, if strict PDF checking the PDF version is enabled.
+ *
+ * @return Returns true, if incoming PDFs should be checked strictly.
+ */
+ public static boolean isStrictPdfChecking()
+ {
+ try
+ {
+ SettingsReader settings = SettingsReader.getInstance();
+ String strict_mode = settings.getSetting(STRICT_MODE_KEY, "false");
+ if (strict_mode.equals("true"))
+ {
+ return true;
+ }
+ }
+ catch (SettingsException e)
+ {
+ log.error(e.getMessage(), e);
+ }
+ return false;
+ }
+
+ /**
+ * Checks the version of the given PDF to be 1.4 or lower.
+ *
+ * <p>
+ * This scans the first 1000 bytes of the PDF for the pdf Header.
+ * </p>
+ *
+ * @param pdfDataSource
+ * The PDF.
+ * @return Returns true, if the given PDF is strict 1.4, false otherwise.
+ * @throws PDFDocumentException
+ * Forwarded exception.
+ */
+ public static boolean isPdf14(PdfDataSource pdfDataSource) throws PDFDocumentException
+ {
+ try
+ {
+ byte[] firstBytes = new byte[1000];
+ InputStream is = pdfDataSource.createInputStream();
+ is.read(firstBytes);
+ is.close();
+
+ HeaderParseResult hpr = PDFUtils.parseHeader(firstBytes, 0);
+
+ if (hpr.major <= 1 && hpr.minor <= 4)
+ {
+ return true;
+ }
+ return false;
+ }
+ catch (Exception e)
+ {
+ throw new PDFDocumentException(201, e);
+ }
+ }
+
+ /**
+ * Applies strict version mode on the PDF and throws an exception, if the pdf
+ * is not 1.4.
+ *
+ * <p>
+ * Furthermore (independently of strict mode) the PDF is checked for
+ * parsability.
+ * </p>
+ *
+ * @param pdfDataSource
+ * The pdf to be checked against strict mode.
+ * @throws PDFDocumentException
+ * @throws SettingsException
+ * @throws CorrectorException
+ */
+ public static PdfDataSource applyStrictMode(PdfDataSource pdfDataSource) throws PDFDocumentException, SettingsException, CorrectorException
+ {
+ if (isStrictPdfChecking())
+ {
+ if (!isPdf14(pdfDataSource))
+ {
+ throw new PDFDocumentException(201, "StrictMode: The pdf version is not 1.4 or lower.");
+ }
+ }
+ try
+ {
+ byte[] pdf = DataSourceHelper.convertDataSourceToByteArray(pdfDataSource);
+ ParseDocument.parseDocument(pdf);
+ }
+ catch (Exception e)
+ {
+ log.debug("Error while parsing Document.", e);
+
+ boolean tryToCorrect = SettingsReader.getInstance().getSetting(CORRECT_DOCUMENT_IF_NECESSARY_KEY, "false").equals("true");
+ if (!tryToCorrect)
+ {
+ throw new PDFDocumentException(201, e);
+ }
+ log.info("Correcting document...");
+ Corrector cor = CorrectorFactory.createCorrector();
+ PdfDataSource correctedDS = cor.correctDocument(pdfDataSource);
+ log.info("Correction finished.");
+
+ return correctedDS;
+ }
+
+ return pdfDataSource;
+ }
+
+ public static at.gv.egiz.pdfas.api.io.DataSource applyStrictMode (at.gv.egiz.pdfas.api.io.DataSource dataSource) throws PDFDocumentException, SettingsException, CorrectorException
+ {
+ if (dataSource.getMimeType().equals("application/pdf"))
+ {
+ PdfDataSource pdfDS = new PdfDataSourceAdapter(dataSource);
+ PdfDataSource correctedDS = applyStrictMode(pdfDS);
+ if (correctedDS != pdfDS)
+ {
+ return new at.gv.egiz.pdfas.impl.api.commons.DataSourceApiAdapter(correctedDS);
+ }
+ }
+ return dataSource;
+ }
+
+ // TODO: unused method - remove
+ // /**
+ // * Verifies the given PDF document.
+ // *
+ // * @param pdf
+ // * The PDF document.
+ // * @param connector
+ // * The connector.
+ // * @return Returns the List of results.
+ // * @throws PresentableException
+ // * Forwarded exception.
+ // */
+ // public static List verifyPdf(final byte[] pdf, final String connector)
+ // throws PresentableException
+ // {
+ // VerificationFilter vf = new VerificationFilter();
+ // List signature_holders = vf.extractSignaturesFromPdf(pdf);
+ // if (signature_holders.isEmpty())
+ // {
+ // throw new PDFDocumentException(206);
+ // }
+ //
+ // List results = verifySignatureHolders(signature_holders, connector);
+ //
+ // return results;
+ // }
+
+ // TODO: unused method - remove
+ // /**
+ // * Verifies the given text that is supposed to be extracted from a PDF
+ // * document using text extraction mechanisms.
+ // *
+ // * @param text
+ // * The text to be verified.
+ // * @param connector
+ // * The connecor.
+ // * @return Returns the List of results.
+ // * @throws PresentableException
+ // * Forwarded exception.
+ // */
+ // public static List verifyText(final String text, final String connector)
+ // throws PresentableException
+ // {
+ // VerificationFilter vf = new VerificationFilter();
+ // List signature_holders = vf.extractSignaturesFromPlainText(text);
+ // if (signature_holders.isEmpty())
+ // {
+ // throw new PDFDocumentException(206);
+ // }
+ //
+ // List results = verifySignatureHolders(signature_holders, connector);
+ //
+ // return results;
+ // }
+
+ /**
+ * Extracts all signature blocks from the given raw text using textual mode.
+ *
+ * @param raw_text
+ * The raw text.
+ * @return Returns a List of all SignatureHolders extracted from the text.
+ * @throws PDFDocumentException
+ * F.e.
+ * @throws SignatureException
+ * F.e.
+ * @throws SignatureTypesException
+ * @throws NormalizeException
+ */
+ public static List extractSignatureHoldersTextual(String raw_text, boolean old_style) throws PDFDocumentException, SignatureException, SignatureTypesException, NormalizeException
+ {
+ List signature_holders = new ArrayList();
+
+ String text = raw_text;
+ for (;;)
+ {
+ TextualSignatureHolder holder = extractSignatureHolderTextual(text, old_style);
+ if (holder == null)
+ {
+ break;
+ }
+ {
+ log.debug("Found holder: " + holder.getSignatureObject().getSignationType());
+ }
+ signature_holders.add(0, holder);
+
+ text = holder.getSignedText();
+ }
+
+ return signature_holders;
+ }
+
+ /**
+ * Extracts the last signature holder from the given text.
+ *
+ * @param raw_text
+ * @param old_style
+ * @return Returns the found singature holder, or null, if none could be
+ * found.
+ * @throws SignatureException
+ * @throws SignatureTypesException
+ * @throws NormalizeException
+ */
+ public static TextualSignatureHolder extractSignatureHolderTextual(String raw_text, boolean old_style) throws SignatureException, SignatureTypesException, NormalizeException
+ {
+ List signatureTypes_ = AbsoluteTextSignature.getSignatureTypesForTextAnalysis();
+
+ List found_blocks = new ArrayList();
+ for (int cur_type = 0; cur_type < signatureTypes_.size(); cur_type++)
+ {
+ SignatureTypeDefinition cur_std = (SignatureTypeDefinition) signatureTypes_.get(cur_type);
+
+ List found_keys = findBlockInText(raw_text, cur_std, old_style);
+ if (found_keys != null)
+ {
+ FoundBlock found_block = new FoundBlock();
+ found_block.found_keys = found_keys;
+ found_block.end_index = raw_text.length();
+ found_block.std = cur_std;
+ found_blocks.add(found_block);
+ }
+ }
+
+ List last_most_blocks = sortOutEarlyBlocks(found_blocks);
+
+ List minimum_blocks = sortOutLargeBlocks(last_most_blocks);
+
+ if (minimum_blocks.size() > 1)
+ {
+ log.debug("There are still " + minimum_blocks.size() + " candidates:");
+
+ for (int i = 0; i < minimum_blocks.size(); i++)
+ {
+ FoundBlock fb = (FoundBlock) minimum_blocks.get(i);
+ log.debug(" fb: " + fb.std.getType());
+ }
+
+ log.debug("... checking for Semantic Equality.");
+ }
+
+ boolean semantic_equality = checkForSemanticEquality(minimum_blocks);
+
+ if (minimum_blocks.size() > 1)
+ {
+ log.debug("... Semantic Equality = " + semantic_equality);
+ }
+
+ if (!semantic_equality)
+ {
+ throw new SignatureException(ErrorCode.NOT_SEMANTICALLY_EQUAL, "The found blocks are not semantically equal.");
+ }
+
+ if (!minimum_blocks.isEmpty())
+ {
+ FoundBlock actual_block = (FoundBlock) minimum_blocks.get(0);
+
+ String signed_text = raw_text.substring(0, actual_block.getFirstKey().start_index);
+
+ SignatureObject signatureObject_ = new SignatureObject();
+ signatureObject_.setSigType(actual_block.std.getType());
+ signatureObject_.initByType();
+
+ int end_index = actual_block.end_index;
+ for (int i = 0; i < actual_block.found_keys.size(); i++)
+ {
+ FoundKey cur_key = (FoundKey) actual_block.found_keys.get(i);
+ int start_index = cur_key.getStartIndex() + cur_key.caption.length();
+
+ String value = raw_text.substring(start_index, end_index);
+
+ signatureObject_.setSigValueCaption(cur_key.getKey(), value, cur_key.caption);
+
+ end_index = cur_key.getStartIndex();
+ }
+
+ // this normalization is required to get rid of possible trailing
+ // newlines.
+ String normalized_text = normalizeText(signed_text);
+ TextualSignatureHolder holder = new TextualSignatureHolder(normalized_text, signatureObject_);
+ return holder;
+ }
+
+ return null;
+ }
+
+ /**
+ * Tries to find a block of the given type in the text.
+ *
+ * @param text
+ * The text.
+ * @param sig_type_def
+ * The type of the block.
+ * @param old_style
+ * Tells, if the block is old style (SIG_KZ will be ignored), or if
+ * it is a new block.
+ * @return Returns a List of the found keys of the block, or null, if the
+ * block could not be found.
+ */
+ public static List findBlockInText(String text, SignatureTypeDefinition sig_type_def, boolean old_style)
+ {
+ Vector keys = sig_type_def.getRevertSortedKeys();
+ Vector captions = sig_type_def.getRevertSortedCaptions();
+
+ int last_index = text.length();
+ List found_keys = new ArrayList();
+ for (int key_idx = 0; key_idx < keys.size(); key_idx++)
+ {
+ String key = (String) keys.get(key_idx);
+ // logger_.debug("Key="+key);
+ if (old_style && key.equals(SignatureTypes.SIG_KZ))
+ {
+ // If separating the old style way - skip The "Kennzeichnung"
+ // key, because it wasn't present in old profiles.
+ continue;
+ }
+
+ String caption = (String) captions.get(key_idx);
+
+ // int found_index = text.lastIndexOf(caption);
+ // we're searching for captions that start at the beginning of the line.
+ int found_index = text.lastIndexOf("\n" + caption) + 1;// text.lastIndexOf("\n"
+ // + caption) + 1;
+ // // the +1
+ // text.lastIndexOf(caption)
+ // + 1; //
+ // compensates the
+ // \n
+ if (found_index == 0)
+ {
+ // try without /n
+ found_index = text.lastIndexOf(caption);
+
+ // fix #331 here ??
+ }
+ log.debug("found key:" + caption + " at index:" + found_index);
+ if (key.equals(SignatureTypes.SIG_ID))
+ {
+ if (found_index < 0 || found_index >= last_index)
+ {
+ // not found, SIG_ID is not required
+ continue;
+ }
+ FoundKey fk = new FoundKey(key, caption, found_index);
+ found_keys.add(fk);
+ }
+ else
+ {
+ if (found_index < 0 || found_index >= last_index)
+ {
+ // one key is not found - the profile doesn't match.
+ return null;
+ }
+
+ FoundKey fk = new FoundKey(key, caption, found_index);
+ found_keys.add(fk);
+ last_index = found_index;
+ }
+ }
+
+ sortFoundKeysDescendingly(found_keys);
+
+ boolean matched = checkThatOrderIsCorrectAndCorrectFoundKeys(found_keys, keys, old_style);
+ // boolean found_required = checkFoundRequiredKeys(found_keys, old_style);
+ // logger_.debug("KKKKKKKKKKmatched="+matched);
+ if (matched)
+ {
+ return found_keys;
+ }
+ return null;
+ }
+
+ /**
+ * Sorts the FoundKeys List descendingly according to the start indices of the
+ * found keys (the first found key in the list will have the highest start
+ * index, the second one the second highest and so forth).
+ *
+ * @param found_keys
+ * The List of FoundKey objects to be sorted.
+ */
+ public static void sortFoundKeysDescendingly(List found_keys)
+ {
+ // sort the found_keys according to their start pos reversely.
+
+ Collections.sort(found_keys, new Comparator() {
+ public int compare(Object arg0, Object arg1)
+ {
+ FoundKey fk0 = (FoundKey) arg0;
+ FoundKey fk1 = (FoundKey) arg1;
+ // sort reversely!
+ return fk1.start_index - fk0.start_index;
+ }
+ });
+ }
+
+ /**
+ * Sorts the FoundKeys List ascendingly according to the start indices of the
+ * found keys (the first found key in the list will have the lowest start
+ * index, the second one the second lowest and so forth).
+ *
+ * @param found_keys
+ * The List of FoundKey objects to be sorted.
+ */
+ public static void sortFoundKeysAscendingly(List found_keys)
+ {
+ // sort the found_keys according to their start pos.
+
+ Collections.sort(found_keys, new Comparator() {
+ public int compare(Object arg0, Object arg1)
+ {
+ FoundKey fk0 = (FoundKey) arg0;
+ FoundKey fk1 = (FoundKey) arg1;
+ return fk0.start_index - fk1.start_index;
+ }
+ });
+ }
+
+ /**
+ * Checks that the found keys are in correct order regarding SIG_ID as
+ * optional key.
+ *
+ * <p>
+ * If the SIG_ID key is misplaced, it will be removed from the found keys
+ * list.
+ * </p>
+ *
+ * @param found_keys
+ * The found keys ordered descendingly to their start position
+ * @param profile_keys
+ * The profile keys.
+ * @param old_style
+ * Tells, if SIG_KZ should be ignored, or not.
+ * @return Returns true, if the keys are correct.
+ */
+ public static boolean checkThatOrderIsCorrectAndCorrectFoundKeys(List found_keys, List profile_keys, boolean old_style)
+ {
+
+ int found_index = 0;
+ for (int profile_index = 0; profile_index < profile_keys.size(); profile_index++)
+ {
+ String key = (String) profile_keys.get(profile_index);
+
+ if (old_style && key.equals(SignatureTypes.SIG_KZ))
+ {
+ continue;
+ }
+
+ FoundKey found_key = (FoundKey) found_keys.get(found_index);
+
+ boolean match = key.equals(found_key.getKey());
+ if (match)
+ {
+ found_index++;
+ continue;
+ }
+
+ if (key.equals(SignatureTypes.SIG_ID))
+ {
+ continue;
+ }
+
+ // doesn't match
+ return false;
+ }
+
+ // remove all fields above the found_index - they are not correctly matched
+ // indices (should be only the ID
+ int size = found_keys.size();
+ for (int i = found_index; i < size; i++)
+ {
+ // this removes all (size - found_index) objects above found_index
+ found_keys.remove(found_index);
+ }
+
+ return true;
+ }
+
+ /**
+ * Sorts out early blocks and leaves only those at the bottom of the text.
+ *
+ * @param found_blocks
+ * The found blocks.
+ * @return Returns a list of the last blocks.
+ */
+ public static List sortOutEarlyBlocks(List found_blocks)
+ {
+ int last_most_index = Integer.MIN_VALUE;
+
+ List last_most_blocks = new ArrayList();
+ for (int block_index = 0; block_index < found_blocks.size(); block_index++)
+ {
+ FoundBlock block = (FoundBlock) found_blocks.get(block_index);
+
+ int this_last_index = block.getLastKey().start_index;
+ if (this_last_index < last_most_index)
+ {
+ // this block cannot be the last most block.
+ continue;
+ }
+ if (this_last_index == last_most_index)
+ {
+ last_most_blocks.add(block);
+ continue;
+ }
+ if (this_last_index > last_most_index)
+ {
+ last_most_blocks = new ArrayList();
+ last_most_blocks.add(block);
+ last_most_index = this_last_index;
+ }
+ }
+
+ return last_most_blocks;
+ }
+
+ /**
+ * Sorts out large blocks.
+ *
+ * @param found_blocks
+ * The found blocks.
+ * @return Returns a list of the smallest blocks.
+ */
+ public static List sortOutLargeBlocks(List found_blocks)
+ {
+ int last_min_size = Integer.MAX_VALUE;
+
+ List min_size_blocks = new ArrayList();
+ for (int block_index = 0; block_index < found_blocks.size(); block_index++)
+ {
+ FoundBlock block = (FoundBlock) found_blocks.get(block_index);
+
+ int size = block.getSize();
+
+ if (size > last_min_size)
+ {
+ // this block is larger
+ continue;
+ }
+ if (size == last_min_size)
+ {
+ min_size_blocks.add(block);
+ continue;
+ }
+ if (size < last_min_size)
+ {
+ min_size_blocks = new ArrayList();
+ min_size_blocks.add(block);
+ last_min_size = size;
+ }
+ }
+
+ return min_size_blocks;
+ }
+
+ /**
+ * Checks the list of blocks for semantic equality.
+ *
+ * @param found_blocks
+ * The list of found blocks.
+ * @return Returns true if all blocks are semantically equal.
+ */
+ public static boolean checkForSemanticEquality(List found_blocks)
+ {
+ if (found_blocks.size() <= 1)
+ {
+ return true;
+ }
+
+ for (int block_index = 0; block_index < found_blocks.size() - 1; block_index++)
+ {
+ FoundBlock first_block = (FoundBlock) found_blocks.get(block_index);
+ FoundBlock second_block = (FoundBlock) found_blocks.get(block_index + 1);
+
+ if (!first_block.isSemanticallyEqual(second_block))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public static int getIndexOfFoundKey(List found_keys, String key)
+ {
+ for (int i = 0; i < found_keys.size(); i++)
+ {
+ FoundKey fk = (FoundKey) found_keys.get(i);
+ if (fk.getKey().equals(key))
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public static boolean containsFoundKey(List found_keys, String key)
+ {
+ return getIndexOfFoundKey(found_keys, key) >= 0;
+ }
+
+ /**
+ * Checks the found keys for the required keys regarding the old style.
+ *
+ * @param found_keys
+ * The found keys.
+ * @param old_style
+ * Flag that tells, if KZ is not required.
+ * @return Returns true, if all required keys were found.
+ */
+ public static boolean checkFoundRequiredKeys(List found_keys, boolean old_style)
+ {
+ if (!containsFoundKey(found_keys, SignatureTypes.SIG_DATE))
+ {
+ return false;
+ }
+ if (!containsFoundKey(found_keys, SignatureTypes.SIG_ISSUER))
+ {
+ return false;
+ }
+ if (!containsFoundKey(found_keys, SignatureTypes.SIG_NUMBER))
+ {
+ return false;
+ }
+ if (!containsFoundKey(found_keys, SignatureTypes.SIG_VALUE))
+ {
+ return false;
+ }
+ if (!old_style && !containsFoundKey(found_keys, SignatureTypes.SIG_KZ))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ public static List verifySignatureHolders(List signature_holders, String connectorType, boolean returnHashInputData, Date verificationTime) throws PDFDocumentException, NormalizeException, SignatureException, ConnectorException, ConnectorFactoryException
+ {
+ List results = new ArrayList();
+ for (int i = 0; i < signature_holders.size(); i++)
+ {
+ SignatureHolder holder = (SignatureHolder) signature_holders.get(i);
+
+ // logger_.debug();
+ // logger_.debug();
+ // logger_.debug("Verifying Holder " + i + "...");
+ // logger_.debug("holder[" + i + "].signed_text = " +
+ // holder.signed_text);
+ // logger_.debug("holder[" + i + "].sig_obj = ");
+ // logger_.debug("holder[" + i + "].type = " +
+ // (holder.signature_object.isTextual() ? "textual" : "binary"));
+ // logger_.debug(holder.signature_object.toString());
+
+ SignatureResponse result = verify(holder, connectorType, returnHashInputData, verificationTime, null);
+ results.add(result);
+
+ // logger_.debug();
+ // logger_.debug("check[" + i + "].cert = " +
+ // result.getCertificateCheckInfo());
+ // logger_.debug("check[" + i + "].sig = " +
+ // result.getSignatureCheckInfo().trim());
+ // logger_.debug("check[" + i + "].manifest = " +
+ // result.getSignatureManifestCheckInfo());
+ // logger_.debug();
+ }
+ return results;
+ }
+
+ /**
+ * Verify a list of signatures
+ *
+ * @param extended_signature_info a list of {@link ExtendedSignatureInformation} to be verified
+ * @param connectorType the connector to use for verification
+ * @param returnHashInputData
+ * @param verificationTime
+ * @param verifySignatureAtIndex only verify the signature at the given index in the extended_signature_info list. A value < 0 means to verify all signatures in the list.
+ * @return a list of {@link SignatureResponse}s
+ * @throws PDFDocumentException
+ * @throws NormalizeException
+ * @throws SignatureException
+ * @throws ConnectorException
+ * @throws ConnectorFactoryException
+ */
+ public static List verifyExtendedSignatureHolders(List extended_signature_info, String connectorType, boolean returnHashInputData, Date verificationTime, int verifySignatureAtIndex) throws PDFDocumentException, NormalizeException, SignatureException, ConnectorException, ConnectorFactoryException
+ {
+ List results = new ArrayList();
+ for (int i = 0; i < extended_signature_info.size(); i++)
+ {
+ if (verifySignatureAtIndex < 0 || verifySignatureAtIndex == i)
+ {
+ ExtendedSignatureInformation sigInfo = (ExtendedSignatureInformation) extended_signature_info.get(i);
+ SignatureInformation si = sigInfo.getSignatureInformation();
+ SignatureHolder holder = (SignatureHolder) si.getInternalSignatureInformation();
+
+ SignatureResponse result = verify(holder, connectorType, returnHashInputData, verificationTime, sigInfo.getXmlDsigData());
+ results.add(result);
+ }
+ }
+ return results;
+ }
+
+ /**
+ * Verifies a SignatureHolder using the given connector.
+ *
+ * @param signature_holder
+ * The SignatureHolder to be verified.
+ * @param connector
+ * The connector.
+ * @return Returns the SignatureResponse object.
+ * @throws NormalizeException
+ * F.e.
+ * @throws PDFDocumentException
+ * F.e.
+ * @throws SignatureException
+ * F.e.
+ * @throws ConnectorException
+ * @throws ConnectorFactoryException
+ */
+ public static SignatureResponse verify(SignatureHolder signature_holder, String connectorType, boolean returnHashInputData, Date verificationTime, XMLDsigData dsig) throws NormalizeException, PDFDocumentException, SignatureException, ConnectorException, ConnectorFactoryException
+ {
+ // String text_to_be_verified = signature_holder.getSignedText();
+ // logger_.debug("verify text_to_be_verified"+text_to_be_verified);
+ SignatureObject so_to_be_verified = signature_holder.getSignatureObject();
+
+ // if (text_to_be_verified == null)
+ // {
+ // throw new SignatureException(311, "Document can not be verified because
+ // the text to be verified is either null.");
+ // }
+ // if (text_to_be_verified.length() <= 0)
+ // {
+ // throw new SignatureException(311, "Document can not be verified because
+ // the length of the text to be verified is 0. (length = " +
+ // text_to_be_verified.length() + ")");
+ // }
+
+ if (so_to_be_verified == null)
+ {
+ throw new SignatureException(312, "Document can not be verified because no signature object are set.");
+ }
+
+ // fixed by tknall
+ if (so_to_be_verified.getX509Cert() == null)
+ {
+ throw new SignatureException(ErrorCode.CERTIFICATE_NOT_FOUND, "Document certificate is not defined.");
+ }
+
+ SignSignatureObject so = SignatureObjectHelper.convertSignatureObjectToSignSignatureObject(so_to_be_verified);
+ SignatureData sd = convertSignatureHolderToSignatureData(signature_holder);
+
+ String profile = so_to_be_verified.getSignatureTypeDefinition().getType();
+// Connector c = ConnectorChooser.chooseCommandlineConnectorForVerify(connector, so_to_be_verified.getKZ(), so.id, profile);
+ String connectorId = CommandlineConnectorChooser.chooseCommandlineConnectorForVerify(connectorType, so_to_be_verified.getKZ(), so.id, profile);
+
+ ConnectorParameters cp = new ConnectorParameters();
+ cp.setProfileId(profile);
+ cp.setReturnHashInputData(returnHashInputData);
+ cp.setVerificationTime(verificationTime);
+ Connector c = at.gv.egiz.pdfas.framework.ConnectorFactory.createConnector(connectorId, cp);
+
+ return executeVerify(dsig, so, sd, c);
+ }
+
+ private static SignatureResponse executeVerify(XMLDsigData dsig, SignSignatureObject so,
+ SignatureData sd, Connector c) throws ConnectorException {
+ SignatureResponse res = null;
+ try {
+ return c.doVerify(sd, so, dsig);
+ } catch (ConnectorException e) {
+ if (VerifyParameters.isSuppressVerifyExceptions()) {
+ res = new SignatureResponse();
+ res.setVerificationImpossibleEx(e);
+ } else {
+ throw e;
+ }
+ }
+ return res;
+ }
+
+ public static SignatureResponse verifyWeb(SignatureHolder signature_holder, String connector, String loc_ref) throws NormalizeException, PDFDocumentException, SignatureException, ConnectorException
+ {
+ // String text_to_be_verified = signature_holder.getSignedText();
+ // logger_.debug("verify text_to_be_verified"+text_to_be_verified);
+ SignatureObject so_to_be_verified = signature_holder.getSignatureObject();
+
+ // if (text_to_be_verified == null)
+ // {
+ // throw new SignatureException(311, "Document can not be verified because
+ // the text to be verified is either null.");
+ // }
+ // if (text_to_be_verified.length() <= 0)
+ // {
+ // throw new SignatureException(311, "Document can not be verified because
+ // the length of the text to be verified is 0. (length = " +
+ // text_to_be_verified.length() + ")");
+ // }
+
+ if (so_to_be_verified == null)
+ {
+ throw new SignatureException(312, "Document can not be verified because no signature object are set.");
+ }
+
+ // added by tknall
+ if (so_to_be_verified.getX509Cert() == null)
+ {
+ throw new SignatureException(ErrorCode.CERTIFICATE_NOT_FOUND, "Document certificate is not defined.");
+ }
+
+
+ SignSignatureObject so = SignatureObjectHelper.convertSignatureObjectToSignSignatureObject(so_to_be_verified);
+ SignatureData sd = convertSignatureHolderToSignatureData(signature_holder);
+
+ String profile = so_to_be_verified.getSignatureTypeDefinition().getType();
+ Connector c = ConnectorChooser.chooseWebConnectorForVerify(connector, so_to_be_verified.getKZ(), so.id, profile, loc_ref);
+
+ return executeVerify(null, so, sd, c);
+
+ }
+
+ public static SignatureData convertSignatureHolderToSignatureData(SignatureHolder signature_holder)
+ {
+ SignatureData sd = null;
+ if (signature_holder instanceof BinarySignatureHolder)
+ {
+ BinarySignatureHolder bsh = (BinarySignatureHolder) signature_holder;
+ sd = new SignatureDataImpl(bsh.getDataSource(), "application/pdf");
+ }
+ else
+ {
+ TextualSignatureHolder tsh = (TextualSignatureHolder)signature_holder;
+ sd = new SignatureDataImpl(tsh.getDataSource(), "text/plain", "UTF-8");
+ }
+ return sd;
+ }
+
+ /**
+ * Signs the given text with the provided connector using the given signature
+ * type.
+ *
+ * @param data_to_sign
+ * The data to be signed.
+ * @param signature_type
+ * The type of the signature.
+ * @param connector
+ * The connector.
+ * @return Returns the corresponding SignatureObject.
+ * @throws SignatureException
+ * F.e.
+ * @throws PDFDocumentException
+ * F.e.
+ * @throws ConnectorException
+ */
+ public static SignSignatureObject sign(final SignatureData data_to_sign, final Connector connector, final TimeStamper timeStamper) throws SignatureException, PDFDocumentException, ConnectorException
+ {
+// if (data_to_sign == null || data_to_sign.getData() == null)
+// {
+// throw new SignatureException(301, "Signature can not be produced. Data is null."); //$NON-NLS-1$
+// }
+ // if (data_to_sign.getData().length <= 0)
+ // {
+ // throw new SignatureException(301, "Signature can not be produced. Data is
+ // empty. (length = " + data_to_sign.getData().length + ")"); //$NON-NLS-1$
+ // //$NON-NLS-2$
+ // }
+
+ SignSignatureObject signed_signature_object = connector.doSign(data_to_sign);
+
+ // call timestamper if available
+ if (timeStamper != null) {
+ log.debug("execute timestamping with stamper: " + timeStamper.getClass());
+ signed_signature_object.sigTimeStamp = timeStamper.applyTimeStamp(signed_signature_object.getSignatureValue());
+ }
+
+ return signed_signature_object;
+ }
+
+ /**
+ * Helper method that creates a SignatureObject and initializes it with the
+ * given type.
+ *
+ * @param signature_type
+ * The type.
+ * @return Returns the created SignatureObject.
+ * @throws SignatureException
+ * f.e.
+ * @throws SignatureTypesException
+ * f.e.
+ */
+ public static SignatureObject createSignatureObjectFromType(final String signature_type) throws SignatureException, SignatureTypesException
+ {
+ SignatureObject sig_obj = new SignatureObject();
+ sig_obj.setSigType(signature_type);
+ sig_obj.initByType();
+
+ return sig_obj;
+ }
+
+// /**
+// * @deprecated moved to Main.processSign use signCommandline instead
+// * @param pdfDataSource
+// * @param dataSink
+// * @param signatorId
+// * @param connectorType
+// * @param profile
+// * @param pos
+// * @throws PresentableException
+// */
+// public static void sign(PdfDataSource pdfDataSource, DataSink dataSink, PdfASID signatorId, final String connectorType, final String profile, TablePos pos) throws PresentableException
+// {
+//// //Signator signator = SignatorFactory.createSignator(algorithm);
+//// at.gv.egiz.pdfas.framework.signator.Signator signator = at.gv.egiz.pdfas.framework.SignatorFactory.createSignator(algorithm);
+////
+//// //IncrementalUpdateInformation iui = signator.prepareSign(pdfDataSource, signature_type, pos, ConnectorFactory.needsSIG_ID(connector));
+//// SignatorInformation si = signator.prepareSign(pdfDataSource, signature_type, pos, ConnectorFactory.needsSIG_ID(connector));
+//
+// // Connector c = ConnectorChooser.chooseCommandlineConnectorForSign(connector, signature_type);
+//
+//// SignSignatureObject sso = sign(si.getSignatureData(), c);
+////
+//// si.setSignSignatureObject(sso);
+////
+//// signator.finishSign(si, dataSink);
+//
+// String connectorId = CommandlineConnectorChooser.chooseCommandlineConnectorForSign(connectorType);
+//
+// signCommandline(pdfDataSource, dataSink, signatorId, connectorId, profile, pos);
+// }
+
+ public static SignatorInformation signCommandline(PdfDataSource pdfDataSource, DataSink dataSink, PdfASID signatorId, String connectorId, final String profile, final String signatureKeyIdentifier, TablePos pos, TimeStamper timeStamper, Properties overrideProps) throws PresentableException
+ {
+ try {
+ at.gv.egiz.pdfas.framework.signator.Signator signator = at.gv.egiz.pdfas.framework.SignatorFactory.createSignator(signatorId);
+ if (overrideProps != null) {
+ OverridePropertyHolder.setOverrideProps(overrideProps);
+ }
+
+ ConnectorParameters cp = new ConnectorParameters();
+ cp.setProfileId(profile);
+ cp.setSignatureKeyIdentifier(signatureKeyIdentifier);
+ Connector c = at.gv.egiz.pdfas.framework.ConnectorFactory.createConnector(connectorId, cp);
+
+ // SignatorInformation si = signator.prepareSign(pdfDataSource, profile, pos, ConnectorFactory.needsSIG_ID(connector));
+ SignatorInformation si = signator.prepareSign(pdfDataSource, profile, pos, timeStamper);
+
+ SignSignatureObject sso = sign(si.getSignatureData(), c, timeStamper);
+
+ si.setSignSignatureObject(sso);
+
+ signator.finishSign(si, dataSink);
+
+ return si;
+ } finally {
+ OverridePropertyHolder.removeProperties();
+ DynamicSignatureProfileImpl.disposeLocalProfile();
+ }
+ }
+
+ public static SignatorInformation signCommandline(PdfDataSource pdfDataSource, DataSink dataSink, PdfASID signatorId, String connectorId, final String profile, TablePos pos) throws PresentableException {
+ return signCommandline(pdfDataSource, dataSink, signatorId, connectorId, profile, null, pos, null, null);
+ }
+
+ /**
+ * Extracts and normalizes the text from the pdf.
+ *
+ * @param pdf
+ * The PDF document.
+ * @return Returns the text String.
+ * @throws PresentableException
+ * F.e.
+ */
+// public static String extractNormalizedTextTextual(final byte[] pdf) throws PresentableException
+// {
+// // ByteArrayInputStream bais = new ByteArrayInputStream(pdf);
+// // String raw_document_text = TextualSignature.extractTextTextual(bais);
+// //
+// // String document_text = normalizeText(raw_document_text);
+//
+// return extractNormalizedTextTextual(pdf, pdf.length);
+// }
+
+
+ /**
+ *
+ * @param pdfDs
+ * @return List of {@link NonTextObjectInfo}
+ */
+ public static List extractNonTextualObjects(PdfDataSource pdfDs) {
+ return ObjectExtractor.extractNonTextInfo(pdfDs);
+ }
+
+
+ /**
+ * @deprecated
+ * Use version with explicit encoding {@link PdfAS#extractNormalizedTextTextual(PdfDataSource, String)}.
+ * This one uses cp1252.
+ *
+ * @param pdfDataSource
+ * @return
+ * @throws PresentableException
+ */
+ public static String extractNormalizedTextTextual(PdfDataSource pdfDataSource) throws PresentableException {
+ return extractNormalizedTextTextual(pdfDataSource, "cp1252");
+
+ }
+
+ public static String extractNormalizedTextTextual(PdfDataSource pdfDataSource, String encoding) throws PresentableException
+ {
+ String raw_document_text = TextualSignature.extractTextTextual(pdfDataSource, encoding);
+ String document_text = normalizeText(raw_document_text);
+ return document_text;
+ }
+ /**
+ @deprecated
+ */
+ public static String extractNormalizedTextTextual(byte [] pdf, int length) throws PresentableException
+ {
+ ByteArrayPdfDataSourceImpl pdfDataSource = new ByteArrayPdfDataSourceImpl(pdf, length);
+ String raw_document_text = TextualSignature.extractTextTextual(pdfDataSource, "cp1252");
+ String document_text = normalizeText(raw_document_text);
+ return document_text;
+ }
+
+// public static String extractNormalizedTextTextual(InputStream pdfInputStream, int length) throws PresentableException
+// {
+// DelimitedInputStream dis = new DelimitedInputStream(pdfInputStream, length);
+// String raw_document_text = TextualSignature.extractTextTextual(dis);
+// String document_text = normalizeText(raw_document_text);
+// return document_text;
+// }
+// /**
+// * Extracts and normalizes the text from the pdf.
+// *
+// * @param pdf
+// * The PDF document.
+// * @param length
+// * The length of the PDF document. The decument is considered to be
+// * that long even if the byte array is longer.
+// * @return Returns the text String.
+// * @throws PresentableException
+// * F.e.
+// */
+// public static String extractNormalizedTextTextual(final byte[] pdf, final int length) throws PresentableException
+// {
+// ByteArrayInputStream bais = new ByteArrayInputStream(pdf, 0, length);
+// String raw_document_text = TextualSignature.extractTextTextual(bais);
+// // logger_.info("extractNormalizedTextTextual
+// // raw_document_text="+raw_document_text);
+// String document_text = normalizeText(raw_document_text);
+// // logger_.info("extractNormalizedTextTextual document_text
+// // ="+document_text);
+// return document_text;
+// }
+
+ /**
+ * Normalizes the given text.
+ *
+ * @param text
+ * The text to be normalized.
+ * @return Returns the normalized text.
+ * @throws NormalizeException
+ * F.e.
+ */
+ public static String normalizeText(final String text) throws NormalizeException
+ {
+ Normalizer normalizer = new Normalizer();
+ String normalized_text = normalizer.normalize(text, false);
+ // fix #331 ??
+ //normalized_text = normalized_text.replaceAll("\n", "");
+ return normalized_text;
+ }
+
+ /**
+ * Creates the iText PDFPTable from a given SignatureObject.
+ *
+ * @param signature_object
+ * The SignatureObject.
+ * @return Returns the created PDFPTable.
+ * @throws PDFDocumentException
+ * F.e.
+ * @throws SignatureException
+ * F.e.
+ */
+ public static PdfPTable createPdfPTableFromSignatureObject(final SignatureObject signature_object) throws PDFDocumentException, SignatureException
+ {
+ PDFSignatureCreation creation = new PDFSignatureCreation(signature_object);
+ PDFSignatureObject pdf_sig_obj = creation.getPDFSignatureObject();
+ PdfPTable pdf_table = (PdfPTable) pdf_sig_obj.getSignatureObject();
+
+ return pdf_table;
+ }
+
+ /**
+ * Evalutates absolute positioning and prepares the PositioningInstruction for
+ * placing the table.
+ *
+ * @param pos
+ * The absolute positioning parameter. If null it is sought in the
+ * profile definition.
+ * @param signature_type
+ * The profile definition of the table to be written.
+ * @param pdf
+ * The pdf.
+ * @param pdf_table
+ * The pdf table to be written.
+ * @return Returns the PositioningInformation.
+ * @throws PDFDocumentException
+ * F.e.
+ * @throws SettingsException
+ * F.e.
+ */
+ public static PositioningInstruction determineTablePositioning(TablePos pos, String signature_type, PdfDataSource pdfDataSource, PdfPTable pdf_table) throws PDFDocumentException, SettingsException
+ {
+ if (pos == null)
+ {
+ String pos_string = SettingsReader.getInstance().getSetting(SignatureTypes.SIG_OBJ + signature_type + ".pos", null);
+ if (pos_string != null)
+ {
+ pos = PdfAS.parsePositionFromPosString(pos_string);
+ }
+ }
+ if (pos == null)
+ {
+ // The default algorithm. x,y,w =auto ,p=lastpage, f:ignored because
+ // y:auto
+ pos = new TablePos();
+ }
+ // System.out.println("Tablepos="+pos);
+ return PdfAS.adjustSignatureTableandCalculatePosition(pdfDataSource, pdf_table, pos);
+ }
+
+ /**
+ * Sets the width of the table according to the layout of the document and
+ * calculates the y position where the PDFPTable should be placed.
+ *
+ * @param pdf
+ * The PDF document.
+ * @param pdf_table
+ * The PDFPTable to be placed.
+ * @return Returns the position where the PDFPTable should be placed.
+ * @throws PDFDocumentException
+ * F.e.
+ */
+ public static PositioningInstruction adjustSignatureTableandCalculatePosition(final PdfDataSource pdfDataSource, PdfPTable pdf_table, TablePos pos) throws PDFDocumentException
+ {
+ // first check pageinstruction in TablePos-object
+ // new,auto,absolut
+ PdfReader reader = readInPdfDocument(pdfDataSource);
+ PDFASUtils.checkReaderPermissions(reader);
+ // get pages of currentdocument
+ int doc_pages = reader.getNumberOfPages();
+ int page = doc_pages;
+ boolean make_new_page = pos.isNewPage();
+ if (!(pos.isNewPage() || pos.isPauto()))
+ {
+ // we should posit signaturtable on this page
+
+ page = pos.getPage();
+ // System.out.println("XXXXPAGE="+page+" doc_pages="+doc_pages);
+ if (page > doc_pages)
+ {
+ make_new_page = true;
+ page = doc_pages;
+ // throw new PDFDocumentException(227, "Page number is to big(=" + page+
+ // ") cannot be parsed.");
+ }
+ }
+
+ // getPagedimensions
+ Rectangle psize = reader.getPageSizeWithRotation(page);
+ int page_rotation = reader.getPageRotation(page);
+
+// [tknall] for iText 1.x.x:
+// float page_width = psize.width();
+// float page_height = psize.height();
+
+// [tknall] for iText 2.x.x:
+// float page_width = psize.getWidth();
+// float page_height = psize.getHeight();
+
+ float page_width = psize.getWidth();
+ float page_height = psize.getHeight();
+
+ // now we can calculate x-position
+ float pre_pos_x = SIGNATURE_BORDER / 2;
+ if (!pos.isXauto())
+ {
+ // we do have absolute x
+ pre_pos_x = pos.getPosX();
+ }
+ // calculate width
+ // center
+ float pre_width = page_width - pre_pos_x - pre_pos_x;
+ if (!pos.isWauto())
+ {
+ // we do have absolute width
+ pre_width = pos.getWidth();
+ if (pos.isXauto())
+ { // center x
+ pre_pos_x = (page_width - pre_width) / 2;
+ }
+ }
+ final float pos_x = pre_pos_x;
+ final float width = pre_width;
+ // Signatur table dimensions are complete
+ pdf_table.setTotalWidth(width);
+ pdf_table.setLockedWidth(true);
+ final float table_height = pdf_table.getTotalHeight();
+ // now check pos_y
+ float pos_y = pos.getPosY();
+ if (!pos.isYauto())
+ {
+ // we do have y-position too --> all parameters but page ok
+ if (make_new_page)
+ {
+ page++;
+ }
+ return new PositioningInstruction(make_new_page, page, pos_x, pos_y);
+ }
+ // pos_y is auto
+ if (make_new_page)
+ {
+ // ignore footer in new page
+ page++;
+ pos_y = page_height - SIGNATURE_BORDER / 2;
+ return new PositioningInstruction(make_new_page, page, pos_x, pos_y);
+ }
+ // up to here no checks have to be made if Tablesize and Pagesize are fit
+ // Now we have to getfreespace in page and reguard footerline
+ float footer_line = pos.getFooterLine();
+ float pre_page_length = PDFUtilities.calculatePageLength(pdfDataSource, page - 1, page_height - footer_line, page_rotation);
+ if (pre_page_length == Float.NEGATIVE_INFINITY)
+ {
+ // we do have an empty page or nothing in area above footerline
+ pre_page_length = page_height;
+ // no text --> SIGNATURE_BORDER
+ pos_y = page_height - SIGNATURE_BORDER / 2;
+ if (pos_y - footer_line <= table_height)
+ {
+ make_new_page = true;
+ if (!pos.isPauto())
+ {
+ // we have to correct pagenumber
+ page = reader.getNumberOfPages();
+ }
+ page++;
+ // no text --> SIGNATURE_BORDER
+ pos_y = page_height - SIGNATURE_BORDER / 2;
+ }
+ return new PositioningInstruction(make_new_page, page, pos_x, pos_y);
+ }
+ final float page_length = pre_page_length;
+ // we do have text take SIGNATURE_MARGIN
+ pos_y = page_height - page_length - SIGNATURE_MARGIN;
+ if (pos_y - footer_line <= table_height)
+ {
+ make_new_page = true;
+ if (!pos.isPauto())
+ {
+ // we have to correct pagenumber in case of absolute page and not enough
+ // space
+ page = reader.getNumberOfPages();
+ }
+ page++;
+ // no text --> SIGNATURE_BORDER
+ pos_y = page_height - SIGNATURE_BORDER / 2;
+ }
+ return new PositioningInstruction(make_new_page, page, pos_x, pos_y);
+ }
+
+// /**
+// * Sets the width of the table according to the layout of the document and
+// * calculates the y position where the PDFPTable should be placed.
+// *
+// * @deprecated
+// * @param pdf
+// * The PDF document.
+// * @param pdf_table
+// * The PDFPTable to be placed.
+// * @return Returns the position where the PDFPTable should be placed.
+// * @throws PDFDocumentException
+// * F.e.
+// */
+// public static PositioningInstruction adjustTableAndCalculatePosition(final byte[] pdf, PdfPTable pdf_table) throws PDFDocumentException
+// {
+// boolean make_new_page = false;
+//
+// PdfReader reader = readInPdfDocument(pdf);
+//
+// int page = reader.getNumberOfPages();
+// Rectangle psize = reader.getPageSizeWithRotation(page);
+// float page_width = psize.width();
+// float page_height = psize.height();
+//
+// final float width = page_width - SIGNATURE_BORDER;
+// pdf_table.setTotalWidth(width);
+// pdf_table.setLockedWidth(true);
+//
+// final float pos_x = SIGNATURE_BORDER / 2;
+//
+// final float table_height = pdf_table.getTotalHeight();
+// final float page_length = PDFUtilities.calculateLastPageLength(pdf, page_height);
+// float pos_y = page_height - page_length - SIGNATURE_MARGIN;
+//
+// if (pos_y <= table_height)
+// {
+// make_new_page = true;
+// page++;
+//
+// pos_y = page_height - SIGNATURE_BORDER / 2;
+// }
+//
+// return new PositioningInstruction(make_new_page, page, pos_x, pos_y);
+// }
+
+// /**
+// * Sets the width of the table according to the layout of the document and
+// * calculates the y position where the PDFPTable should be placed.
+// *
+// * <p>
+// * This algorithm tries to position the table between the end of the text and
+// * the footer line.
+// * </p>
+// *
+// * @deprecated
+// * @param pdf
+// * The PDF document.
+// * @param pdf_table
+// * The PDFPTable to be placed.
+// * @return Returns the position where the PDFPTable should be placed.
+// * @throws PDFDocumentException
+// * F.e.
+// */
+// public static PositioningInstruction adjustTableAndCalculatePositionRegardingFooter(final byte[] pdf, PdfPTable pdf_table, float footer_line) throws PDFDocumentException
+// {
+// boolean make_new_page = false;
+//
+// PdfReader reader = readInPdfDocument(pdf);
+//
+// int page = reader.getNumberOfPages();
+// Rectangle psize = reader.getPageSizeWithRotation(page);
+// float page_width = psize.width();
+// float page_height = psize.height();
+//
+// final float width = page_width - SIGNATURE_BORDER;
+// pdf_table.setTotalWidth(width);
+// pdf_table.setLockedWidth(true);
+//
+// final float pos_x = SIGNATURE_BORDER / 2;
+//
+// final float table_height = pdf_table.getTotalHeight();
+//
+// final float page_length = PDFUtilities.calculateLastPageLength(pdf, page_height - footer_line);
+// float pos_y = page_height - page_length - SIGNATURE_MARGIN;
+//
+// if (pos_y - footer_line <= table_height)
+// {
+// make_new_page = true;
+// page++;
+//
+// pos_y = page_height - SIGNATURE_BORDER / 2;
+// }
+//
+// return new PositioningInstruction(make_new_page, page, pos_x, pos_y);
+// }
+
+ /**
+ * Creates an iText Reader that parses the document.
+ * <p>
+ * This is a convenience function for wrapping the Reader's exceptions into
+ * PDFDocumentException.
+ * </p>
+ *
+ * @param pdf
+ * The PDF document.
+ * @return Returns the created PdfReader.
+ * @throws PDFDocumentException
+ * F.e.
+ */
+ public static PdfReader readInPdfDocument(final PdfDataSource pdfDataSource) throws PDFDocumentException
+ {
+ try
+ {
+ //InputStream is = pdfDataSource.createInputStream();
+ // PERF: byte array instead of stream
+ byte [] pdf_data = pdfDataSource.getAsByteArray();
+ PdfReader reader = new PdfReader(pdf_data);
+ //is.close();
+ return reader;
+ }
+ catch (IOException e)
+ {
+ throw new PDFDocumentException(201, e);
+ }
+ }
+
+ /**
+ * Parses the TablePos object from a given String with the appropriate format.
+ *
+ * @param pos_string
+ * The pos string. e.g. x:40.0;y:auto;w:auto;p:1;f:300.0
+ * @return Returns the parsed TablePos object.
+ * @throws PDFDocumentException
+ * Thrown, if the String doesn't have the proper format.
+ */
+ public static TablePos parsePositionFromPosString(String pos_string) throws PDFDocumentException
+ {
+ TablePos pos = new TablePos(pos_string);
+ return pos;
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/PdfASID.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/PdfASID.java
new file mode 100644
index 0000000..ef9cb87
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/PdfASID.java
@@ -0,0 +1,222 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: PdfASID.java,v 1.1 2006/08/25 17:04:16 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz;
+
+import java.io.Serializable;
+
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.knowcenter.wag.egov.egiz.exceptions.InvalidIDException;
+import at.knowcenter.wag.egov.egiz.framework.SignatorFactory;
+
+/**
+ * This class encapsulates the Pdf-AS ID ("Kennzeichnung") urn.
+ *
+ * @author wprinz
+ */
+public class PdfASID implements Serializable
+{
+
+ /**
+ * SVUID.
+ */
+ private static final long serialVersionUID = 4776635173830445739L;
+
+ /**
+ * The urn word that leads in the identifier.
+ */
+ protected static final String URN = "urn";
+
+ /**
+ * The namespace of the urn.
+ */
+ protected static final String NAMESPACE = "pdfsigfilter";
+
+ /**
+ * The separator between urn blocks.
+ */
+ protected static final String SPLIT_STRING = ":";
+
+ /**
+ * The vendor.
+ */
+ protected String vendor = null;
+
+ /**
+ * The algorithm type.
+ */
+ protected String type = null;
+
+ /**
+ * The version of the algorithm.
+ */
+ protected String version = null;
+
+ /**
+ * Constructor that fills in the parameters directly.
+ *
+ * @param vendor
+ * @param type
+ * @param version
+ */
+ public PdfASID(String vendor, String type, String version)
+ {
+ set(vendor, type, version);
+ }
+
+ /**
+ * Parses the given id String and throws an Exception if it is not valid.
+ *
+ * @param id
+ * The id String to be parsed.
+ */
+ public PdfASID(String id) throws InvalidIDException
+ {
+ String[] tokens = id.split(SPLIT_STRING);
+
+ if (tokens.length != 5)
+ {
+ throw new InvalidIDException(ErrorCode.UNABLE_TO_PARSE_ID, "The method doesn't have enough tokens (" + id + ")");
+ }
+
+ if (!tokens[0].equals(URN))
+ {
+ throw new InvalidIDException(ErrorCode.UNABLE_TO_PARSE_ID, "The method must start with " + URN + " (" + id + ")");
+ }
+
+ if (!tokens[1].equals(NAMESPACE))
+ {
+ throw new InvalidIDException(ErrorCode.UNABLE_TO_PARSE_ID, "The namespace of the method must be " + NAMESPACE + " (" + id + ")");
+ }
+
+ set(tokens[2], tokens[3], tokens[4]);
+ }
+
+ /**
+ * Copy Constructor.
+ *
+ * @param other
+ * The other PdfASID to copy the data from.
+ */
+ public PdfASID(final PdfASID other)
+ {
+ set(other.vendor, other.type, other.version);
+ }
+
+ /**
+ * Auxiliary constructor.
+ *
+ * @param vendor
+ * The vendor.
+ * @param type
+ * The type.
+ * @param version
+ * The version.
+ */
+ private void set(String vendor, String type, String version)
+ {
+ this.vendor = vendor;
+ this.type = type;
+ this.version = version;
+ }
+
+ /**
+ * Returns the type.
+ *
+ * @return Returns the type.
+ */
+ public String getType()
+ {
+ return this.type;
+ }
+
+ /**
+ * Returns the vendor.
+ *
+ * @return Returns the vendor.
+ */
+ public String getVendor()
+ {
+ return this.vendor;
+ }
+
+ /**
+ * Returns the version.
+ *
+ * @return Returns the version.
+ */
+ public String getVersion()
+ {
+ return this.version;
+ }
+
+
+
+ /**
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ //@override
+ public boolean equals(Object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+ if (!(obj instanceof PdfASID))
+ {
+ return false;
+ }
+
+ PdfASID other = (PdfASID) obj;
+
+ return this.toString().equals(other.toString());
+ }
+
+ /**
+ * @see java.lang.Object#hashCode()
+ */
+ public int hashCode()
+ {
+ return toString().hashCode();
+ }
+
+ /**
+ * @see java.lang.Object#toString()
+ */
+ public String toString()
+ {
+ return URN + SPLIT_STRING + NAMESPACE + SPLIT_STRING + this.vendor + SPLIT_STRING + this.type + SPLIT_STRING + this.version;
+ }
+
+ /**
+ * Returns if it is an old textual signature (pre 1.2.0) that used cp1252 encoding for text extraction (mostly)
+ * @return
+ */
+ public boolean isOldCp1252Version() {
+ return this.getVersion().equals(SignatorFactory.VERSION_1_0_0)
+ || this.getVersion().equals(SignatorFactory.VERSION_1_1_0);
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/ConfigLogger.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/ConfigLogger.java
new file mode 100644
index 0000000..ed3dd3c
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/ConfigLogger.java
@@ -0,0 +1,79 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: ConfigLogger.java,v 1.3 2006/08/30 13:55:50 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.cfg;
+
+import java.util.ArrayList;
+
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+
+/**
+ * This logger class is the main logger class for the pdf-as project. It holds static logger
+ * instances with could be configured the level with one method.
+ *
+ * @deprecated use commons.logging instead
+ */
+public class ConfigLogger {
+
+ /**
+ * The static logger cache. It holds all used logger instances that could be configured by this
+ * main class.
+ */
+ private static ArrayList logger_ = new ArrayList();
+ /**
+ * This is the Level to use. Default is INFO.
+ */
+ private static Level level_ = Level.INFO;
+
+ /**
+ * This method activates a new log4j logger instance and store the instance in the local logger
+ * store.
+ *
+ * @param classRef the caller class to be set
+ * @return a log4j logger instance
+ * @see Logger
+ */
+ public static Logger getLogger(Class classRef) {
+ Logger logger = Logger.getLogger(classRef);
+ //logger.setLevel(level_);
+ logger_.add(logger);
+ return logger;
+ }
+
+ /**
+ * This method is to set a new logger level for all stored config logger.
+ *
+ * @param level the level to set
+ */
+ public static void setLevel(Level level) {
+ level_ = level;
+ for (int log_idx = 0; log_idx < logger_.size(); log_idx++) {
+ Logger logger = (Logger) logger_.get(log_idx);
+ logger.setLevel(level_);
+ logger_.set(log_idx, logger);
+ }
+ }
+} \ No newline at end of file
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/OverridePropertyHolder.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/OverridePropertyHolder.java
new file mode 100644
index 0000000..ddc3290
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/OverridePropertyHolder.java
@@ -0,0 +1,86 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.cfg;
+
+import java.util.Properties;
+
+import at.gv.egiz.pdfas.api.sign.SignParameters;
+import at.gv.egiz.pdfas.utils.OgnlUtil;
+
+/**
+ * Thread local holder for profile override values.
+ * Don't use this class directly, use {@link SignParameters#setProfileOverrideValue(String, String)}
+ *
+ * @author exthex
+ *
+ */
+public class OverridePropertyHolder {
+
+ private static ThreadLocal propHolder = new ThreadLocal() {
+ protected Object initialValue() { return new Properties();};
+ };
+ private static ThreadLocal ognlHolder = new ThreadLocal();
+
+ public static Properties getOverrideProps() {
+ return (Properties) propHolder.get();
+ }
+
+ public static void setOverrideProps(Properties props) {
+ propHolder.set(props);
+ }
+
+ public static void setProperty(String key, String val) {
+ getOverrideProps().setProperty(key, val);
+ }
+
+ public static String getProperty(String key) {
+
+ String res = getOverrideProps().getProperty(key);
+ if (res != null) {
+ OgnlUtil ognl = getOgnl();
+ if (ognl != null && ognl.containsExpression(res)) {
+ // evaluate expression
+ res = ognl.compileMessage(res);
+ }
+ }
+ return res;
+ }
+
+ public static void removeProperties() {
+ propHolder.set(new Properties());
+ }
+
+ public static void setOgnlUtil(OgnlUtil ognl) {
+ ognlHolder.set(ognl);
+ }
+
+ private static OgnlUtil getOgnl() {
+ return (OgnlUtil) ognlHolder.get();
+ }
+
+ public static void removeOgnlUtil() {
+ ognlHolder.set(null);
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/PropertyTree.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/PropertyTree.java
new file mode 100644
index 0000000..49ba003
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/PropertyTree.java
@@ -0,0 +1,358 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: PropertyTree.java,v 1.4 2006/10/31 08:06:28 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.cfg;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Vector;
+
+/**
+ * This class can be used to store a property config tree. The property key are separated by the
+ * {@link at.knowcenter.wag.egov.egiz.cfg.PropertyTree#SPLIT_STRING}. Therefore the keys an also
+ * the values of a configuration is stored in nested hashes. The keys in an area are stored in a
+ * HashMap. The values of a key are stored in a Vector to overload some keys. The property tree can
+ * be used to extract sub nodes and sub keys of different tree levels.
+ *
+ * @author wlackner
+ * @see java.util.HashMap
+ * @see java.util.Vector
+ */
+public class PropertyTree implements Serializable {
+
+ /**
+ * SVUID.
+ */
+ private static final long serialVersionUID = -1686170519955886222L;
+
+ /**
+ * The key split string. A key can be a complex key. Sub keys are separated from each other with
+ * the split string. This string is used to devide the complex key.
+ */
+ public static final String SPLIT_STRING = "\\.";
+ /**
+ * Stores the key references to the sub nodes
+ */
+ private Map keys_ = new HashMap(3);
+ /**
+ * Stores all values of a node
+ */
+ private Vector values_ = new Vector(3);
+
+ /**
+ * The default constructor od the class.
+ */
+ public PropertyTree() {
+ }
+
+ /**
+ * This method takes a key value tupel and store them in the property tree. The key splitted into
+ * different levels (splitted by the string
+ * {@link at.knowcenter.wag.egov.egiz.cfg.PropertyTree#SPLIT_STRING}). All subnodes not stored in
+ * the tree will be created. The last part of the key (last splitted element) adds the value to
+ * there own value data structure (Vector). <br />
+ * <strong>Example: </strong> <code>setKeyValue("key.1_level.2_level","the value for k_1_2")</code
+ *
+ * @param splitKey the key that has to be store the value
+ * @param value only String values can be stored
+ */
+ public void setKeyValue(String splitKey, String value) {
+ String[] keys = splitKey.split(SPLIT_STRING);
+ PropertyTree curr_tree = this;
+ for (int key_idx = 0; key_idx < keys.length; key_idx++) {
+ String key = keys[key_idx];
+ if (!curr_tree.containsNode(key)) {
+ curr_tree.setSubTree(key, null);
+ }
+ if (key_idx < keys.length - 0)
+ curr_tree = (PropertyTree) curr_tree.getSubTree(key);
+ }
+ curr_tree.addValue(value);
+ }
+
+ /**
+ * Adds a String value to the current key
+ *
+ * @param value
+ */
+ private void addValue(String value) {
+ values_.add(value);
+ }
+
+ /**
+ * This method takes a key as input value, split them into subnodes and return the sub tree of the
+ * last node of the key. If the key or a sub node not found, the method return null. This means
+ * the key is not part of the sub property tree.
+ *
+ * @param splitKey the key that has to be found as sub node of the current node
+ * @return the sub tree (PropertyTree) or <code>null</code> if the key is not a subtree referece
+ */
+ private PropertyTree getLastSubTree(String splitKey) {
+ String[] keys = splitKey.split(SPLIT_STRING);
+ PropertyTree curr_tree = this;
+ for (int key_idx = 0; key_idx < keys.length; key_idx++) {
+ String key = keys[key_idx];
+ if (!curr_tree.containsNode(key)) {
+ return null;
+ }
+ curr_tree = (PropertyTree) curr_tree.getSubNode(key);
+ }
+ return curr_tree;
+ }
+
+ /**
+ * This method return the subtree that corresponds to a particular key. The key does not split.
+ * Therefore the key must be a children of the current node. Search only in the key map of the
+ * current node.
+ *
+ * @param key the key that has to be a sub node
+ * @return a sub tree (PropertyTree) or <code>null</code> if the key is not a children of the
+ * current node
+ */
+ private PropertyTree getSubNode(String key) {
+ return (PropertyTree) keys_.get(key);
+ }
+
+ /**
+ * Returns the last value (keys can be overloaded) of a key. The key are splitted into subnodes
+ * and the last node of the key is the current value holder. If a key or subnode is not in the sub
+ * tree the return value is <code>null.</code>
+ *
+ * @param key the key that holds the value (can be a nested key like <code>"key.1.2.3"</code>)
+ * @return the value of the key (last node of the key) or <code>null</code> otherwise
+ */
+ public String getLastValue(String key) {
+ PropertyTree curr_tree = getLastSubTree(key);
+ String result = null;
+ if (curr_tree != null && !curr_tree.values_.isEmpty()) {
+ result = (String) curr_tree.values_.lastElement();
+ }
+// if (logger_.isDebugEnabled()) {
+// logger_.debug("getLastValue:" + key + "=" + result);
+// }
+ return result;
+ }
+
+ /**
+ * Returns the first value (keys can be overloaded) of a key. The key are splitted into subnodes
+ * and the last node of the key is the current value holder. If a key or subnode is not in the sub
+ * tree the return value is <code>null</code>.
+ *
+ * @param key the key that holds the value (can be a nested key like <code>"key.1.2.3"</code>)
+ * @return the value of the key (last node of the key) or <code>null</code> otherwise
+ */
+ public String getFirstValue(String key) {
+ PropertyTree curr_tree = getLastSubTree(key);
+ String result = null;
+ if (curr_tree != null && !curr_tree.values_.isEmpty()) {
+ result = (String) curr_tree.values_.firstElement();
+ }
+// if (logger_.isDebugEnabled()) {
+// logger_.debug("getFirstValue:" + key + "=" + result);
+// }
+ return result;
+ }
+
+ /**
+ * This method return all values of the current node. The values are stored as String values.
+ *
+ * @return the values (type String) of the current node
+ * @see Vector
+ */
+ public Vector getValues() {
+ return values_;
+ }
+
+ /**
+ * This method return all keys (sub tree references) of the current node as a Map. The keys are
+ * stored as String values.
+ *
+ * @return the keys (type String) of the current node
+ * @see Map
+ */
+ public Map getKeyEntries() {
+ return keys_;
+ }
+
+ /**
+ * This method return all keys (sub tree references) of the current node as an ArrayList. The keys
+ * are stored as String values.
+ *
+ * @return the keys (type String) of the current node
+ * @see ArrayList
+ */
+ public ArrayList getKeys() {
+ if (!keys_.isEmpty()) {
+ Object[] objs = keys_.keySet().toArray();
+ ArrayList keys = new ArrayList(objs.length);
+ for (int idx = 0; idx < objs.length; idx++) {
+ keys.add((String) objs[idx]);
+ }
+ return keys;
+ }
+ return null;
+ }
+
+ /**
+ *
+ * This method return all sub tree references of a key as an ArrayList. The keys are stored as
+ * String values.
+ *
+ * @param key (can be a nested key like <code>"key.1.2.3"</code>)
+ * @return the keys (type String) of the current node
+ * @see ArrayList
+ */
+ public ArrayList getKeys(String key) {
+ PropertyTree curr_tree = getLastSubTree(key);
+ if (curr_tree != null) {
+ return curr_tree.getKeys();
+ }
+ return null;
+ }
+
+ /**
+ * This method return all values of a key. The values are stored as String values.
+ *
+ * @param key (can be a nested key like <code>"key.1.2.3"</code>)
+ * @return the values (type Vector) of the key or <code>null</code> if the key is not in the sub
+ * tree of the current node
+ * @see Vector
+ */
+ public Vector getValues(String key) {
+ PropertyTree curr_tree = getLastSubTree(key);
+ if (curr_tree != null) {
+ return curr_tree.values_;
+ }
+ return null;
+ }
+
+ /**
+ * Store a sub tree (type PropertyTree) in the current node. The key and it's sub tree are stored
+ * in a HashMap.
+ *
+ * @param key the reference of the sub tree
+ * @param tree the sub tree of the key
+ * @see HashMap
+ */
+ private void setSubTree(String key, PropertyTree tree) {
+ if (tree == null) {
+ tree = new PropertyTree();
+ }
+ keys_.put(key, tree);
+ }
+
+ /**
+ * Extracts a sub tree of a nested key. The Method returns the last sub tree of the nested key.
+ * <strong>Example: </strong>if the key is like: <code>key.1.2.3</code> the sub tree of the last
+ * node <code>3</code> is returned.
+ *
+ * @param key the reference of the sub tree
+ * @return a sub tree of the key or <code>null</code> if the key can not be found
+ */
+ public PropertyTree getSubTree(String key) {
+ return getLastSubTree(key);
+ }
+
+ /**
+ * This method checks if a key is a reference to a sub tree in the current node.
+ *
+ * @param key a simple key that is a parent reference of a sub tree
+ * @return true if the key is found, false otherwise
+ */
+ public boolean containsNode(String key) {
+ return keys_.containsKey(key);
+ }
+
+ /**
+ * The default toString method. It starts with the current node recursively downwards and return
+ * the String representation of the node.
+ *
+ * @return the string representation of the node
+ */
+ public String toString() {
+ return toString("", this);
+ }
+
+ /**
+ * This is a helper function to define the prefix for different levels in the toString method, not
+ * realy nice ;-).
+ * It replaces all "." chars with " ".
+ *
+ * @param key
+ * @return a replaces prefix string
+ */
+ private static String getEmptyString(String key) {
+ return key.replaceAll(".", " ");
+ }
+
+ /**
+ * This method concatenates all values of the current node and return them as a combinded string.
+ *
+ * @param prefix
+ * @param tree
+ * @return the string representation of the node values
+ */
+ private static String printValues(String prefix, PropertyTree tree) {
+ String os = "";
+ Iterator values = tree.getValues().iterator();
+ while (values.hasNext()) {
+ String value = (String) values.next();
+ os += prefix + "=" + value;
+ }
+ return os;
+ }
+
+ /**
+ * The toString method. It starts with a special level prefix, sub tree and recursively adds all
+ * sub trees.
+ *
+ * @param prefix the prefix for this node
+ * @param tree the current node
+ * @return the string representation of the node
+ */
+ public static String toString(String prefix, PropertyTree tree) {
+ String os = "";
+ Iterator entries = tree.getKeyEntries().entrySet().iterator();
+ while (entries.hasNext()) {
+ Map.Entry entry = (Map.Entry) entries.next();
+ String key = (String) entry.getKey();
+ PropertyTree sub = (PropertyTree) entry.getValue();
+ String os_key = "\n" + prefix + "." + key;
+ os += printValues(os_key, sub);
+ String subs = toString(prefix + getEmptyString(key) + " |", sub);
+ if (subs.length() > 0) {
+ os += os_key + "|" + subs;
+ }
+ }
+ return os;
+ }
+
+ public void removeEntry(String key) {
+ this.keys_.remove(key);
+ }
+} \ No newline at end of file
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/Settings.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/Settings.java
new file mode 100644
index 0000000..0c238ac
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/Settings.java
@@ -0,0 +1,63 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: Settings.java,v 1.2 2006/08/03 07:43:03 wprinz Exp $
+ */
+
+package at.knowcenter.wag.egov.egiz.cfg;
+
+import at.knowcenter.wag.egov.egiz.exceptions.SettingNotFoundException;
+
+/**
+ * Defines an interface reading a configuration file.
+ *
+ * @author wlackner
+ */
+public interface Settings {
+ /**
+ * Search for a key in the configuration file.
+ *
+ * @param key to search for
+ * @return the corresponding value
+ * @throws SettingNotFoundException if the key is not found
+ */
+ public String getSetting(String key) throws SettingNotFoundException;
+
+ /**
+ * Search for a key in the configuration file.
+ *
+ * @param key to search for
+ * @param defaultValue return this value if the key is not found
+ * @return the corresponding value
+ */
+ public String getSetting(String key, String defaultValue);
+
+ /**
+ *
+ * @param primaryKey to search for
+ * @param defaultKey to search for if the primaryKey is not found
+ * @param defaultValue return this value if the defaultKey is not found
+ * @return the corresponding value
+ */
+ public String getSetting(String primaryKey, String defaultKey, String defaultValue);
+} \ No newline at end of file
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/SettingsReader.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/SettingsReader.java
new file mode 100644
index 0000000..6bc1c99
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/cfg/SettingsReader.java
@@ -0,0 +1,905 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: SettingsReader.java,v 1.6 2006/10/31 08:06:36 wprinz Exp $
+ */
+
+package at.knowcenter.wag.egov.egiz.cfg;
+
+import iaik.asn1.ObjectID;
+import iaik.security.ecc.provider.ECCProvider;
+import iaik.security.provider.IAIK;
+import iaik.utils.RFC2253NameParser;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Serializable;
+import java.security.Security;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Properties;
+import java.util.Vector;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.text.StrSubstitutor;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import at.gv.egiz.pdfas.api.commons.Constants;
+import at.gv.egiz.pdfas.api.exceptions.ConfigUtilsException;
+import at.gv.egiz.pdfas.utils.ConfigUtils;
+import at.gv.egiz.pdfas.utils.TempDirHelper;
+import at.knowcenter.wag.egov.egiz.PdfAS;
+import at.knowcenter.wag.egov.egiz.exceptions.SettingNotFoundException;
+import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
+import at.knowcenter.wag.egov.egiz.pdf.Utils;
+import at.knowcenter.wag.egov.egiz.tools.FileHelper;
+
+/**
+ * The SettingsReader reads the <code>settings.txt</code> file. The
+ * <code>settings.txt</code> is a simple java property file that collects all
+ * parameters used in different modules.
+ *
+ * The SettingsReader provides methods to get the property keys and the
+ * corresponding values. The keys could be defined as combinations of single
+ * keys. Therefore it is possible to combine differen classes of keys. An
+ * example could be:
+ *
+ * <pre>
+ *
+ * #SettingNotFoundException
+ * error.code.100=Interner Fehler
+ * error.code.101=Die Konfigurationsdatei konnte nicht geladen werden
+ *
+ * #PDFDocumentException
+ * error.code.200=Das Dokument konnte nicht geladen werden
+ *
+ * #SignatureException
+ * error.code.300=Die Signatur ist ungültig
+ *
+ * #NormalizeException
+ * error.code.400=Die angegebene Version ist nicht bekannt
+ *
+ * normalizer.version=V01
+
+ *
+ * </pre>
+ *
+ * The internal representation of the example above is:
+ *
+ * <pre>
+ *
+
+ * .error|
+ * |.code|
+ * | |.200=Das Dokument konnte nicht geladen werden
+ * | |.100=Interner Fehler
+ * | |.400=Die angegebene Version ist nicht bekannt
+ * | |.101=Die Konfigurationsdatei konnte nicht geladen werden
+ * | |.300=Die Signatur ist ungueltig
+ * .normalizer|
+ * |.version=V01
+ *
+ * </pre>
+ *
+ * @author wlackner
+ */
+public class SettingsReader implements Serializable
+{
+
+ /**
+ * SVUID.
+ */
+ private static final long serialVersionUID = -8754114172766023454L;
+
+ /**
+ * The system File separator char
+ */
+ private static final String FILE_SEP = System.getProperty("file.separator");
+
+ // /**
+ // * The system temp file path
+ // */
+ // private static final String TEMP_FILE_PATH =
+ // System.getProperty("java.io.tmpdir");
+
+// /**
+// * The home path of the tomcat webaplication
+// */
+// private static final String CATALINA_HOME = System.getProperty("catalina.home");
+
+// /**
+// * The default application name used in templates, settings, jsp's etc.
+// */
+// private static final String APPL_NAME = "pdf-as";
+
+ // private static final String APPL_NAME = "egiz";
+ /**
+ * The config file path postfix
+ */
+ private static final String CFG = "cfg";
+
+ /**
+ * The file path postfix where certificates are stored
+ */
+ private static final String CERT = "certificates";
+
+ /**
+ * pdf-as internal properties resource path
+ */
+ private static final String PDF_AS_PROP_RESOURCE = "/config/pdf-as.properties";
+
+ /**
+ * internal help file
+ */
+ private static final String HELP_TEXT_PROP_RESOURCE = "/config/help_text.properties";
+
+ public static final boolean REGISTER_IAIK_PROVIDERS_ON_DEFAULT = true;
+
+// /**
+// * The web application path
+// */
+// private static final String WEB_APPL_DIR = "webapps" + FILE_SEP + APPL_NAME + FILE_SEP;
+
+ /**
+ * The path of the resources repository.
+ *
+ * <p>
+ * This usually contains sub directories for the templates, the configuration
+ * files, etc.
+ * </p>
+ */
+ public static String RESOURCES_PATH = null;
+
+ /**
+ * The path for temporary files.
+ */
+ public static String TMP_PATH = null;
+
+ /**
+ * The path of the configuration directory.
+ */
+ public static String CONFIG_PATH = null;
+
+ /**
+ * The path of the certificated directory.
+ */
+ public static String CERT_PATH = null;
+
+ // /**
+ // * The application config path for the command line tool
+ // */
+ // public static final String APPL_CONFIG_PATH = USER_DIR + FILE_SEP + CFG +
+ // FILE_SEP;
+ //
+ // /**
+ // * The application config path for the web application
+ // */
+ // public static final String WEB_CONFIG_PATH = CATALINA_HOME + FILE_SEP +
+ // WEB_APPL_DIR + CFG + FILE_SEP;
+ //
+ // /**
+ // * The certificates path for the command line tool
+ // */
+ // public static final String APPL_CERT_PATH = USER_DIR + FILE_SEP + CERT +
+ // FILE_SEP;
+ //
+ // /**
+ // * The certificates path for the cweb application
+ // */
+ // public static final String WEB_CERT_PATH = CATALINA_HOME + FILE_SEP +
+ // WEB_APPL_DIR + CERT + FILE_SEP;
+
+ /**
+ * The name of the default configuration file. The definition syntax is the
+ * java property config syntax.
+ */
+ public static final String CONFIG_FILE_DEFAULT_NAME = "config.properties";
+
+ /**
+ * The name of the help text configuration file. The definition syntax is the
+ * java property config syntax.
+ */
+// public static final String HELP_TEXT_FILE_DEFAULT_NAME = "help_text.properties";
+
+ /**
+ * The java properties from the settings file.
+ */
+ private Properties properties_ = null;
+
+ /**
+ * The settings reader instance. Used to make the class singleton.
+ */
+ private static SettingsReader instance_ = null;
+
+ /**
+ * The reference to the settings file.
+ */
+ private static String settingsFile_ = null;
+
+ /**
+ * The reference to the property representation of the settings file.
+ */
+ private PropertyTree pTree_ = new PropertyTree();
+
+ /**
+ * The log.
+ */
+ private static final Log logger_ = LogFactory.getLog(SettingsReader.class);
+
+ private static final String INTERNAL_RESOURCE_PATH = "/config/";
+
+
+ /**
+ * Make this constructor private. Use the method
+ * {@link SettingsReader#getInstance()}to get an instance from this class.
+ * The only cause to do this is that the definition file should only be read
+ * once while getting often this instance. The method throws an IOException if
+ * the settings file could not be read.
+ *
+ * @param settingsFile
+ * load this file, if the <code>settingsFile == null</code> the
+ * default settings ({@link SettingsReader#CONFIG_FILE_DEFAULT_NAME})
+ * file is used
+ * @throws SettingsException
+ * if the settings file could not be read
+ */
+ private SettingsReader(String settingsFile) throws SettingsException
+ {
+ try
+ {
+ String cfg_path = CONFIG_PATH;
+ properties_ = new Properties();
+ if (settingsFile == null)
+ {
+ settingsFile = cfg_path + CONFIG_FILE_DEFAULT_NAME;
+ }
+ settingsFile_ = settingsFile;
+ if (logger_.isInfoEnabled())
+ {
+ File file = new File(settingsFile_);
+ logger_.debug("load Settings:" + file.getAbsolutePath());
+ // Properties sys_prop = System.getProperties();
+ // Enumeration prop_keys = sys_prop.propertyNames();
+ // while (prop_keys.hasMoreElements()) {
+ // String key = (String) prop_keys.nextElement();
+ // String value = sys_prop.getProperty(key);
+ // logger_.info(key + "=" + value);
+ // }
+ }
+ FileInputStream sfs = new FileInputStream(settingsFile_);
+ properties_.load(sfs);
+
+ // dferbas override with system props
+ properties_.load(SettingsReader.class.getResourceAsStream(PDF_AS_PROP_RESOURCE));
+
+ Properties help_prop = new Properties();
+// FileInputStream hfs = new FileInputStream(cfg_path + HELP_TEXT_FILE_DEFAULT_NAME);
+// help_prop.load(hfs);
+ help_prop.load(SettingsReader.class.getResourceAsStream(HELP_TEXT_PROP_RESOURCE));
+
+ // load properties from current package!
+ // properties_.load(getClass().getResourceAsStream(settingsFile_));
+ Enumeration prop_keys = properties_.propertyNames();
+
+ while (prop_keys.hasMoreElements())
+ {
+ String key = (String) prop_keys.nextElement();
+ String value = properties_.getProperty(key);
+ pTree_.setKeyValue(key, value);
+ }
+ prop_keys = help_prop.propertyNames();
+ while (prop_keys.hasMoreElements())
+ {
+ String key = (String) prop_keys.nextElement();
+ String value = help_prop.getProperty(key);
+ properties_.setProperty(key, value);
+ pTree_.setKeyValue(key, value);
+ }
+ }
+ catch (IOException e)
+ {
+ throw new SettingsException("Couldn't load settings from file " + settingsFile, e);
+ }
+ }
+
+ /**
+ * This method returns an synchronized instance of this class. The settings
+ * file is read only once using this class. This method returns the instance
+ * holding the definitions of the default settings file. Default file:
+ * {@link SettingsReader#CONFIG_FILE_DEFAULT_NAME}: "settings.txt".
+ * Note: IAIK JCE and IAIK ECC security providers are automatically registered.
+ *
+ * @return an instance of the SettingsReader
+ * @throws SettingsException
+ * if the default settings file could not be read
+ */
+ public synchronized static SettingsReader getInstance() throws SettingsException
+ {
+ return getInstance(null);
+ }
+
+ /**
+ * Reloads the Settings file.
+ *
+ * <p>
+ * Subsequent calls to getInstance will return the new settings.
+ * Note: IAIK JCE and IAIK ECC security providers are automatically registered.
+ * </p>
+ *
+ * @throws SettingsException f.e.
+ */
+ public synchronized static void createInstance() throws SettingsException
+ {
+ instance_ = null;
+ getInstance();
+ }
+
+ /**
+ * Reloads the Settings file.
+ *
+ * <p>
+ * Subsequent calls to getInstance will return the new settings.
+ * </p>
+ * @param registerProvider <code>true</code>: automatically registers IAIK JCE and ECC Provider;
+ * <code>false</code>: providers will NOT be automatically registered, providers
+ * needed have to be registered by the API user
+ * @throws SettingsException f.e.
+ */
+ public synchronized static void createInstance(boolean registerProvider) throws SettingsException
+ {
+ instance_ = null;
+ getInstance(null, registerProvider);
+ }
+
+ /**
+ * This method returns an synchronized instance of this class. The settings
+ * file is read only once using this class. This method returns the instance
+ * holding the definitions of the settingsFile. If the input param
+ * <code>settingsFile == null</code> the default settings file will be load.
+ * Default file: {@link SettingsReader#CONFIG_FILE_DEFAULT_NAME}:
+ * "settings.txt"
+ *
+ * If an instance of this class exist, the input param is ignored! The
+ * SettingsReader is singleton and therefore the first
+ * {@link SettingsReader#getInstance()}defines the settings file that has to
+ * be loaded. This means changes between a application lifecyle can not be
+ * done!
+ *
+ * @param settingsFile
+ * the settings file that should be load.
+ * @param registerProvider <code>true</code>: automatically registers IAIK JCE and ECC Provider;
+ * <code>false</code>: providers will NOT be automatically registered, providers
+ * needed have to be registered by the API user
+ * @return an instance of the SettingsReader
+ * @throws SettingsException
+ * if the settings file could not be read
+ */
+ private synchronized static SettingsReader getInstance(String settingsFile, boolean registerProvider) throws SettingsException
+ {
+ if (instance_ == null)
+ {
+ int length = Utils.max(new int[] { RESOURCES_PATH.length(), TMP_PATH.length(), CONFIG_PATH.length(), CERT_PATH.length() });
+
+ logger_.info(StringUtils.repeat("*", length + 25));
+ logger_.info(" resources path = \"" + RESOURCES_PATH + "\"");
+ logger_.info(" configuration path = \"" + CONFIG_PATH + "\"");
+ logger_.info(" certstore path = \"" + CERT_PATH + "\"");
+ logger_.info(" temporary path = \"" + TMP_PATH + "\"");
+ logger_.debug(" file.encoding = \"" + System.getProperty("file.encoding") + "\"");
+ logger_.info(StringUtils.repeat("*", length + 25));
+
+ if (registerProvider) {
+ IAIK.addAsProvider();
+ ECCProvider.addAsProvider();
+ } else {
+ if (Security.getProvider("IAIK") == null) {
+ logger_.debug("Default IAIK JCE provider not registered.");
+ } else {
+ logger_.debug("IAIK JCE provider already registered.");
+ }
+ if (Security.getProvider("IAIK_ECC") == null) {
+ logger_.debug("Default IAIK ECC provider not registered.");
+ } else {
+ logger_.debug("IAIK ECC provider already registered.");
+ }
+ }
+ // Does not conform with PKIX, but is used by belgium citizen card
+// log.info("Registering RDN \"SERIALNUMBER\" as " + ObjectID.serialNumber + ".");
+ RFC2253NameParser.register("SERIALNUMBER", ObjectID.serialNumber);
+
+ instance_ = new SettingsReader(settingsFile);
+ }
+ return instance_;
+ }
+
+ /**
+ * This method returns an synchronized instance of this class. The settings
+ * file is read only once using this class. This method returns the instance
+ * holding the definitions of the settingsFile. If the input param
+ * <code>settingsFile == null</code> the default settings file will be load.
+ * Default file: {@link SettingsReader#CONFIG_FILE_DEFAULT_NAME}:
+ * "settings.txt".
+ * Note: IAIK JCE and IAIK ECC security providers are automatically registered.
+ *
+ * If an instance of this class exist, the input param is ignored! The
+ * SettingsReader is singleton and therefore the first
+ * {@link SettingsReader#getInstance()}defines the settings file that has to
+ * be loaded. This means changes between a application lifecyle can not be
+ * done!
+ *
+ * @param settingsFile
+ * the settings file that should be load.
+ * @return an instance of the SettingsReader
+ * @throws SettingsException
+ * if the settings file could not be read
+ */
+ private static SettingsReader getInstance(String settingsFile) throws SettingsException
+ {
+ return getInstance(settingsFile, REGISTER_IAIK_PROVIDERS_ON_DEFAULT);
+ }
+
+ /**
+ * This method returns a property value to the corresponding key. If the key
+ * is not found in the property file a SettingNotFoundException is thrown.
+ *
+ * @param key
+ * get the value for that key in the property file
+ * @return the value of the property key.
+ * @throws SettingNotFoundException
+ * ErrorCode: 100
+ */
+ public String getSetting(String key) throws SettingNotFoundException
+ {
+ String result = OverridePropertyHolder.getProperty(key);
+ if (result == null) {
+ result = properties_.getProperty(key);
+ }
+ if (result == null)
+ {
+ String log_message = "Configuration key not found: '" + key + "'! Check '" + settingsFile_ + "' file.";
+ if (logger_.isWarnEnabled())
+ {
+ logger_.warn(log_message);
+ }
+ SettingNotFoundException snf = new SettingNotFoundException(log_message);
+ throw snf;
+ }
+
+ return result;
+ }
+
+ // TODO in the next change request, the Setting system will be refactored
+ // this is just for testing purposes.
+ public void setSetting(String key, String value)
+ {
+ properties_.setProperty(key, value);
+ }
+
+ /**
+ * Relocates the relative file.
+ *
+ * @param file
+ * The relative file.
+ * @return Returns the usable file.
+ */
+ public static String relocateFile(String file)
+ {
+ // if (isWeb())
+ // {
+ // return CATALINA_HOME + FILE_SEP + WEB_APPL_DIR + file;
+ // }
+ //
+ // return file;
+ return RESOURCES_PATH + file;
+ }
+
+ /**
+ * This method returns a property value to the corresponding key. If the key
+ * is not found in the property file the input param defaultValue is returned.
+ *
+ * @param key
+ * get the value for that key in the property file
+ * @param defaultValue
+ * the default value if the key is not found
+ * @return the value of the property key
+ */
+ public String getSetting(String key, String defaultValue)
+ {
+
+ String result = properties_.getProperty(key);
+ if (result == null)
+ {
+ result = defaultValue;
+ }
+// if (logger_.isDebugEnabled())
+// {
+// logger_.debug("Get Property:" + key + "=" + result);
+// }
+ return result;
+ }
+
+ /**
+ * This method returns a property value to the corresponding key. If the key
+ * is not found in the property file the input param defaultKey is searched.
+ * If the default key is not found the input param defaultValue is returned.
+ *
+ * @param primaryKey
+ * get the value for that key in the property file
+ * @param defaultKey
+ * the default key that should be searched if the primaryKey is not
+ * found
+ * @param defaultValue
+ * the default value if the defaultKey is not found
+ * @return the value of the property key
+ */
+ public String getSetting(String primaryKey, String defaultKey, String defaultValue)
+ {
+ String key = primaryKey;
+ String result = properties_.getProperty(key);
+ if (result == null)
+ {
+ key = defaultKey;
+ result = properties_.getProperty(key);
+ if (result == null)
+ {
+ result = defaultValue;
+ }
+ }
+// if (logger_.isDebugEnabled())
+// {
+// logger_.debug("Get Property:" + key + "=" + result);
+// }
+ return result;
+ }
+
+ /**
+ * This method returns an array of keys in the same hierarchy of the
+ * keyPrefix. The method search all keys in the property file that has the
+ * keyPrefix as leading substring. The <code>Object[]</code> collects all
+ * sub keys without the keyPrefix.
+ *
+ * @param keyPrefix
+ * to search for sub keys
+ * @return alls keys starting with the keyPrefix
+ */
+ public Vector getSettingKeys(String keyPrefix)
+ {
+ Vector keys = new Vector();
+ Enumeration names = properties_.propertyNames();
+ while (names.hasMoreElements())
+ {
+ String full_name = (String) names.nextElement();
+ if (full_name.indexOf(keyPrefix) == 0)
+ {
+ keys.add(full_name.substring(keyPrefix.length() + 1));
+ }
+ }
+ return keys;
+ }
+
+ /**
+ * If a property value is number (interger) this method extracts the value and
+ * convert it to an int. If the key ist not found or the conversion fails, the
+ * defaultValue is returned.
+ *
+ * @param key
+ * get the value for that key in the property file
+ * @param defaultValue
+ * the default value if the key is not found
+ * @return the int value of the property key
+ */
+ public int getIntSetting(String key, int defaultValue)
+ {
+ int int_property = defaultValue;
+ String value = null;
+ try
+ {
+ value = getSetting(key);
+ int_property = Integer.parseInt(value);
+ }
+ catch (NumberFormatException e)
+ {
+ if (logger_.isWarnEnabled())
+ {
+ logger_.warn("Can not convert " + value + " to int.", e);
+ }
+ }
+ catch (SettingNotFoundException e)
+ {
+ if (logger_.isWarnEnabled())
+ {
+ logger_.warn("Setting " + key + " not found, return default value:" + defaultValue, e);
+ }
+ }
+ return int_property;
+ }
+
+ /**
+ * This method returns an array of sub keys (children references) of the key.
+ * The method is a wrapper calling the method
+ * {@link PropertyTree#getKeys(String key)}.
+ *
+ * @param key
+ * get all sub keys for that key in the property file
+ * @return an list of sub keys (type String)
+ * @see PropertyTree
+ */
+ public ArrayList getKeys(String key)
+ {
+ return pTree_.getKeys(key);
+ }
+
+ /**
+ * This method returns a the first value from a key. This means the method
+ * search in the PropertyTree representation of the config file. The
+ * PropertyTree class can overload key value paires. But the config file can
+ * not overload keys. If a key is defined more than one times the last
+ * definition is stored it the property list. The method is a wrapper calling
+ * the method {@link PropertyTree#getFirstValue(String key)}.
+ *
+ * @param key
+ * get the value for that key in the property file
+ * @return the value of the property key
+ * @see PropertyTree
+ */
+ public String getValueFromKey(String key)
+ {
+ String value = OverridePropertyHolder.getProperty(key);
+ if (value == null) {
+ value = pTree_.getFirstValue(key);
+ }
+
+ return value;
+ }
+
+ /**
+ * This method returns the PropertyTree representation of the configuration
+ * file.
+ *
+ * @return Returns the pTree.
+ * @see PropertyTree
+ */
+ public PropertyTree getPTree()
+ {
+ return pTree_;
+ }
+
+ /**
+ * Reads internal resource as string.
+ * @param relativePath
+ * @return null in case of error
+ */
+ public String readInternalResourceAsString(String relativePath) {
+// return readAsString(getInternalResource(relativePath));
+ return FileHelper.readFromInputStream(getInternalResource(relativePath));
+ }
+
+ /**
+ * Get resource as stream, relative to internal resource path {@value #INTERNAL_RESOURCE_PATH}
+ *
+ * @param relativePath
+ * @return
+ */
+ public InputStream getInternalResource(String relativePath) {
+ // kill starting "." and "./" in resource path
+ relativePath = StringUtils.removeStart(relativePath, ".");
+ relativePath = StringUtils.removeStart(relativePath, "/");
+ String streamURI = INTERNAL_RESOURCE_PATH + relativePath;
+ logger_.trace("Trying to get stream from \"" + streamURI + "\".");
+ InputStream stream = this.getClass().getResourceAsStream(streamURI);
+ if (stream == null) {
+ logger_.trace("Could not get stream.");
+ } else {
+ logger_.trace("Got stream.");
+ }
+ return stream;
+ }
+
+ /**
+ * Read resource as utf8 string.
+ * @param is
+ * @return <code>null</code> in case of error
+ */
+ /*
+ public String readAsString(InputStream is) {
+ if (is == null) return null;
+ try {
+ return IOUtils.toString(is, "utf-8");
+ } catch (IOException e) {
+ logger_.info("error reading stream to string ", e);
+ }
+ return null;
+ }
+ */
+
+ // /**
+ // * This method checks the application context.
+ // *
+ // * @return true if the application is running in a webinterface, false
+ // * otherwise
+ // */
+ // public static boolean isWeb()
+ // {
+ // return CATALINA_HOME != null;
+ // }
+
+ /**
+ * Assembles the File of the temporary directory without checking if it really
+ * exists.
+ * @see TempDirHelper#assembleTemporaryDirectoryFile()
+ */
+ protected static File assembleTemporaryDirectoryFile()
+ {
+ return TempDirHelper.assembleTemporaryDirectoryFile();
+ }
+
+ /**
+ * Returns the directory where temporary files should be stored.
+ *
+ * <p>
+ * If the directory doesn't exist, it is created.
+ * </p>
+ *
+ * @return Returns the directory where temporary files should be stored.
+ * @see TempDirHelper#getTemporaryDirectory()
+ */
+ public static File getTemporaryDirectory()
+ {
+ return TempDirHelper.getTemporaryDirectory();
+ }
+
+ /**
+ * Deletes all files in the temporary directory, if it exists.
+ *
+ * <p>
+ * This should be used to clear temporary files when the application shuts
+ * down.
+ * </p>
+ * @see TempDirHelper#clearTemporaryDirectory()
+ */
+ public static void clearTemporaryDirectory()
+ {
+ TempDirHelper.clearTemporaryDirectory();
+ }
+
+ public static synchronized void initialize(String configdir, String tmpdir) {
+
+ String defaultConfigDeployedTo = null;
+ // resolve work directory
+ // configuration explicitely given ?
+ if (configdir == null) {
+
+ // configuration via system property ?
+ logger_.debug("No configuration directory given. Looking for system property \"" + Constants.CONFIG_DIR_SYSTEM_PROPERTY + "\".");
+ configdir = System.getProperty(Constants.CONFIG_DIR_SYSTEM_PROPERTY);
+ if (configdir == null) {
+
+ // configuration via user's home directory ?
+ logger_.debug("System property not set. Trying to locate configuration within the user's home directory.");
+ String userHome = System.getProperty("user.home");
+ if (userHome == null || userHome.length() == 0) {
+ throw new RuntimeException("Unable to resolve user's home directory.");
+ }
+ configdir = ConfigUtils.assertFileSeparator(userHome) + Constants.USERHOME_CONFIG_FOLDER;
+ try {
+ defaultConfigDeployedTo = ConfigUtils.deployDefaultConfiguration(configdir, false);
+ } catch (ConfigUtilsException e) {
+ throw new RuntimeException(e);
+ }
+ if (defaultConfigDeployedTo != null) {
+ logger_.info("** Default configuration successfully deployed to \"" + defaultConfigDeployedTo + "\" **");
+ } else {
+ logger_.debug("Default configuration has NOT been deployed. Maybe the configuration already exists.");
+ }
+ } else {
+ logger_.debug("Configuration set by system property.");
+ if (tmpdir == null) {
+ tmpdir = configdir;
+ }
+ }
+ } else {
+ logger_.debug("Configuration path explicitely set.");
+ }
+ File configdirFile = new File(StrSubstitutor.replaceSystemProperties(configdir));
+ try {
+ configdir = ConfigUtils.assertFileSeparator(configdirFile.getCanonicalPath());
+ } catch (IOException e) {
+ configdir = ConfigUtils.assertFileSeparator(configdirFile.getPath());
+ }
+ if (!configdirFile.isDirectory())
+ {
+ throw new IllegalArgumentException("The config directory \"" + configdir + "\" does not exist or is not a directory.");
+ }
+
+ // resolve temporary dir
+ if (tmpdir == null) {
+ logger_.debug("Temporary directory not explicitely set. Looking for user's temp directory.");
+ tmpdir = System.getProperty("java.io.tmpdir");
+ if (tmpdir == null) {
+ logger_.debug("Unable to resolve user's temporary directory. Assuming temporary directory located within config dir.");
+ tmpdir = configdir;
+ }
+ } else {
+ logger_.debug("Temporary directory explicitely set.");
+ }
+ File tmpdirFile = new File(StrSubstitutor.replaceSystemProperties(ConfigUtils.assertFileSeparator(tmpdir) + Constants.TEMP_DIR_NAME));
+ try {
+ tmpdir = ConfigUtils.assertFileSeparator(tmpdirFile.getCanonicalPath());
+ } catch (IOException e) {
+ tmpdir = ConfigUtils.assertFileSeparator(tmpdirFile.getPath());
+ }
+
+ RESOURCES_PATH = configdir;
+ TMP_PATH = tmpdir;
+ CONFIG_PATH = RESOURCES_PATH + CFG + FILE_SEP;
+ CERT_PATH = RESOURCES_PATH + CERT + FILE_SEP;
+
+// ConfigUtils.printConfigInfo(logger_);
+
+ if (defaultConfigDeployedTo != null) {
+ logger_.debug("** Default configuration successfully deployed to \"" + defaultConfigDeployedTo + "\" **");
+ }
+ logger_.debug("Setting system property \"" + Constants.CONFIG_DIR_SYSTEM_PROPERTY + "\" to \"" + configdirFile.getPath() + "\".");
+ System.setProperty(Constants.CONFIG_DIR_SYSTEM_PROPERTY, configdirFile.getPath());
+ }
+
+ public static void initialize(String base_dir)
+ {
+ initialize(base_dir, null);
+ }
+
+ /**
+ * Initializes the paths of the SettingsReader for web application usage.
+ *
+ * @param base_dir
+ * The base directory of this web application. E.g.
+ * TOMCAT_HOME/webapps/pdf-as
+ */
+ public static void initializeForWeb(String base_dir)
+ {
+ initialize(base_dir, base_dir);
+ }
+
+ /**
+ * Initializes the paths of the SettingsReader for commanline usage.
+ */
+ public static void initializeForCommandLine()
+ {
+ initialize(null);
+ }
+
+ static {
+
+ String versionString = "* PDF-AS library version " + PdfAS.PDFAS_VERSION + " *";
+ String paddingString = StringUtils.repeat("*", versionString.length());
+ logger_.info("PDF-AS info\n" + paddingString + "\n" + versionString + "\n" + paddingString);
+ }
+
+ public Properties getProperties() {
+ return this.properties_;
+ }
+
+} \ No newline at end of file
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/commandline/Main.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/commandline/Main.java
new file mode 100644
index 0000000..1b66f53
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/commandline/Main.java
@@ -0,0 +1,1149 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: Main.java,v 1.5 2006/10/31 08:06:56 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.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.commandline.CommandlineConnectorChooser;
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.gv.egiz.pdfas.exceptions.ErrorCodeHelper;
+import at.gv.egiz.pdfas.exceptions.external.ExternalErrorException;
+import at.gv.egiz.pdfas.framework.DataSourceHolder;
+import at.gv.egiz.pdfas.framework.config.SettingsHelper;
+import at.gv.egiz.pdfas.framework.input.DataSource;
+import at.gv.egiz.pdfas.framework.input.ExtractionStage;
+import at.gv.egiz.pdfas.framework.input.PdfDataSource;
+import at.gv.egiz.pdfas.framework.output.DataSink;
+import at.gv.egiz.pdfas.framework.vfilter.VerificationFilterParameters;
+import at.gv.egiz.pdfas.impl.input.FileBasedPdfDataSourceImpl;
+import at.gv.egiz.pdfas.impl.input.TextDataSourceImpl;
+import at.gv.egiz.pdfas.impl.output.FileBasedDataSink;
+import at.knowcenter.wag.egov.egiz.PdfAS;
+import at.knowcenter.wag.egov.egiz.PdfASID;
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorFactoryException;
+import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException;
+import at.knowcenter.wag.egov.egiz.exceptions.PlaceholderException;
+import at.knowcenter.wag.egov.egiz.exceptions.PresentableException;
+import at.knowcenter.wag.egov.egiz.exceptions.SettingNotFoundException;
+import at.knowcenter.wag.egov.egiz.exceptions.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.TablePos;
+import at.knowcenter.wag.egov.egiz.sig.ConnectorFactory;
+import at.knowcenter.wag.egov.egiz.sig.ConnectorInformation;
+import at.knowcenter.wag.egov.egiz.sig.SignatureResponse;
+import at.knowcenter.wag.egov.egiz.sig.SignatureTypes;
+
+/**
+ * The main program entry point of the commandline tool.
+ *
+ * @author wprinz
+ */
+public abstract class Main
+{
+ /**
+ * Command line parameter setting the application mode sign|verify
+ */
+ protected static final String PARAMETER_MODE = "-mode";
+
+ /**
+ * Command line parameter setting the application to connect
+ */
+ protected static final String PARAMETER_CONNECTOR = "-connector";
+
+ /**
+ * Command line parameter setting the signature mode.
+ */
+ protected static final String PARAMETER_SIGNATURE_MODE = "-sigmode";
+
+ /**
+ * Command line parameter setting the signature type.
+ */
+ protected static final String PARAMETER_SIGNATURE_TYPE = "-sigtype";
+
+ /**
+ * Command line parameter setting the username
+ */
+ protected static final String PARAMETER_USER_NAME = "-username";
+
+ /**
+ * Command line parameter setting the users password
+ */
+ protected static final String PARAMETER_USER_PASSWORD = "-password";
+
+ /**
+ * Command line parameter selecting the position of the signature.
+ */
+ protected static final String PARAMETER_POS = "-pos";
+
+ /**
+ * Command line parameter selecting the signature which is going to be
+ * verified.
+ */
+ protected static final String PARAMETER_VERIFY_WHICH = "-verify_which";
+
+ /**
+ * The application mode sign
+ */
+ public static final String VALUE_MODE_SIGN = "sign";
+
+ /**
+ * The application mode verify
+ */
+ public static final String VALUE_MODE_VERIFY = "verify";
+
+ /**
+ * The application mode sign
+ */
+ public static final String VALUE_SIGNATURE_MODE_BINARY = "binary";
+
+ /**
+ * The application mode verify
+ */
+ public static final String VALUE_SIGNATURE_MODE_TEXTUAL = "textual";
+
+ /**
+ * The application mode verify
+ */
+ public static final String VALUE_SIGNATURE_MODE_DETACHED = "detached";
+
+ /**
+ * The application mode verify
+ */
+ public static final String VALUE_SIGNATURE_MODE_DETACHED_TEXT = "detachedtextual";
+
+ /**
+ * The log.
+ */
+ private static final Log logger_ = LogFactory.getLog(Main.class);
+
+ /**
+ * Main program entry point.
+ *
+ * @param args
+ * The commandline arguments.
+ * @throws IOException
+ *
+ * @deprecated use {@link at.gv.egiz.pdfas.commandline.Main} instead
+ */
+ public static void main(String[] args) throws IOException {
+ System.out.println("\nWarning: The entry point at.knowcenter.wag.egov.egiz.commandline.Main is deprecated. Use at.gv.egiz.pdfas.commandline.Main instead.\n");
+ at.gv.egiz.pdfas.commandline.Main.main(args);
+ }
+
+ /*
+ public static void main(String[] args) throws IOException
+ {
+ // ConfigLogger.setLevel(Level.DEBUG);
+
+ SettingsReader.initializeForCommandLine();
+ PropertyConfigurator.configure(SettingsReader.CONFIG_PATH + "log4j.properties");
+
+ // printUsage(System.out);
+
+ String mode = null;
+ String signature_mode = null;
+ String connector = null;
+
+ String signature_type = null;
+ String user_name = null;
+ String user_password = null;
+ String pos_string = null;
+
+ int verify_which = -1;
+
+ String input = null;
+ String output = null;
+
+ try
+ {
+
+ // for (int i = 0; i < args.length; i++)
+ // {
+ // logger_.debug("arg[" + i + "] = " + args[i]);
+ // }
+
+ for (int i = 0; i < args.length; i++)
+ {
+ String cur_arg = args[i].trim();
+
+ if (cur_arg.equals(PARAMETER_MODE))
+ {
+ i++;
+ if (i >= args.length)
+ {
+ printNoValue(PARAMETER_MODE);
+ return;
+ }
+ mode = args[i];
+ if (!checkMode(mode))
+ {
+ printUnrecognizedValue(PARAMETER_MODE, mode);
+ return;
+ }
+ continue;
+ }
+
+ if (cur_arg.equals(PARAMETER_CONNECTOR))
+ {
+ i++;
+ if (i >= args.length)
+ {
+ printNoValue(PARAMETER_CONNECTOR);
+ return;
+ }
+ connector = args[i];
+ if (!checkConnector(connector))
+ {
+ printUnrecognizedValue(PARAMETER_CONNECTOR, connector);
+ return;
+ }
+ continue;
+ }
+
+ if (cur_arg.equals(PARAMETER_SIGNATURE_MODE))
+ {
+ i++;
+ if (i >= args.length)
+ {
+ printNoValue(PARAMETER_SIGNATURE_MODE);
+ return;
+ }
+ signature_mode = args[i];
+ if (!checkSignatureMode(signature_mode))
+ {
+ printUnrecognizedValue(PARAMETER_SIGNATURE_MODE, signature_mode);
+ return;
+ }
+ continue;
+ }
+
+ if (cur_arg.equals(PARAMETER_SIGNATURE_TYPE))
+ {
+ i++;
+ if (i >= args.length)
+ {
+ printNoValue(PARAMETER_SIGNATURE_TYPE);
+ return;
+ }
+ signature_type = args[i];
+ if (!checkSignatureType(signature_type))
+ {
+ printUnrecognizedValue(PARAMETER_SIGNATURE_TYPE, signature_type);
+ return;
+ }
+ continue;
+ }
+
+ if (cur_arg.equals(PARAMETER_USER_NAME))
+ {
+ i++;
+ if (i >= args.length)
+ {
+ printNoValue(PARAMETER_USER_NAME);
+ return;
+ }
+ user_name = args[i];
+ continue;
+ }
+
+ if (cur_arg.equals(PARAMETER_USER_PASSWORD))
+ {
+ i++;
+ if (i >= args.length)
+ {
+ printNoValue(PARAMETER_USER_PASSWORD);
+ return;
+ }
+ user_password = args[i];
+ continue;
+ }
+
+ if (cur_arg.equals(PARAMETER_POS))
+ {
+ i++;
+ if (i >= args.length)
+ {
+ printNoValue(PARAMETER_POS);
+ return;
+ }
+ pos_string = args[i];
+ continue;
+ }
+
+ if (cur_arg.equals(PARAMETER_VERIFY_WHICH))
+ {
+ i++;
+ if (i >= args.length)
+ {
+ printNoValue(PARAMETER_VERIFY_WHICH);
+ return;
+ }
+ String str_verify_which = args[i];
+ try
+ {
+ verify_which = Integer.parseInt(str_verify_which);
+ }
+ catch (NumberFormatException e)
+ {
+ printUnrecognizedValue(PARAMETER_VERIFY_WHICH, str_verify_which);
+ return;
+ }
+
+ continue;
+ }
+
+ if (cur_arg.charAt(0) == '-')
+ {
+ printUnrecognizedOption(cur_arg);
+ return;
+ }
+
+ if (input == null)
+ {
+ input = cur_arg;
+ continue;
+ }
+
+ if (output == null)
+ {
+ output = cur_arg;
+ continue;
+ }
+
+ printUnrecognizedAdditionalCommandlineArgument(cur_arg);
+ return;
+ }
+
+ if (mode == null)
+ {
+ printMissingParameter("a mode", PARAMETER_MODE);
+ return;
+ }
+ if (connector == null)
+ {
+ printMissingParameter("a connector", PARAMETER_CONNECTOR);
+ return;
+ }
+ if (mode.equals(VALUE_MODE_SIGN))
+ {
+ if (signature_mode == null)
+ {
+ printMissingParameter("a signature mode", PARAMETER_SIGNATURE_MODE);
+ return;
+ }
+ if (signature_type == null)
+ {
+ SettingsReader settings = SettingsReader.getInstance();
+ String default_type = settings.getValueFromKey(SignatureTypes.DEFAULT_TYPE);
+ signature_type = default_type;
+ }
+ if (user_name == null)
+ {
+ user_name = "";
+ // printMissingParameter("a user name", PARAMETER_USER_NAME);
+ // return;
+ }
+ if (user_password == null)
+ {
+ user_password = "";
+ // printMissingParameter("a user password", PARAMETER_USER_PASSWORD);
+ // return;
+ }
+ }
+
+ if (input == null)
+ {
+ printMissing("an input document");
+ return;
+ }
+
+ File file = new File(input);
+ if (!file.exists())
+ {
+ System.err.println("The input file '" + input + "' doesn't exist.");
+ return;
+ }
+
+ if (mode.equals(VALUE_MODE_SIGN) && output == null)
+ {
+ output = generateOutputFileNameFromInput(input, signature_mode);
+ }
+
+ carryOutCommand(mode, signature_mode, connector, signature_type, user_name, user_password, verify_which, input, output, pos_string);
+
+ }
+ catch (PresentableException e)
+ {
+ printPresentableException(e);
+
+ if (output != null)
+ {
+ logger_.debug("Deleting output file on error.");
+ File oFile = new File(output);
+ boolean deleted = oFile.delete();
+ if (!deleted)
+ {
+ logger_.error("Couldn't delete output file " + output);
+ }
+ }
+ }
+ finally
+ {
+ SettingsReader.clearTemporaryDirectory();
+ }
+ }
+ */
+
+ protected static void carryOutCommand(final String mode, final String signature_mode, final String connector, final String signature_type, final String user_name, final String user_password,
+ final int verify_which, final String input, String output, final String pos_string) throws PresentableException
+ {
+ // File file = new File(input);
+ //
+ // byte[] input_bytes = null;
+ // try
+ // {
+ // FileInputStream fis = new FileInputStream(file);
+ // input_bytes = new byte[(int) file.length()];
+ // fis.read(input_bytes);
+ // fis.close();
+ // }
+ // catch (IOException e)
+ // {
+ // throw new PDFDocumentException(201);
+ // }
+
+ PrintWriter messageOutput = new PrintWriter(System.out);
+
+
+ if (mode.equals(VALUE_MODE_SIGN))
+ {
+ carryOutSign(input, connector, signature_mode, signature_type, pos_string, user_name, user_password, output, messageOutput);
+ }
+ else
+ {
+ carryOutVerify(input, connector, verify_which, messageOutput);
+ }
+ messageOutput.flush();
+ }
+
+ public static void carryOutSign(String input, String connector, String signature_mode, String signature_type, String pos_string, String user_name, String user_password, String output,
+ PrintWriter messageOutput) throws PresentableException
+ {
+ messageOutput.println("Signing...");
+
+ // for performance measurement
+ long startTime = 0;
+ long fileSize = 0;
+ if (logger_.isInfoEnabled()) {
+ startTime = System.currentTimeMillis();
+ }
+
+ PdfDataSource pdfDataSource;
+ try
+ {
+ File file = new File(input);
+ pdfDataSource = new FileBasedPdfDataSourceImpl(file, (int)file.length());
+ if (logger_.isDebugEnabled())
+ fileSize = file.length();
+
+ }
+ catch (IOException e)
+ {
+ throw new PDFDocumentException(201, e);
+ }
+
+ FileBasedDataSink 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(pdfDataSource, connector, signature_mode, signature_type, pos_string, 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 {
+ 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.");
+ }
+
+ public static void carryOutVerify(String input, String connector, int verify_which, PrintWriter messageOutput) throws PresentableException
+ {
+ messageOutput.println("Verifying...");
+
+ // for performance measurement
+ long startTime = 0;
+ long fileSize = 0;
+ if (logger_.isInfoEnabled()) {
+ startTime = System.currentTimeMillis();
+ }
+
+ DataSource dataSource = null;
+ try
+ {
+ File file = new File(input);
+ if (logger_.isDebugEnabled())
+ fileSize = file.length();
+ String extension = extractExtension(input);
+ if (extension != null && extension.equals("txt"))
+ {
+ try
+ {
+ FileInputStream fis = new FileInputStream(file);
+ byte[] input_bytes = new byte[(int) file.length()];
+ fis.read(input_bytes);
+ fis.close();
+
+ String text = new String(input_bytes, "UTF-8");
+ dataSource = new TextDataSourceImpl(text);
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ throw new RuntimeException("Very strange: UTF-8 character encoding not supported.", e);
+ }
+ }
+ else
+ {
+ dataSource = new FileBasedPdfDataSourceImpl(file, (int)file.length());
+ }
+ }
+ catch (IOException e)
+ {
+ throw new PDFDocumentException(ErrorCode.DOCUMENT_CANNOT_BE_READ, e);
+ }
+
+ List results = processVerify(new DataSourceHolder(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.
+ *
+ * <p>
+ * The extension of a file name is whatever text follows the last '.'.
+ * </p>
+ *
+ * @param file_name
+ * The file name.
+ * @return Returns the extension. If the file name ends with the '.', then an
+ * 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(PdfDataSource pdfDataSource, String connector, String signature_mode, String signature_type, String pos_string, DataSink dataSink) throws PresentableException
+ {
+ pdfDataSource = PdfAS.applyStrictMode(pdfDataSource);
+
+ TablePos pos = null;
+ if (pos_string != null)
+ {
+ try
+ {
+ pos = PdfAS.parsePositionFromPosString(pos_string);
+ }
+ catch (PDFDocumentException e)
+ {
+ printUnrecognizedValue(PARAMETER_POS, pos_string);
+ return;
+
+ }
+ }
+
+ PdfASID signatorId = translateSignatureModeToPdfASID(signature_mode);
+
+ // TODO MOA detached signing is not allowed at the commandline
+// logger_.debug("Suggested sign algorithm = " + signatorId);
+ if (connector.equals("moa"))
+ {
+ // TODO: possible new implementation of moa where is commandline call
+ // supported
+ // it should be checked in config file is it allowed to use MOA detached
+ // from command line.
+// String msg = "Hinweis: Der MOA Detached Connector ist fuer die Kommandozeile nicht geeignet. Die Signatur wird daher im alten Base64 enveloping Format ausgefuehrt.";
+// System.out.println(msg);
+// logger_.warn(msg);
+//
+// if (signature_mode.equals(VALUE_SIGNATURE_MODE_BINARY))
+// {
+// signatorId = BinarySignator_1_0_0.MY_ID;
+// }
+// if (signature_mode.equals(VALUE_SIGNATURE_MODE_TEXTUAL))
+// {
+// signatorId = TextualSignator_1_0_0.MY_ID;
+// }
+ }
+// logger_.debug("Finally used sign algorithm = " + signatorId);
+
+ String connectorId = CommandlineConnectorChooser.chooseCommandlineConnectorForSign(connector);
+
+ PdfAS.signCommandline(pdfDataSource, dataSink, signatorId, connectorId, signature_type, null, pos, null, null);
+
+// PdfAS.sign(algorithm, pdfDataSource, dataSink, signature_type, connector, pos);
+ }
+
+ public static List processVerify(DataSourceHolder dataSource, String connector, int verify_which) throws PresentableException
+ {
+ VerificationFilterParameters parameters = SettingsHelper.readVerificationFilterParametersFromSettings();
+ ExtractionStage es = new ExtractionStage();
+
+ List signature_holders = es.extractSignatureHolders(dataSource, parameters);
+
+ if (signature_holders.isEmpty())
+ {
+ throw new PDFDocumentException(ErrorCode.DOCUMENT_NOT_SIGNED, "Document is unsigned.");
+ }
+
+ List holders_to_verify = signature_holders;
+
+ // verify_which - optional argument in command line/web
+ if (verify_which >= 0)
+ {
+ if (verify_which >= signature_holders.size())
+ {
+ throw new SignatureException(312, "The selected signature to be verified doesn't exist.");
+ }
+
+ SignatureHolder holder = (SignatureHolder) signature_holders.get(verify_which);
+ holders_to_verify = new ArrayList();
+ holders_to_verify.add(holder);
+ }
+
+ List results = PdfAS.verifySignatureHolders(holders_to_verify, connector, false, null);
+
+ return results;
+ }
+
+ // TODO old method - remove
+ // /**
+ // * Generates a suitable output file name for the output regarding the type
+ // of
+ // * the sign_result.
+ // *
+ // * @param input
+ // * The input file name.
+ // * @param sign_result
+ // * The sign result.
+ // * @return Returns the output file name.
+ // */
+ // protected static String generateOutputFileNameFromInput(String input,
+ // SignResult sign_result)
+ // {
+ // String output = input + "_out";
+ // if (sign_result.getMimeType().equals(DetachedSignator_1_0_0.MIME_TYPE))
+ // {
+ // output += ".xml";
+ // }
+ // else
+ // {
+ // output += ".pdf";
+ // }
+ //
+ // return output;
+ // }
+
+ protected static String generateOutputFileNameFromInput(String input, String sig_mode)
+ {
+ String output = input + "_out";
+ if (sig_mode.equals("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 PresentableException e)
+ {
+ if (e.getErrorCode() == ErrorCode.PLACEHOLDER_EXCEPTION)
+ {
+ PlaceholderException phe = null;
+ if (e instanceof PlaceholderException)
+ {
+ phe = (PlaceholderException) e;
+ }
+ else
+ {
+ phe = (PlaceholderException) e.getCause();
+ }
+
+ System.err.println("Der Platzhalter des Feldes " + phe.getField() + " ist um " + phe.getMissing() + " Bytes zu kurz. ");
+ }
+
+ System.err.println("Fehler " + e.getErrorCode() + ": " + ErrorCodeHelper.getMessageForErrorCode(e.getErrorCode()));
+
+ if (e instanceof ExternalErrorException)
+ {
+ ExternalErrorException eee = (ExternalErrorException) e;
+ System.err.println("Externer Fehlergrund: " + eee.getExternalErrorCode() + ": " + eee.getExternalErrorMessage());
+ }
+
+ logger_.error(e);
+ }
+
+ /**
+ * Prints the usage text.
+ *
+ * @param writer
+ * The writer to print the text to.
+ * @throws PresentableException
+ * Forwarded exception.
+ */
+ public static void printUsage(PrintStream writer) throws PresentableException
+ {
+ writer.println("Usage: pdf-as [OPTIONS] <input file> [output file]");
+ writer.println(" Required OPTIONS:");
+
+ writer.println(" " + PARAMETER_MODE + " <" + VALUE_MODE_SIGN + "|" + VALUE_MODE_VERIFY + ">");
+ writer.println(" " + VALUE_MODE_SIGN + " ... signs a document");
+ writer.println(" " + VALUE_MODE_VERIFY + " ... verifies a document");
+
+ writer.print(" " + PARAMETER_CONNECTOR + " ");
+ ConnectorInformation[] ci = ConnectorFactory.getConnectorInformationArray();
+ for (int i = 0; i < ci.length; i++)
+ {
+ String id = ci[i].getIdentifier();
+ if (!ConnectorFactory.isAvailableForCommandline(id))
+ {
+ continue;
+ }
+ writer.print(id);
+ if (i < ci.length - 1)
+ {
+ writer.print("|");
+ }
+ }
+ writer.println();
+ for (int i = 0; i < ci.length; i++)
+ {
+ String id = ci[i].getIdentifier();
+ if (!ConnectorFactory.isAvailableForCommandline(id))
+ {
+ continue;
+ }
+ writer.println(" " + id + " ... " + ci[i].getDescription());
+ }
+
+ writer.println(" OPTIONS for signation:");
+
+ writer.println(" " + PARAMETER_SIGNATURE_MODE + " <" + VALUE_SIGNATURE_MODE_BINARY + "|" + VALUE_SIGNATURE_MODE_TEXTUAL + ">");
+ writer.println(" " + VALUE_SIGNATURE_MODE_BINARY + " ... signs the complete binary document");
+ writer.println(" " + VALUE_SIGNATURE_MODE_TEXTUAL + " ... signs only the textual portion of the document");
+ //writer.println(" " + VALUE_SIGNATURE_MODE_DETACHED + " ... signs the document using the binary mode and returns the xml signature of it.");
+ writer.println(" " + VALUE_SIGNATURE_MODE_DETACHED_TEXT + " ... signs the document using the textual mode and returns the xml signature of it.");
+
+ writer.print(" " + PARAMETER_SIGNATURE_TYPE + " <");
+ SignatureTypes sig_types = SignatureTypes.getInstance();
+ SettingsReader settings = SettingsReader.getInstance();
+ 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 + " <user_name> ... [optional] the user name");
+ writer.println(" " + PARAMETER_USER_PASSWORD + " <password> ... [optional] the user password");
+
+ writer.println(" " + PARAMETER_POS + " <position> ... [optional] the position of the signature block");
+ writer.println(" position has the format [x:x_algo];[y:y_algo];[w:w_algo][p:p_algo];[f:f_algo]");
+ writer.println(" if not present default is set to x:auto;y:auto;w:auto;p:auto;f:0");
+ writer.println(" x_algo:='auto' ... automatic positioning x");
+ writer.println(" floatvalue ... absolute x must be >= 0");
+ writer.println(" y_algo:='auto' ... automatic positioning y");
+ writer.println(" floatvalue ... absolute y must be >= 0");
+ writer.println(" w_algo:='auto' ... automatic width");
+ writer.println(" floatvalue ... absolute width must be > 0");
+ writer.println(" p_algo:='auto' ... automatic last page");
+ writer.println(" 'new' ... new page");
+ writer.println(" intvalue ... pagenumber must be > 0 if p>number of pages in document p-->handled like p:'new'");
+ writer.println(" f_algo floatvalue ... consider footerline must be >= 0 (only if y_algo is auto and p_algo is not 'new')");
+
+ writer.println(" OPTIONS for verification:");
+ writer.println(" " + PARAMETER_VERIFY_WHICH + " <number> ... [optional] zero based number of the signature");
+ writer.println(" to be verified. If omitted, all signatures are verified.");
+
+ writer.println(" Example usage:");
+ writer.println(" pdf-as " + PARAMETER_MODE + " " + VALUE_MODE_SIGN + " " + PARAMETER_CONNECTOR + " moa some_document.pdf");
+ writer.println(" pdf-as " + PARAMETER_MODE + " " + VALUE_MODE_VERIFY + " some_document.pdf_out.pdf");
+ }
+
+ /**
+ * Checks the value for correctness.
+ *
+ * @param mode
+ * The parameter's value.
+ * @return Returns true, if the value is correct, false otherwise.
+ */
+ protected static boolean checkMode(String mode)
+ {
+ return mode.equals(VALUE_MODE_SIGN) || mode.equals(VALUE_MODE_VERIFY);
+ }
+
+ /**
+ * Checks the value for correctness.
+ *
+ * @param signature_mode
+ * The parameter's value.
+ * @return Returns true, if the value is correct, false otherwise.
+ */
+ protected static boolean checkSignatureMode(String signature_mode)
+ {
+ return signature_mode.equals(VALUE_SIGNATURE_MODE_BINARY) || signature_mode.equals(VALUE_SIGNATURE_MODE_TEXTUAL) || signature_mode.equals(VALUE_SIGNATURE_MODE_DETACHED)
+ || signature_mode.equals(VALUE_SIGNATURE_MODE_DETACHED_TEXT);
+ }
+
+ /**
+ * Checks the value for correctness.
+ *
+ * @param connector
+ * The parameter's value.
+ * @return Returns true, if the value is correct, false otherwise.
+ * @throws ConnectorFactoryException
+ * F.e.
+ */
+ protected static boolean checkConnector(String connector) throws ConnectorFactoryException
+ {
+ return ConnectorFactory.isValidConnectorIdentifier(connector) && ConnectorFactory.isAvailableForCommandline(connector);
+ }
+
+ /**
+ * Checks the value for correctness.
+ *
+ * @param signature_type
+ * The parameter's value.
+ * @return Returns true, if the value is correct, false otherwise.
+ */
+ protected static boolean checkSignatureType(String signature_type) throws SignatureTypesException
+ {
+ return SignatureTypes.getInstance().getSignatureTypes().contains(signature_type);
+
+ // exthex: uuuaaaahhhhh WHY??? wprinz again?, dont do that. Use List.contains(o), please
+ // take a java course and read: http://www.amazon.de/Java-f%C3%BCr-Dummies-Barry-Burd/dp/382662999X
+// List types_array = sig_types.getSignatureTypes();
+// Iterator it = types_array.iterator();
+// while (it.hasNext())
+// {
+// String type = (String) it.next();
+// if (type.equals(signature_type))
+// {
+// return true;
+// }
+// }
+// return false;
+ }
+
+ /**
+ * Translates the commandline argument to a PDF-AS-ID.
+ *
+ * @param signature_mode
+ * The signator mode commandline argument.
+ * @return Returns the corresponding PDFASID.
+ */
+ protected static PdfASID translateSignatureModeToPdfASID(String signature_mode)
+ {
+ if (signature_mode.equals(VALUE_SIGNATURE_MODE_BINARY))
+ {
+ return SignatorFactory.MOST_RECENT_BINARY_SIGNATOR_ID;
+ }
+ if (signature_mode.equals(VALUE_SIGNATURE_MODE_TEXTUAL))
+ {
+ return SignatorFactory.MOST_RECENT_TEXTUAL_SIGNATOR_ID;
+ }
+ if (signature_mode.equals(VALUE_SIGNATURE_MODE_DETACHED))
+ {
+ return SignatorFactory.MOST_RECENT_DETACHED_SIGNATOR_ID;
+ }
+ if (signature_mode.equals(VALUE_SIGNATURE_MODE_DETACHED_TEXT))
+ {
+ return SignatorFactory.MOST_RECENT_DETACHEDTEXT_SIGNATOR_ID;
+ }
+ return null;
+ }
+
+ /**
+ * Formats the verification results.
+ *
+ * @param results
+ * The List of SignatureResponse verification results.
+ * @param writer
+ * The output sink to write the formatted text to.
+ * @throws SettingNotFoundException
+ * Forwarded exception.
+ */
+ protected static void formatVerifyResults(List results, PrintWriter writer) throws SettingNotFoundException
+ {
+ Iterator it = results.iterator();
+ while (it.hasNext())
+ {
+ SignatureResponse result = (SignatureResponse) it.next();
+ formatSignatureResponse(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(List results) throws SettingNotFoundException
+ {
+ int toreturn = 0;
+ Iterator it = results.iterator();
+ while (it.hasNext())
+ {
+ SignatureResponse result = (SignatureResponse) it.next();
+
+ toreturn += Integer.valueOf(result.getSignatureCheckCode()).intValue();
+ }
+ return toreturn;
+ }
+
+
+ /**
+ * Formats the SignatureResponse.
+ *
+ * @param result
+ * The SignatureResponse to be printed.
+ * @param writer
+ * The output sink to write the formatted text to.
+ * @throws SettingNotFoundException
+ * Forwarded exception.
+ */
+ public static void formatSignatureResponse(SignatureResponse result, PrintWriter writer) throws SettingNotFoundException
+ {
+
+ writer.println(" Zertifikat:");
+ writer.println(" Signator: " + result.getX509SubjectName());
+ writer.println(" Aussteller: " + result.getX509IssuerName());
+ writer.println(" Seriennummer: " + result.getX509SerialNumber());
+ 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.getCertificateCheckCode() + " - " + result.getCertificateCheckInfo());
+ writer.println(" Signatur-Check:");
+ writer.println(" " + result.getSignatureCheckCode() + " - " + result.getSignatureCheckInfo());
+ writer.println(" Manifest-Check:");
+ writer.println(" " + result.getSignatureManifestCheckCode() + " - " + result.getSignatureManifestCheckInfo());
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/ConnectorException.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/ConnectorException.java
new file mode 100644
index 0000000..9969056
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/ConnectorException.java
@@ -0,0 +1,72 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.exceptions;
+
+/**
+ * This exception is thrown when a Connector encounters an exception during sign
+ * or verify.
+ *
+ * @author wprinz
+ */
+public class ConnectorException extends PresentableException
+{
+
+ /**
+ * SVUID.
+ */
+ private static final long serialVersionUID = 4321130695505581234L;
+
+ /**
+ * @param error_code
+ * @param message
+ * @param cause
+ */
+ public ConnectorException(int error_code, String message, Throwable cause)
+ {
+ super(error_code, message, cause);
+ }
+
+ /**
+ * @param error_code
+ * @param message
+ */
+ public ConnectorException(int error_code, String message)
+ {
+ super(error_code, message);
+ }
+
+ /**
+ * @param error_code
+ * @param cause
+ */
+ public ConnectorException(int error_code, Throwable cause)
+ {
+ super(error_code, cause);
+ }
+
+ public ConnectorException(PresentableException cause)
+ {
+ super(cause.getErrorCode(), cause);
+ }
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/ConnectorFactoryException.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/ConnectorFactoryException.java
new file mode 100644
index 0000000..eb90c5e
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/ConnectorFactoryException.java
@@ -0,0 +1,74 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: ConnectorFactoryException.java,v 1.2 2006/08/25 17:10:34 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.exceptions;
+
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+
+/**
+ * This exception is thrown when the connector factory encounters an error
+ * during providing a connector.
+ *
+ * <p>
+ * The most likely case for this exception is that a wrong connector identifier
+ * was provided.
+ * </p>
+ *
+ * @author wprinz
+ */
+public class ConnectorFactoryException extends PresentableException
+{
+
+ /**
+ * SVUID.
+ */
+ private static final long serialVersionUID = -1398538795243257880L;
+
+ /**
+ * @param message
+ */
+ public ConnectorFactoryException(String message)
+ {
+ super(ErrorCode.SETTINGS_EXCEPTION, message);
+ }
+
+// /**
+// * @param message
+// * @param cause
+// */
+// public ConnectorFactoryException(String message, Throwable cause)
+// {
+// super(message, cause);
+// }
+
+ /**
+ * @param cause
+ */
+ public ConnectorFactoryException(Throwable cause)
+ {
+ super(ErrorCode.SETTINGS_EXCEPTION, cause);
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/ErrorCodeException.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/ErrorCodeException.java
new file mode 100644
index 0000000..dc35582
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/ErrorCodeException.java
@@ -0,0 +1,318 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: ErrorCodeException.java,v 1.1 2006/08/03 07:47:02 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.exceptions;
+
+import org.apache.log4j.Logger;
+
+import at.knowcenter.wag.egov.egiz.cfg.ConfigLogger;
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+
+/**
+ * This exception should be inherit, if an exception should be shown as a
+ * feedback message in user interfaces.
+ *
+ * <p>
+ * The error code is an integer number. The error codes are defined in an
+ * separate configuration file, readed be the SettingsReader. If the
+ * SettingsReader can not initialized, a corresponding error message can not
+ * read!
+ * </p>
+ * <p>
+ * The error code can be seen a a replacement of the exception message. For all
+ * intents and purposes, the error code should be used to provide exceptional
+ * feedback to the user. Nevertheless, if possible, a debug message String (the
+ * message parameter) should still be provided giving in depth developer
+ * descriptions of the problem. These message strings will then show up in the
+ * log files accordingly.
+ * </p>
+ *
+ * @author wlackner
+ * @author wprinz (enforced error code)
+ *
+ * @deprecated
+ *
+ * @see at.knowcenter.wag.egov.egiz.cfg.SettingsReader
+ */
+public class ErrorCodeException extends PresentableException
+{
+ /**
+ * SVUID.
+ */
+ private static final long serialVersionUID = 2071967845179686593L;
+
+ /**
+ * Template key getting error messages
+ */
+ private static final String ERROR_CODE_KEY = "error.code.";
+
+ /**
+ * The default error message
+ */
+ private static final String DEFAULT_ERROR_MESSAGE = "Fehler Code:";
+
+ /**
+ * The logger definition.
+ */
+ private static final Logger logger_ = ConfigLogger.getLogger(ErrorCodeException.class);
+
+ /**
+ * The SettingsReader instance
+ */
+ private SettingsReader settings_ = null;
+
+ /**
+ * The default error code
+ */
+ private int error_code_ = -1;
+
+ /**
+ * If an external application is called
+ */
+ private String externalErrorCode_ = null;
+
+ /**
+ * If an external application is called
+ */
+ private String externalErrorMessage_ = null;
+
+ /**
+ * Constructor that sets the error code.
+ *
+ * @param error_code
+ * The error code.
+ */
+ public ErrorCodeException(final int error_code)
+ {
+ super(error_code, "just an error code");
+ this.error_code_ = error_code;
+ loadSettings();
+ }
+
+ /**
+ * Inherit Constructor from Exception,
+ *
+ * @param error_code
+ * The error code.
+ * @param message
+ * The in depth developer provided error message.
+ * @see Exception
+ */
+ public ErrorCodeException(final int error_code, String message)
+ {
+ super(error_code, message);
+ this.error_code_ = error_code;
+ loadSettings();
+ }
+
+ /**
+ * Inherit Constructor from Exception,
+ *
+ * @param error_code
+ * The error code.
+ * @param message
+ * The in depth developer provided error message.
+ * @param cause
+ * The cause of this exception.
+ * @see Exception
+ */
+ public ErrorCodeException(final int error_code, String message, Throwable cause)
+ {
+ super(error_code, message, cause);
+ this.error_code_ = error_code;
+ loadSettings();
+ }
+
+ /**
+ * Inherit Constructor from Exception,
+ *
+ * @param error_code
+ * The error code.
+ * @param cause
+ * The cause of this exception.
+ * @see Exception
+ */
+ public ErrorCodeException(final int error_code, Throwable cause)
+ {
+ super(error_code, cause);
+ this.error_code_ = error_code;
+ loadSettings();
+ }
+
+ /**
+ * Load the settings file. Call the SettingsReader instance.
+ */
+ private void loadSettings()
+ {
+ if (settings_ == null)
+ {
+ try
+ {
+ settings_ = SettingsReader.getInstance();
+ }
+ catch (SettingsException e)
+ {
+ String log_message = "Can not load pdf signature settings. Cause:\n" + e.getMessage();
+ logger_.error(log_message, e);
+ }
+ }
+ }
+
+ /**
+ * Return the manually stored error code. The error code is only a key for a
+ * configurable error message. The error code and its corresponding message
+ * have to be declared in an separate property file, loaded by the
+ * SettingsReader
+ *
+ * @see at.knowcenter.wag.egov.egiz.cfg.SettingsReader
+ * @return Returns the errorCode.
+ */
+ public int getErrorCode()
+ {
+ return this.error_code_;
+ }
+
+ /**
+ * Set a special error code in case of commuicating this error in an user
+ * interface. The error code is only a key for a configurable error message.
+ * The error code and its corresponding message have to be declared in an
+ * separate property file, loaded by the SettingsReader
+ *
+ * @see at.knowcenter.wag.egov.egiz.cfg.SettingsReader
+ * @param error_code
+ * The error code to be set.
+ */
+ public void setErrorCode(final int error_code)
+ {
+ this.error_code_ = error_code;
+ }
+
+ /**
+ * Set a special error code in case of commuicating this error in an user
+ * interface. The error code is a key for an external application error
+ * message. The error code and its corresponding message have to be declared
+ * by the external tool that used.
+ *
+ * @param errorCode
+ * The errorCode to set.
+ */
+ public void setExternalErrorCode(String errorCode)
+ {
+ externalErrorCode_ = errorCode;
+ }
+
+ /**
+ * Returns an external error code that is set manually
+ *
+ * @return the external error code if set, <code>null</code> otherwise
+ */
+ public String getExternalErrorCode()
+ {
+ return externalErrorCode_;
+ }
+
+ /**
+ * Set a special error message in case of commuicating this error in an user
+ * interface. The error message and its corresponding error code have to be
+ * declared by the external tool that used.
+ *
+ * @param errorMessage
+ */
+ public void setExternalErrorMessage(String errorMessage)
+ {
+ externalErrorMessage_ = errorMessage;
+ }
+
+ /**
+ * Returns an external error message that is set manually
+ *
+ * @return the external error message if set, <code>null</code> otherwise
+ */
+ public String getExternalErrorMessage()
+ {
+ return externalErrorMessage_;
+ }
+
+ /**
+ * Checks if an external error message is set.
+ *
+ * @return returns <code>true</code> if a message is set, <code>false</code>
+ * otherwise
+ */
+ public boolean hasExternalErrorMessage()
+ {
+ return (externalErrorMessage_ != null);
+ }
+
+ /**
+ * Get the configured error message that corresponds to the error code. If the
+ * config file can't be read, or an error code is not declared in the config
+ * file, the default error message would be returned.
+ *
+ * @return an error message that can be used for ui communication
+ */
+ public String getErrorCodeMessage()
+ {
+ String err_msg = null;
+ if (settings_ != null)
+ {
+ err_msg = settings_.getSetting(ERROR_CODE_KEY + error_code_, DEFAULT_ERROR_MESSAGE + error_code_);
+ }
+ return err_msg;
+ }
+
+ /**
+ * Get the configured error message that corresponds to the given error code.
+ * If the config file can't be read, or an error code is not declared in the
+ * config file, the default error message would be returned.
+ *
+ * @return an error message that can be used for ui communication
+ */
+ public static String getErrorCodeMessage(int errorCode)
+ {
+ SettingsReader settings = null;
+ String err_msg = DEFAULT_ERROR_MESSAGE + errorCode;
+ try
+ {
+ settings = SettingsReader.getInstance();
+ err_msg = settings.getSetting(ERROR_CODE_KEY + errorCode, DEFAULT_ERROR_MESSAGE + errorCode);
+ }
+ catch (SettingsException e)
+ {
+ logger_.error(e.getMessage(), e);
+ }
+ return err_msg;
+ }
+
+ /**
+ * Checks if the exception has an ErrorCode state.
+ *
+ * @return true if an ErrorCode does exist false otherwise
+ */
+ public boolean hasErrorCode()
+ {
+ return error_code_ != 0;
+ }
+} \ No newline at end of file
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/InvalidIDException.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/InvalidIDException.java
new file mode 100644
index 0000000..ae3a2f8
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/InvalidIDException.java
@@ -0,0 +1,55 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: InvalidIDException.java,v 1.1 2006/08/25 17:10:34 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.exceptions;
+
+/**
+ * Thrown when parsing an ID ("Kennzeichnung") fails.
+ * @author wprinz
+ */
+public class InvalidIDException extends SignatureException
+{
+
+ /**
+ * SVUID.
+ */
+ private static final long serialVersionUID = -7945398356854048254L;
+
+ public InvalidIDException(int error_code, String message, Throwable cause)
+ {
+ super(error_code, message, cause);
+ }
+
+ public InvalidIDException(int error_code, String message)
+ {
+ super(error_code, message);
+ }
+
+ public InvalidIDException(int error_code, Throwable cause)
+ {
+ super(error_code, cause);
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/NormalizeException.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/NormalizeException.java
new file mode 100644
index 0000000..0f8f145
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/NormalizeException.java
@@ -0,0 +1,62 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: NormalizeException.java,v 1.1 2006/08/03 07:47:02 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.exceptions;
+
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+
+
+/**
+ * This exception is thrown by the processing a normalizer.
+ *
+ * @author wlackner
+ */
+public class NormalizeException extends PresentableException {
+
+ /**
+ * SVUID.
+ */
+ private static final long serialVersionUID = -4080682145462891501L;
+
+ /**
+ * @param error_code
+ * @param message
+ * @param cause
+ */
+ public NormalizeException(String message, Throwable cause)
+ {
+ super(ErrorCode.NORMALIZER_EXCEPTION, message, cause);
+ }
+
+ /**
+ * @param error_code
+ * @param message
+ */
+ public NormalizeException(String message)
+ {
+ super(ErrorCode.NORMALIZER_EXCEPTION, message);
+ }
+
+} \ No newline at end of file
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/OutOfMemoryException.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/OutOfMemoryException.java
new file mode 100644
index 0000000..ec2ccb3
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/OutOfMemoryException.java
@@ -0,0 +1,42 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.exceptions;
+
+public class OutOfMemoryException extends PresentableException {
+
+ private static final long serialVersionUID = 1L;
+
+ public OutOfMemoryException(int errorCode, String message, Throwable cause) {
+ super(errorCode, message, cause);
+ }
+
+ public OutOfMemoryException(int errorCode, String message) {
+ super(errorCode, message);
+ }
+
+ public OutOfMemoryException(int errorCode, Throwable cause) {
+ super(errorCode, cause);
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/PDFDocumentException.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/PDFDocumentException.java
new file mode 100644
index 0000000..7fb4c8d
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/PDFDocumentException.java
@@ -0,0 +1,70 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: PDFDocumentException.java,v 1.1 2006/08/03 07:47:02 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.exceptions;
+
+/**
+ * This exception is thrown in case of problems using pdf librarys.
+ *
+ * @author wlackner
+ */
+public class PDFDocumentException extends PresentableException
+{
+
+ /**
+ * SVUID.
+ */
+ private static final long serialVersionUID = -4595955288382226408L;
+
+ /**
+ * @param error_code
+ * @param message
+ * @param cause
+ */
+ public PDFDocumentException(int error_code, String message, Throwable cause)
+ {
+ super(error_code, message, cause);
+ }
+
+ /**
+ * @param error_code
+ * @param message
+ */
+ public PDFDocumentException(int error_code, String message)
+ {
+ super(error_code, message);
+ }
+
+ /**
+ * @param error_code
+ * @param cause
+ */
+ public PDFDocumentException(int error_code, Throwable cause)
+ {
+ super(error_code, cause);
+ }
+
+
+} \ No newline at end of file
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/PlaceholderException.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/PlaceholderException.java
new file mode 100644
index 0000000..5697edc
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/PlaceholderException.java
@@ -0,0 +1,66 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: PlaceholderException.java,v 1.1 2006/08/25 17:10:34 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.exceptions;
+
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+
+/**
+ * @author wprinz
+ */
+public class PlaceholderException extends PDFDocumentException
+{
+ /**
+ * SVUID.
+ */
+ private static final long serialVersionUID = -9149805408421810170L;
+
+
+ protected String field = null;
+ protected int missing = -1;
+
+ public PlaceholderException(String field, int missing)
+ {
+ super(ErrorCode.PLACEHOLDER_EXCEPTION, field + ":" + missing);
+
+ this.field = field;
+ this.missing = missing;
+ }
+
+ public void setField (String field)
+ {
+ this.field = field;
+ }
+
+ public String getField()
+ {
+ return this.field;
+ }
+
+ public int getMissing()
+ {
+ return this.missing;
+ }
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/PresentableException.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/PresentableException.java
new file mode 100644
index 0000000..40d7181
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/PresentableException.java
@@ -0,0 +1,68 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: PresentableException.java,v 1.2 2006/08/25 17:10:34 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.exceptions;
+
+import at.gv.egiz.pdfas.api.exceptions.PdfAsException;
+
+/**
+ * This exception should be the base for all exceptions that are to be presented
+ * to the user.
+ *
+ * <p>
+ * For example, exceptions that signal that a pdf file is corrupt should be
+ * represented as presentable exceptions so that the user interface frontends
+ * can present according texts.
+ * </p>
+ *
+ * @see PdfAsException
+ *
+ * @author wprinz
+ */
+public class PresentableException extends PdfAsException
+{
+
+ /**
+ * SVUID.
+ */
+ private static final long serialVersionUID = -102406558526000792L;
+
+ public PresentableException(int errorCode, String message, Throwable cause)
+ {
+ super(errorCode, message, cause);
+ }
+
+ public PresentableException(int errorCode, String message)
+ {
+ super(errorCode, message);
+ }
+
+ public PresentableException(int errorCode, Throwable cause)
+ {
+ super(errorCode, cause);
+ }
+
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/SettingNotFoundException.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/SettingNotFoundException.java
new file mode 100644
index 0000000..6c140eb
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/SettingNotFoundException.java
@@ -0,0 +1,77 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: SettingNotFoundException.java,v 1.1 2006/08/03 07:47:03 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.exceptions;
+
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+
+/**
+ * This exception is thrown by the SettingsReader if a property key is not
+ * found.
+ *
+ * @author wlackner
+ */
+public class SettingNotFoundException extends PresentableException
+{
+
+ /**
+ * SVUID.
+ */
+ private static final long serialVersionUID = -7502191288775676006L;
+
+ /**
+ * @param error_code
+ * @param message
+ * @param cause
+ */
+ public SettingNotFoundException(String message, Throwable cause)
+ {
+ super(ErrorCode.SETTING_NOT_FOUND, message, cause);
+ }
+
+ /**
+ * @param error_code
+ * @param message
+ */
+ public SettingNotFoundException(String message)
+ {
+ super(ErrorCode.SETTING_NOT_FOUND, message);
+ }
+
+ /**
+ * @param error_code
+ * @param cause
+ */
+ public SettingNotFoundException(Throwable cause)
+ {
+ super(ErrorCode.SETTING_NOT_FOUND, cause);
+ }
+
+ protected SettingNotFoundException(int errorCode, String message)
+ {
+ super(errorCode, message);
+ }
+
+} \ No newline at end of file
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/SettingsException.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/SettingsException.java
new file mode 100644
index 0000000..a43de6a
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/SettingsException.java
@@ -0,0 +1,74 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: SettingsException.java,v 1.2 2006/08/25 17:10:34 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.exceptions;
+
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+
+/**
+ * Thrown when the settings couldn't be loaded.
+ *
+ * <p>
+ * This is most likely the case when the config file isn't found or when the
+ * settings are corrupt.
+ * </p>
+ *
+ * @author wprinz
+ */
+public class SettingsException extends PresentableException {
+
+ /**
+ * SVUID.
+ */
+ private static final long serialVersionUID = -99979541706943372L;
+
+ /**
+ * @param message
+ */
+ public SettingsException(String message) {
+ super(ErrorCode.SETTINGS_EXCEPTION, message);
+ }
+
+ /**
+ * @param message
+ * @param cause
+ */
+ public SettingsException(String message, Throwable cause) {
+ super(ErrorCode.SETTINGS_EXCEPTION, message, cause);
+ }
+
+ public SettingsException(int errorCode, String message, Throwable cause) {
+ super(errorCode, message, cause);
+ }
+
+ public SettingsException(int errorCode, String message) {
+ super(errorCode, message);
+ }
+
+ public SettingsException(int errorCode, Throwable cause) {
+ super(errorCode, cause);
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/SignatorFactoryException.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/SignatorFactoryException.java
new file mode 100644
index 0000000..e9e6af0
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/SignatorFactoryException.java
@@ -0,0 +1,47 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: SignatorFactoryException.java,v 1.1 2006/08/25 17:10:34 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.exceptions;
+
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+
+/**
+ * Exception coming out of the SignatorFactory.
+ * @author wprinz
+ */
+public class SignatorFactoryException extends PresentableException
+{
+
+ /**
+ * SVUID.
+ */
+ private static final long serialVersionUID = -4051644056058970435L;
+
+ public SignatorFactoryException(String message)
+ {
+ super(ErrorCode.SETTINGS_EXCEPTION, message);
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/SignatureException.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/SignatureException.java
new file mode 100644
index 0000000..5b0d458
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/SignatureException.java
@@ -0,0 +1,79 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: SignatureException.java,v 1.1 2006/08/03 07:47:03 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.exceptions;
+
+
+/**
+ * This exception is thrown by the processing a signature.
+ *
+ * @author wlackner
+ */
+public class SignatureException extends PresentableException {
+
+ /**
+ * SVUID.
+ */
+ private static final long serialVersionUID = 6387300820234118374L;
+
+ /**
+ * @param error_code
+ * @param message
+ * @param cause
+ */
+ public SignatureException(int error_code, String message, Throwable cause)
+ {
+ super(error_code, message, cause);
+ }
+
+ /**
+ * @param error_code
+ * @param message
+ */
+ public SignatureException(int error_code, String message)
+ {
+ super(error_code, message);
+ }
+
+ /**
+ * @param error_code
+ * @param cause
+ */
+ public SignatureException(int error_code, Throwable cause)
+ {
+ super(error_code, cause);
+ }
+
+ /**
+ * @param error_code
+ * @param cause
+ */
+ public SignatureException(PresentableException cause)
+ {
+ super(cause.getErrorCode(), cause);
+ }
+
+
+} \ No newline at end of file
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/SignatureTypesException.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/SignatureTypesException.java
new file mode 100644
index 0000000..279d46f
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/SignatureTypesException.java
@@ -0,0 +1,75 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: SignatureTypesException.java,v 1.2 2006/08/25 17:10:34 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.exceptions;
+
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+
+/**
+ * Exception for Signature Type problems.
+ *
+ * @author wprinz
+ */
+public class SignatureTypesException extends PresentableException
+{
+
+ /**
+ * SVUID.
+ */
+ private static final long serialVersionUID = -7899273202684297943L;
+
+ /**
+ * @param message
+ */
+ public SignatureTypesException(String message)
+ {
+ super(ErrorCode.SIGNATURE_TYPES_EXCEPTION, message);
+ }
+
+// /**
+// * @param message
+// * @param cause
+// */
+// public SignatureTypesException(String message, Throwable cause)
+// {
+// super(ErrorCode.SIGNATURE_TYPES_EXCEPTION, message, cause);
+// }
+
+ // /**
+ // * @param cause
+ // */
+ // public SignatureTypesException(Throwable cause)
+ // {
+ // super(ErrorCode.SIGNATURE_TYPES_EXCEPTION, cause);
+ // }
+
+ /**
+ * @param cause
+ */
+ public SignatureTypesException(PresentableException cause)
+ {
+ super(cause.getErrorCode(), cause);
+ }
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/WebException.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/WebException.java
new file mode 100644
index 0000000..8fbdda7
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/exceptions/WebException.java
@@ -0,0 +1,72 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: WebException.java,v 1.2 2006/08/25 17:10:34 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.exceptions;
+
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+
+
+/**
+ * Exception for web problems.
+ * @author wlackner
+ */
+public class WebException extends PresentableException {
+
+ /**
+ * SVUID.
+ */
+ private static final long serialVersionUID = 4329890155872840492L;
+
+// /**
+// * @param error_code
+// * @param message
+// * @param cause
+// */
+// public WebException(int error_code, String message, Throwable cause)
+// {
+// super(error_code, message, cause);
+// }
+//
+// /**
+// * @param error_code
+// * @param message
+// */
+// public WebException(int error_code, String message)
+// {
+// super(error_code, message);
+// }
+//
+
+ /**
+ * @param error_code
+ * @param cause
+ */
+ public WebException(Throwable cause)
+ {
+ super(ErrorCode.WEB_EXCEPTION, cause);
+ }
+
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/FoundBlock.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/FoundBlock.java
new file mode 100644
index 0000000..4076129
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/FoundBlock.java
@@ -0,0 +1,230 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: FoundBlock.java,v 1.2 2006/10/31 08:07:29 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.framework;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import at.knowcenter.wag.egov.egiz.sig.SignatureTypeDefinition;
+import at.knowcenter.wag.egov.egiz.sig.SignatureTypes;
+
+/**
+ * Contains all the information about a found Block in text extracton.
+ *
+ * <p>
+ * This is basically the ordered list of found captions.
+ * </p>
+ *
+ * @author wprinz
+ */
+public class FoundBlock
+{
+ /**
+ * The ordered list of found keys.
+ */
+ public List found_keys = null;
+
+ /**
+ * The end index of the block.
+ */
+ public int end_index = 0;
+
+ /**
+ * The type of the block.
+ */
+ public SignatureTypeDefinition std = null;
+
+ /**
+ * Returns the first key of this block.
+ *
+ * @return Returns the first key of this block.
+ */
+ public FoundKey getFirstKey()
+ {
+ return (FoundKey) this.found_keys.get(found_keys.size() - 1);
+ }
+
+ /**
+ * Returns the last key of this block.
+ *
+ * @return Returns the last key of this block.
+ */
+ public FoundKey getLastKey()
+ {
+ return (FoundKey) this.found_keys.get(0);
+ }
+
+ /**
+ * Returns the size of this block.
+ *
+ * <p>
+ * Note that this doesn't give the exact size of the block, but rather a value
+ * suirable for comparison.
+ * </p>
+ *
+ * @return Returns the size of this block.
+ */
+ public int getSize()
+ {
+ int size = getLastKey().start_index - getFirstKey().start_index;
+ return size;
+ }
+
+ /**
+ * @see java.lang.Object#toString()
+ */
+ public String toString()
+ {
+ return "FoundBlock: std=" + this.std.getType() + ", #=" + this.found_keys.size() + ", size = " + getSize();
+ }
+
+ /**
+ * Tells, if this block is semantically equal to the other block.
+ *
+ * Two blocks are semantically equal, if all the required fields (except SIG_ID) have the
+ * same captions in the same order.
+ *
+ * @param other_block
+ * The other block.
+ * @return Returns true, of this block is semantically equal to the other one,
+ * false otherwise.
+ */
+ public boolean isSemanticallyEqual(FoundBlock other_block)
+ {
+ return this.std.isSemanticallyEqual(other_block.std);
+
+// List this_keys = filterOutNonRequiredFoundKeys(filterOutSIG_ID(this.found_keys));
+// List other_keys = filterOutNonRequiredFoundKeys(filterOutSIG_ID(other_block.found_keys));
+//
+// if (this_keys.size() != other_keys.size())
+// {
+// return false;
+// }
+//
+// for (int i = 0; i < this_keys.size(); i++)
+// {
+// FoundKey this_found_key = (FoundKey) this_keys.get(i);
+// FoundKey other_found_key = (FoundKey) other_keys.get(i);
+//
+// if (!this_found_key.isSemanticallyEqual(other_found_key))
+// {
+// return false;
+// }
+// }
+// return true;
+ }
+
+ /**
+ * Filters out all non required keys from the List of found keys.
+ *
+ * @param found_keys The List of found keys.
+ *
+ * @return Returns the subset List which contains only the required keys.
+ */
+ protected static List filterOutNonRequiredFoundKeys (List found_keys)
+ {
+ List required_found_keys = new ArrayList(found_keys.size());
+ for (int i = 0; i < found_keys.size(); i++)
+ {
+ FoundKey this_found_key = (FoundKey) found_keys.get(i);
+
+ if (!SignatureTypes.isRequiredKey(this_found_key.key))
+ {
+ continue;
+ }
+
+ required_found_keys.add(this_found_key);
+ }
+ return required_found_keys;
+ }
+
+ /**
+ * Filters out a SIG_ID found key.
+ * @param found_keys The List of found keys.
+ * @return Returns the subset List which contains all keys but the SIG_ID.
+ */
+ protected static List filterOutSIG_ID (List found_keys)
+ {
+ List nonsigid_found_keys = new ArrayList(found_keys.size());
+ for (int i = 0; i < found_keys.size(); i++)
+ {
+ FoundKey this_found_key = (FoundKey) found_keys.get(i);
+
+ if (this_found_key.key.equals(SignatureTypes.SIG_ID))
+ {
+ continue;
+ }
+
+ nonsigid_found_keys.add(this_found_key);
+ }
+ return nonsigid_found_keys;
+ }
+
+ /**
+ * Tells, if this block is strictly semantically equal to the other block.
+ *
+ * Two blocks are strictly semantically equal, if they contain the same keys with the
+ * same captions in the same order.
+ *
+ * @param other_block
+ * The other block.
+ * @return Returns true, of this block is semantically equal to the other one,
+ * false otherwise.
+ */
+ public boolean isStrictlySemanticallyEqual(FoundBlock other_block)
+ {
+ if (this.found_keys.size() != other_block.found_keys.size())
+ {
+ return false;
+ }
+
+ for (int i = 0; i < this.found_keys.size(); i++)
+ {
+ FoundKey this_found_key = (FoundKey) this.found_keys.get(i);
+ FoundKey other_found_key = (FoundKey) other_block.found_keys.get(i);
+
+ if (!this_found_key.isSemanticallyEqual(other_found_key))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+
+ public FoundKey getDateFoundKey ()
+ {
+ for (int i = 0; i < this.found_keys.size(); i++)
+ {
+ FoundKey found_key = (FoundKey) this.found_keys.get(i);
+ if (found_key.key.equals(SignatureTypes.SIG_DATE))
+ {
+ return found_key;
+ }
+ }
+ throw new RuntimeException("There is no SIG_DATE in the list of found_keys. This must not happen.");
+ }
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/FoundKey.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/FoundKey.java
new file mode 100644
index 0000000..b8e9609
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/FoundKey.java
@@ -0,0 +1,104 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: FoundKey.java,v 1.1 2006/08/25 17:07:21 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.framework;
+
+/**
+ * Holds the information of one found key.
+ * @author wprinz
+ */
+public class FoundKey
+{
+ /**
+ * The type of the key.
+ */
+ public String key = null;
+
+ /**
+ * The caption of the key.
+ */
+ public String caption = null;
+
+ /**
+ * The start index of the caption in the text.
+ */
+ public int start_index = -1;
+
+ /**
+ *
+ * @param key The type of the key.
+ * @param caption The caption of the key.
+ * @param start_index The start index of the caption in the text.
+ */
+ public FoundKey(String key, String caption, int start_index)
+ {
+ this.key = key;
+ this.caption = caption;
+ this.start_index = start_index;
+ }
+
+ /**
+ * Returns the key.
+ * @return Returns the key.
+ */
+ public String getKey()
+ {
+ return this.key;
+ }
+
+ /**
+ * Returns the start_index.
+ * @return Returns the start_index.
+ */
+ public int getStartIndex()
+ {
+ return this.start_index;
+ }
+
+ /**
+ * @see java.lang.Object#toString()
+ */
+ public String toString()
+ {
+ return this.key + "(" + this.caption + ")@" + this.start_index;
+ }
+
+ /**
+ * Tells, if this FoundKey is semantically equal to the other FoundKey.
+ *
+ * <p>
+ * Two FoundKeys are semantically equal if their key and caption are the same.
+ * </p>
+ *
+ * @param other_found_key
+ * The other FoundKey.
+ * @return Returns true if the two keys are semantically equal.
+ */
+ public boolean isSemanticallyEqual(FoundKey other_found_key)
+ {
+ return this.key.equals(other_found_key.key) && this.caption.equals(other_found_key.caption);
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/SignResult.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/SignResult.java
new file mode 100644
index 0000000..5471d86
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/SignResult.java
@@ -0,0 +1,104 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: SignResult.java,v 1.1 2006/08/25 17:07:21 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.framework;
+
+import java.io.Serializable;
+
+/**
+ * This class holds the signed document, which is given by the mime type and the
+ * binary data.
+ *
+ * @author wprinz
+ */
+public class SignResult implements Serializable
+{
+ /**
+ * SVUID.
+ */
+ private static final long serialVersionUID = -6664489317508509973L;
+
+ /**
+ * The mime type of the data specifying the type of the document.
+ */
+ protected String mime_type = null;
+
+ /**
+ * The binary data of the document.
+ */
+ protected byte[] data = null;
+
+ /**
+ * Constructor.
+ *
+ * @param document_mime_type
+ * The mime type of the data specifying the type of the document.
+ * @param document_data
+ * The binary data of the document.
+ */
+ public SignResult(String document_mime_type, byte[] document_data)
+ {
+ if (document_mime_type == null || document_mime_type.length() == 0)
+ {
+ throw new IllegalArgumentException("Please provide a valid Mime Type for the SignResult. " + document_mime_type);
+ }
+ if (document_data == null)
+ {
+ throw new IllegalArgumentException("Please provide document data. " + document_data);
+ }
+
+ this.mime_type = document_mime_type;
+ this.data = document_data;
+ }
+
+ /**
+ * Returns the binary data.
+ *
+ * @return Returns the binary data.
+ */
+ public byte[] getData()
+ {
+ return this.data;
+ }
+
+ /**
+ * Returns the mime type.
+ *
+ * @return Returns the mime type.
+ */
+ public String getMimeType()
+ {
+ return this.mime_type;
+ }
+
+ /**
+ * @see java.lang.Object#toString()
+ */
+ public String toString()
+ {
+ return "SignResult:" + this.mime_type + "," + this.data.length;
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/Signator.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/Signator.java
new file mode 100644
index 0000000..88a6ea1
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/Signator.java
@@ -0,0 +1,93 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: Signator.java,v 1.1 2006/08/25 17:07:21 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.framework;
+
+import at.gv.egiz.pdfas.framework.input.PdfDataSource;
+import at.knowcenter.wag.egov.egiz.PdfASID;
+import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException;
+import at.knowcenter.wag.egov.egiz.exceptions.PresentableException;
+import at.knowcenter.wag.egov.egiz.pdf.IncrementalUpdateInformation;
+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.
+ *
+ * <p>
+ * This should always return the MY_ID static field of the connector. Dont't
+ * forget to override this.
+ * </p>
+ * <p>
+ * Within connector code always use this method so that code reuse through
+ * derivation can take place correctly.
+ * </p>
+ *
+ * @return Returns the PdfASID of this Connector.
+ */
+ public PdfASID getMyId();
+
+ /**
+ * This is called before the data is sent to the connector.
+ *
+ * @param pdf
+ * The PDF document to be signed.
+ * @param signature_type
+ * The type/profile of the signature to apply.
+ * @param pos
+ * The table position. If null, the position is read from the
+ * profile, if this is null too, the position is computed.
+ * @param has_SIG_ID
+ * Tells the algorithm, id a SIG_ID field will be required after
+ * signing. Algorithms with fixed formatted signature blocks need to
+ * know this.
+ * @return Returns the IncrementalUpdateInformation.
+ * @throws PresentableException
+ * Forwarded exception.
+ */
+ public IncrementalUpdateInformation prepareSign(PdfDataSource pdfDataSource,
+ String signature_type, TablePos pos, boolean has_SIG_ID) throws PresentableException;
+
+ /**
+ * This is called after the data has been signed by the connector.
+ *
+ * <p>
+ * Replaces all the left out placeholders with their values retrieved from the
+ * signation process.
+ * </p>
+ *
+ * @param iui
+ * The IncrementalUpdateInformation.
+ * @throws PDFDocumentException
+ * Forwarded exception.
+ */
+ public SignResult finishSign(IncrementalUpdateInformation iui) throws PresentableException;
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/SignatorFactory.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/SignatorFactory.java
new file mode 100644
index 0000000..ccb414d
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/SignatorFactory.java
@@ -0,0 +1,226 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: SignatorFactory.java,v 1.2 2006/08/30 14:02:35 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.framework;
+
+import at.gv.egiz.pdfas.impl.signator.textual.TextualSignator_1_2_0;
+import at.knowcenter.wag.egov.egiz.PdfASID;
+import at.knowcenter.wag.egov.egiz.exceptions.SignatorFactoryException;
+import at.knowcenter.wag.egov.egiz.framework.signators.BinarySignator_1_0_0;
+import at.knowcenter.wag.egov.egiz.framework.signators.BinarySignator_1_1_0;
+import at.knowcenter.wag.egov.egiz.framework.signators.DetachedSignator_1_0_0;
+import at.knowcenter.wag.egov.egiz.framework.signators.DetachedfTextualSignator_1_0_0;
+import at.knowcenter.wag.egov.egiz.framework.signators.TextualSignator_1_0_0;
+import at.knowcenter.wag.egov.egiz.framework.signators.TextualSignator_1_1_0;
+
+/**
+ * This factory creates instances of Signator classes corresponding to the given
+ * PdfAS Algorithm IDs.
+ *
+ * @author wprinz
+ */
+public abstract 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$
+
+ /**
+ * This signator is only for testing the framework.
+ */
+ public static final String TYPE_TEST = "testalgo"; //$NON-NLS-1$
+
+ /**
+ * This signator is only for testing the framework.
+ */
+ 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$
+
+
+ /**
+ * The most recent binary algorithm this application provides.
+ */
+ public static final PdfASID MOST_RECENT_BINARY_SIGNATOR_ID = BinarySignator_1_1_0.MY_ID;
+
+ /**
+ * The most recent textual algorithm this application provides.
+ */
+ public static final PdfASID MOST_RECENT_TEXTUAL_SIGNATOR_ID = TextualSignator_1_2_0.MY_ID;
+
+ /**
+ * The most recent test algorithm this application provides.
+ */
+ public static final PdfASID MOST_RECENT_DETACHED_SIGNATOR_ID = DetachedfTextualSignator_1_0_0.MY_ID;
+
+ /**
+ * The most recent test algorithm this application provides.
+ */
+ public static final PdfASID MOST_RECENT_DETACHEDTEXT_SIGNATOR_ID = DetachedfTextualSignator_1_0_0.MY_ID;
+
+
+ /**
+ * Creates a Signator for the given ID.
+ *
+ * @param id
+ * The ID of the Signator to be created.
+ * @return Returns the created Signator object.
+ * @throws SignatorFactoryException
+ * Thrown, if there is no appropriate Signator for the given ID.
+ */
+ 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();
+ }
+
+ 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_TEST))
+ {
+ if (id.getVersion().equals(VERSION_1_0_0))
+ {
+ return new DetachedSignator_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$
+ }
+
+ if (id.getType().equals(TYPE_DETACHED_TEXTUAL))
+ {
+ if (id.getVersion().equals(VERSION_1_0_0))
+ {
+ return new DetachedfTextualSignator_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$
+ }
+
+ /**
+ * Creates the most recent signator the application provides for the given
+ * type.
+ *
+ * @param signator_type
+ * The type of the signator to be created (see the type field of
+ * PdfASID).
+ * @return Returns the created Signator instance.
+ * @throws SignatorFactoryException
+ * Thrown, if the type is unknown.
+ */
+ public static Signator createMostRecentSignator(String signator_type) throws SignatorFactoryException
+ {
+ PdfASID id = null;
+ if (signator_type.equals(TYPE_BINARY))
+ {
+ id = MOST_RECENT_BINARY_SIGNATOR_ID;
+ }
+ if (signator_type.equals(TYPE_TEXTUAL))
+ {
+ id = MOST_RECENT_TEXTUAL_SIGNATOR_ID;
+ }
+ if (signator_type.equals(TYPE_TEST))
+ {
+ id = MOST_RECENT_TEXTUAL_SIGNATOR_ID;
+ }
+
+ if (id == null)
+ {
+ throw new SignatorFactoryException("The type '" + signator_type + "' is not supported by this SignatorFactory."); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ return createSignator(id);
+ }
+
+ /**
+ * Returns the list of available Signator algorithms of this application.
+ *
+ * <p>
+ * Use createMostRecentSignator to create the most recent signator for the
+ * type.
+ * </p>
+ *
+ * @return Returns the list of available Signator algorithms of this
+ * application.
+ */
+ public static String[] getAvailableTyes()
+ {
+ String[] types = new String[] { TYPE_BINARY, TYPE_TEXTUAL, TYPE_TEST };
+ return types;
+ }
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/VerificationFilter.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/VerificationFilter.java
new file mode 100644
index 0000000..0bab96f
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/VerificationFilter.java
@@ -0,0 +1,569 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: VerificationFilter.java,v 1.5 2006/10/31 08:07:20 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.framework;
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.gv.egiz.pdfas.impl.vfilter.VerificationFilterImpl;
+import at.knowcenter.wag.egov.egiz.PdfAS;
+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.InvalidIDException;
+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.exceptions.SignatureTypesException;
+import at.knowcenter.wag.egov.egiz.framework.verificators.BinaryVerificator_1_0_0;
+import at.knowcenter.wag.egov.egiz.framework.verificators.TextualVerificator_1_0_0;
+import at.knowcenter.wag.egov.egiz.pdf.AbsoluteTextSignature;
+import at.knowcenter.wag.egov.egiz.pdf.BinarySignature;
+import at.knowcenter.wag.egov.egiz.pdf.Placeholder;
+import at.knowcenter.wag.egov.egiz.pdf.SignatureHolder;
+import at.knowcenter.wag.egov.egiz.pdf.StringInfo;
+import at.knowcenter.wag.egov.egiz.pdf.TextualSignatureHolder;
+import at.knowcenter.wag.exactparser.ParseDocument;
+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;
+
+
+/**
+ * This filter transforms an arbitrary input pdf into an ordered List of
+ * SignatureHolders for verification.
+ *
+ * <p>
+ * The pdf document is parsed and the signature blocks (textual, binary, etc.)
+ * are extracted as verifyable SignatureHolder objects in the order they appear
+ * in the document.
+ * </p>
+ *
+ * @deprecated use the new at.gv.egiz.framework instead
+ *
+ * @author wprinz
+ * @author amavriqi
+ */
+public class VerificationFilter
+{
+ public static final byte[] EGIZ_DICT_NAME = { 'E', 'G', 'I', 'Z', 'S', 'i',
+ 'g', 'D', 'i', 'c', 't' };
+
+ public static final byte[] EGIZ_KZ_NAME = { 'I', 'D' };
+
+ //tzefferer: flag for accepting post-sign modifications
+ public static final String ALLOW_POST_SIGN_MODIFICATIONS = "allow_post_sign_modifications";
+
+ /**
+ * The logger definition.
+ */
+ private static final Logger logger_ = ConfigLogger.getLogger(VerificationFilter.class);
+
+ /**
+ * Default constructor.
+ */
+ public VerificationFilter()
+ {
+ // empty block.
+ }
+
+ /**
+ * Extracts the List of SignatureHolders from the given PDF document.
+ *
+ * @param pdf
+ * The PDF document.
+ * @return Returns the ordered List of SignatureHolder objects (the first
+ * signature will be at index 0) extracted from the document or an
+ * empty list, if none could be found.
+ * @throws PresentableException
+ */
+ public List extractSignaturesFromPdf(final byte[] pdf) throws PresentableException
+ {
+ return extractSignaturesFromPdf(pdf, false);
+ }
+
+ //@deprecated
+ public List extractSignaturesFromPdf(final byte[] pdf, boolean ignorePostSignModificationsRestriction) throws PresentableException
+ {
+
+ // tzefferer: get allow_post_sign_modifications property from property file
+ SettingsReader settings = SettingsReader.getInstance();
+ String allow_post_sign_mods = settings.getSetting(ALLOW_POST_SIGN_MODIFICATIONS, "false");
+ boolean supressException = "true".equalsIgnoreCase(settings.getSetting(VerificationFilterImpl.SUPRESS_EXCEPTION_WHEN_LAST_UIBLOCK_IS_NO_SIGNATURE, "false"));
+
+ List holders = new ArrayList();
+
+ List blocks = null;
+ try
+ {
+ blocks = ParseDocument.parseDocument(pdf);
+ }
+ catch (Exception e)
+ {
+ logger_.debug("Error while parsing Document.", e);
+ throw new PDFDocumentException(201, e);
+ }
+
+// for (int i = 0; i < blocks.size(); i++)
+// {
+// FooterParseResult bpr = (FooterParseResult) blocks.get(i);
+// // logger_.debug("block[" + i + "] from " + bpr.start_index + " to
+// // " + bpr.next_index);
+// }
+
+ unrollLinearization(blocks);
+
+ boolean signature_block_detected = false;
+
+ for (int i = 0; i < blocks.size(); i++)
+ {
+ boolean current_block_contains_signature = false;
+ FooterParseResult bpr = (FooterParseResult) blocks.get(i);
+
+ int prev_end = 0;
+ if (i > 0)
+ {
+ FooterParseResult prev_bpr = (FooterParseResult) blocks.get(i - 1);
+ prev_end = prev_bpr.next_index;
+ }
+
+ // logger_.debug("block from " + prev_end + " to " +
+ // bpr.next_index);
+
+ if (containsEGIZDict(pdf, bpr))
+ {
+ logger_.debug("Parsing Binary Sig:");
+
+ PdfASID kz = extractKZFromEGIZBlock(pdf, bpr);
+
+ if (!kz.toString().equals(BinaryVerificator_1_0_0.MY_ID.toString()))
+ {
+ logger_.debug("Warning: Binary Kennzeichnung not recognized:" + kz.toString());
+ }
+
+ Verificator verificator = new BinaryVerificator_1_0_0();
+ List binary_holders = verificator.parseBlock(pdf, bpr, prev_end);
+
+ holders.addAll(binary_holders);
+
+ // tzefferer: check if signatures have been detected in current block
+ if(binary_holders.size() > 0)
+ {
+ signature_block_detected = true;
+ current_block_contains_signature = true;
+ }
+
+ logger_.debug(":Parsing Binary Sig END - holders.size = " + holders.size());
+ }
+ else
+ {
+ // TODO: make better - already deprecated
+ //amavriqi: skip checking for old sigs becouse of performance issues
+ String old_text_sigs = SettingsReader.getInstance().getSetting("check_old_textual_sigs", "false");
+
+ //amavriqi: if old textual signatures not checked for then
+ // no need to check Incremental Block 0
+ if(old_text_sigs.equalsIgnoreCase("false") && (prev_end == 0))
+ {
+ continue;
+ }
+ logger_.debug("Extracting text for: " + prev_end + " to " + bpr.next_index);
+
+ Verificator verificator = new TextualVerificator_1_0_0();
+ List text_holders = verificator.parseBlock(pdf, bpr, prev_end);
+ logger_.debug("text_holders = " + text_holders.size());
+
+ // tzefferer: check if signatures have been detected in current block
+ if(text_holders.size() > 0)
+ {
+ signature_block_detected = true;
+ current_block_contains_signature = true;
+ }
+
+ // TODO: make better - already deprecated
+ //amavriqi: only if old textual signatures are checked for
+ if(old_text_sigs.equalsIgnoreCase("true")){
+ if (prev_end == 0)
+ {
+ String rest_text = null;
+ if (!text_holders.isEmpty())
+ {
+ TextualSignatureHolder first_holder = (TextualSignatureHolder) text_holders.get(0);
+ rest_text = first_holder.getSignedText();
+ }
+ else
+ {
+ //a.m.
+ logger_.debug("Incemental block" + prev_end + " and there are " + text_holders.size() + " text holders");
+ logger_.debug("Checking for older textual Signatures");
+ logger_.debug("Extracting text to " + bpr.next_index);
+ rest_text = PdfAS.extractNormalizedTextTextual(pdf, bpr.next_index);
+ }
+
+ List old_holders = PdfAS.extractSignatureHoldersTextual(rest_text, true);
+
+ logger_.debug("Found old holders = " + old_holders.size());
+ if (!old_holders.isEmpty())
+ {
+ // there must be only one old holder.
+ holders.add(0, old_holders.get(0));
+ }
+ }
+ }
+ if (!text_holders.isEmpty())
+ {
+ List actual_text_holders = throwOutBinHolders(text_holders);
+ holders.addAll(actual_text_holders);
+ }
+
+ logger_.debug(":Extracting tex END - holders.size = " + holders.size());
+ }
+
+ // tzefferer: check if illegal modifications have been performed on the document after performing a signation
+ if (!("true".equalsIgnoreCase(allow_post_sign_mods)) && !ignorePostSignModificationsRestriction)
+ {
+ if (signature_block_detected && !current_block_contains_signature)
+ {
+ if (!supressException) {
+ throw new PDFDocumentException(ErrorCode.MODIFIED_AFTER_SIGNATION, "Das Dokument wurde nach erfolgter Signierung verändert.");
+ }
+
+ }
+ }
+ }
+
+ for (int i = 0; i < holders.size(); i++)
+ {
+ SignatureHolder holder = (SignatureHolder) holders.get(i);
+
+ PdfASID kz = holder.getSignatureObject().getKZ();
+ if (kz != null)
+ {
+ checkKZ(kz);
+ }
+ }
+
+ return holders;
+ }
+
+ /**
+ * Checks, if the given KZ is recognized by this application or logs a warning if it isn't.
+ * @param kz The Kennzeichnung.
+ */
+ protected void checkKZ (PdfASID kz)
+ {
+ if (!kz.getVendor().equals(SignatorFactory.VENDOR))
+ {
+ logger_.warn("The vendor " + kz.getVendor() + " isn't known by this application.");
+ }
+ if (!kz.getVersion().equals(SignatorFactory.VERSION_1_0_0))
+ {
+ logger_.warn("The version " + kz.getVersion() + " istn't supported by this application. This might cause problems.");
+ }
+ }
+
+ /**
+ * Throws out SignatureHolders with a binary KZ.
+ *
+ * @param text_holders
+ * The List of SignatureHolder objects.
+ * @return Returns the List of SignatureHolder objects, where no object has
+ * binary KZ.
+ */
+ private List throwOutBinHolders(List text_holders)
+ {
+ List actual_text_holders = new ArrayList();
+ for (int i = 0; i < text_holders.size(); i++)
+ {
+ SignatureHolder sh = (SignatureHolder) text_holders.get(i);
+ PdfASID kz = null;
+ try
+ {
+ kz = sh.getSignatureObject().getKZ();
+ }
+ catch (InvalidIDException e)
+ {
+ logger_.error(e.getMessage(), e);
+ }
+ if (kz != null && kz.getType().equals(SignatorFactory.TYPE_BINARY))
+ {
+ logger_.info("Throwing out binary signature: " + kz);
+ continue;
+ }
+ actual_text_holders.add(sh);
+ }
+ return actual_text_holders;
+ }
+
+ /**
+ * 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);
+ }
+ }
+
+ /**
+ * Extracts the List of SignatureHolders from the given plain text document.
+ *
+ * <p>
+ * Note that this can only extract text signatures.
+ * </p>
+ *
+ * @param raw_text
+ * The plain text document.
+ * @return Returns the ordered List of SignatureHolder objects (the first
+ * signature will be at index 0) extracted from the document or an
+ * empty list, if none could be found.
+ * @throws SignatureException
+ * @throws PDFDocumentException
+ * @throws SignatureTypesException
+ * @throws NormalizeException
+ */
+ public List extractSignaturesFromPlainText(final String raw_text) throws PDFDocumentException, SignatureException, SignatureTypesException, NormalizeException
+ {
+ String normalized_text = PdfAS.normalizeText(raw_text);
+
+ //List text_holders = PdfAS.extractSignatureHoldersTextual(normalized_text, false);
+ List text_holders = AbsoluteTextSignature.extractSignatureHoldersFromText(normalized_text);
+
+ String rest_text = normalized_text;
+ if (!text_holders.isEmpty())
+ {
+ TextualSignatureHolder holder = (TextualSignatureHolder) text_holders.get(0);
+ rest_text = holder.getSignedText();
+ }
+
+ List old_holders = PdfAS.extractSignatureHoldersTextual(rest_text, true);
+ if (!old_holders.isEmpty())
+ {
+ text_holders.addAll(0, old_holders);
+ }
+
+ List actual_text_holders = throwOutBinHolders(text_holders);
+
+ return actual_text_holders;
+ }
+
+ /**
+ * Tells, if the given incremental update block contains a binary signature.
+ *
+ * <p>
+ * According to definition, if a block is a binary block, it must/cannot
+ * contain other signatures than this one.
+ * </p>
+ *
+ * @param block
+ * The incremental update block.
+ * @return Returns true, if this block is a binary signature block, false
+ * otherwise.
+ */
+ protected 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.
+ */
+ protected PdfASID extractKZFromEGIZBlock(final byte[] pdf,
+ final FooterParseResult block) throws PDFDocumentException, InvalidIDException
+ {
+ int egiz_index = PDFUtils.indexOfName(pdf, block.tpr.dpr.names, VerificationFilter.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();
+
+ for (int i = 0; i < kz_apr.elements.size() / 2; 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;
+
+ 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);
+ }
+ }
+
+
+ protected static void printFoundHolders (String list_caption, List found_holders, PrintStream writer)
+ {
+ writer.println("------------------------------------");
+ writer.println(list_caption + ": #=" + found_holders.size());
+
+ for (int i = 0; i < found_holders.size(); i++)
+ {
+ SignatureHolder holder = (SignatureHolder) found_holders.get(i);
+ String kz = "invalid";
+ try
+ {
+ PdfASID kz_id = holder.getSignatureObject().getKZ();
+ if (kz_id == null)
+ {
+ kz = "old signature";
+ }
+ else
+ {
+ kz = kz_id.toString();
+ }
+ }
+ catch (InvalidIDException e)
+ {
+ logger_.error(e.getMessage(), e);
+ }
+ writer.println(" holder[" + i + "]: " + holder.getSignatureObject().getSignationType() + ", KZ=" + kz);
+ }
+
+ writer.println(":" + list_caption);
+ writer.println("------------------------------------");
+
+ }
+
+ // TODO old code - remove
+// public static void main(String[] args) throws IOException, PresentableException
+// {
+// SettingsReader.initializeForCommandLine();
+//
+// File in = new File(args[0]);
+// FileInputStream fis = new FileInputStream(in);
+// byte[] pdf = new byte[(int) in.length()];
+// fis.read(pdf);
+// fis.close();
+//
+// String text = PdfAS.extractNormalizedTextTextual(pdf, pdf.length);;
+//
+// VerificationFilter vf = new VerificationFilter();
+// //List found = vf.extractSignaturesFromPdf(pdf);
+//
+// List found = vf.extractSignaturesFromPlainText(text);
+//
+// printFoundHolders("Final Holders", found, System.out);
+// }
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/Verificator.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/Verificator.java
new file mode 100644
index 0000000..5a8228e
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/Verificator.java
@@ -0,0 +1,62 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: Verificator.java,v 1.1 2006/08/25 17:07:21 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.framework;
+
+import java.util.List;
+
+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.
+ *
+ * @deprecated replaced by the one in framework
+ *
+ * @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(final byte[] pdf, final FooterParseResult block,
+ int start_of_whole_block) throws PresentableException;
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/BinarySignator_1_0_0.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/BinarySignator_1_0_0.java
new file mode 100644
index 0000000..46245d2
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/BinarySignator_1_0_0.java
@@ -0,0 +1,285 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: BinarySignator_1_0_0.java,v 1.1 2006/08/25 17:07:35 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.framework.signators;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import at.gv.egiz.pdfas.framework.input.DataSource;
+import at.gv.egiz.pdfas.framework.input.PdfDataSource;
+import at.gv.egiz.pdfas.impl.input.CompoundPdfDataSourceImpl;
+import at.gv.egiz.pdfas.impl.signator.IncrementalUpdateHelper;
+import at.knowcenter.wag.egov.egiz.PdfAS;
+import at.knowcenter.wag.egov.egiz.PdfASID;
+import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException;
+import at.knowcenter.wag.egov.egiz.exceptions.PresentableException;
+import at.knowcenter.wag.egov.egiz.framework.SignResult;
+import at.knowcenter.wag.egov.egiz.framework.Signator;
+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.exactparser.ByteArrayUtils;
+
+import com.lowagie.text.pdf.PdfPTable;
+
+/**
+ * Signs the document binary.
+ *
+ * <p>
+ * In prepareSign, an Incremental Update is created that contains the Signature
+ * block and the egiz dictionary. For formatting the layout, variable values are
+ * filled with placeholders. After the layout has been fixed, all variable
+ * fields (all holes in the byte ranges) are replaced with 0. This document is
+ * then base64 encoded and signed.
+ * </p>
+ * <p>
+ * In finishSign, the variable fields (values, /Cert) are replaced with the
+ * values according to the encoding.
+ * </p>
+ *
+ * @deprecated moved to new-framework
+ *
+ * @author wprinz
+ */
+public class BinarySignator_1_0_0 implements Signator
+{
+ /**
+ * 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);
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.framework.Signator#getMyId()
+ */
+ public PdfASID getMyId()
+ {
+ return MY_ID;
+ }
+
+ /**
+ * Default constructor.
+ */
+ public BinarySignator_1_0_0()
+ {
+ // Default constructor.
+ }
+
+ /**
+ * @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
+ {
+ try
+ {
+ SignatureObject signature_object = PdfAS.createSignatureObjectFromType(signature_type);
+ signature_object.fillValues((char) BinarySignature.LAYOUT_PLACEHOLDER, has_SIG_ID, false);
+
+ signature_object.setKZ(getMyId());
+
+ PdfPTable pdf_table = PdfAS.createPdfPTableFromSignatureObject(signature_object);
+
+ PositioningInstruction pi = PdfAS.determineTablePositioning(pos, signature_type, pdf, 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;
+ }
+ variable_field_definitions.add(sfd);
+ }
+ }
+
+ //check if signature block is invisible, and if so and if also signature block is positioned
+ //on a new page, prevent pdf-as to do that, because why should make a new page just for an invisible block
+ //added by rpiazzi
+ if (signature_object.getSignatureTypeDefinition().getInvisibleFieldDefinitions().size()==SignatureTypes.REQUIRED_SIG_KEYS.length) {
+ if (pi.isMakeNewPage()) {
+ int pageNumber = pi.getPage();
+ pi = new PositioningInstruction(false, pageNumber-1, 0, 0);
+ }
+ }
+ //end added
+
+ IncrementalUpdateInformation iui = IncrementalUpdateHelper.writeIncrementalUpdate(pdf, pdf_table, signature_type, pi, variable_field_definitions, all_field_definitions, null, null, null);
+
+ String temp_string = iui.temp_ir_number + " " + iui.temp_ir_generation + " obj"; //$NON-NLS-1$//$NON-NLS-2$
+ byte[] temp_bytes = temp_string.getBytes("US-ASCII"); //$NON-NLS-1$
+ 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:
+ 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);
+
+ reduceToIUBlock(iui);
+
+ iui.signature_data = formSignatureData(iui);
+
+ return iui;
+
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ e.printStackTrace();
+ throw new PDFDocumentException(201, e);
+ }
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.framework.Signator#finishSign(at.knowcenter.wag.egov.egiz.pdf.IncrementalUpdateInformation)
+ */
+ public SignResult finishSign(IncrementalUpdateInformation iui) throws PresentableException
+ {
+ restoreSignedPdf(iui);
+
+ // PdfAS.prefixID(iui.signed_signature_object, PdfAS.BINARY_ID);
+ fillReplacesWithValues(iui);
+
+ BinarySignature.replaceCertificate(iui);
+ BinarySignature.replacePlaceholders(iui);
+
+ SignResult sign_result = new SignResult(PdfAS.PDF_MIME_TYPE, iui.signed_pdf);
+ return sign_result;
+ }
+
+ /**
+ * 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(IncrementalUpdateInformation iui)
+ {
+ Iterator it = iui.replaces.iterator();
+ while (it.hasNext())
+ {
+ ReplaceInfo ri = (ReplaceInfo) it.next();
+
+ ri.value = iui.signed_signature_object.retrieveStringValue(ri.sfd.field_name);
+ }
+ }
+
+ protected void reduceToIUBlock(IncrementalUpdateInformation iui)
+ {
+ byte[] iu_block = new byte[iui.signed_pdf.length - iui.original_document.getLength()];
+ System.arraycopy(iui.signed_pdf, iui.original_document.getLength(), iu_block, 0, iu_block.length);
+
+ iui.signed_pdf = null;
+ iui.sign_iui_block = iu_block;
+ }
+
+ 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);
+ }
+
+ /**
+ * 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;
+ }
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/BinarySignator_1_1_0.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/BinarySignator_1_1_0.java
new file mode 100644
index 0000000..2cb99c2
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/BinarySignator_1_1_0.java
@@ -0,0 +1,83 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: BinarySignator_1_0_0.java,v 1.1 2006/08/25 17:07:35 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.framework.signators;
+
+import java.io.ByteArrayInputStream;
+
+import at.gv.egiz.pdfas.impl.input.ByteArrayPdfDataSourceImpl;
+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.
+ *
+ * <p>
+ * 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.
+ * </p>
+ *
+ * @see BinarySignator_1_0_0
+ *
+ * @deprecated moved to nc-framework
+ *
+ * @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 at.knowcenter.wag.egov.egiz.framework.signators.BinarySignator_1_0_0#formSignatureData(at.knowcenter.wag.egov.egiz.pdf.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/knowcenter/wag/egov/egiz/framework/signators/DetachedSignator_1_0_0.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/DetachedSignator_1_0_0.java
new file mode 100644
index 0000000..9ffeefe
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/DetachedSignator_1_0_0.java
@@ -0,0 +1,125 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: DetachedSignator_1_0_0.java,v 1.1 2006/08/30 14:02:35 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.framework.signators;
+
+import java.io.UnsupportedEncodingException;
+
+import at.gv.egiz.pdfas.framework.input.DataSource;
+import at.gv.egiz.pdfas.framework.input.PdfDataSource;
+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.exceptions.PDFDocumentException;
+import at.knowcenter.wag.egov.egiz.exceptions.PresentableException;
+import at.knowcenter.wag.egov.egiz.framework.SignResult;
+import at.knowcenter.wag.egov.egiz.framework.Signator;
+import at.knowcenter.wag.egov.egiz.framework.SignatorFactory;
+import at.knowcenter.wag.egov.egiz.pdf.IncrementalUpdateInformation;
+import at.knowcenter.wag.egov.egiz.pdf.TablePos;
+import at.knowcenter.wag.egov.egiz.sig.SignatureDataImpl;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUPostConnection;
+
+/**
+ * This signator is just for testing purposes.
+ *
+ * <p>
+ * It doesn't modify the original document, but simply returns the XML signature
+ * response as the signed document.
+ * </p>
+ *
+ * @author wprinz
+ */
+public class DetachedSignator_1_0_0 implements Signator
+{
+ /**
+ * The Pdf-AS ID of this Signator.
+ */
+ public static final PdfASID MY_ID = new PdfASID(SignatorFactory.VENDOR, SignatorFactory.TYPE_TEST, SignatorFactory.VERSION_1_0_0);
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.framework.Signator#getMyId()
+ */
+ public PdfASID getMyId()
+ {
+ return MY_ID;
+ }
+
+ /**
+ * The Mime Type.
+ */
+ public static final String MIME_TYPE = "text/xml"; //$NON-NLS-1$
+
+ /**
+ * Default constructor.
+ */
+ public DetachedSignator_1_0_0()
+ {
+ // Default constructor.
+ }
+
+ /**
+ * @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);
+ iui.nonTextObjectInfos = PdfAS.extractNonTextualObjects(pdf);
+ // logger_.debug("signed_text = " + document_text);
+
+ DataSource ds = new TextDataSourceImpl(document_text);
+ iui.signature_data = new SignatureDataImpl(ds, MIME_TYPE, "UTF-8"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ 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);
+ }
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/DetachedfTextualSignator_1_0_0.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/DetachedfTextualSignator_1_0_0.java
new file mode 100644
index 0000000..1559246
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/DetachedfTextualSignator_1_0_0.java
@@ -0,0 +1,133 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: TextualSignator_1_0_0.java,v 1.3 2006/10/31 08:07:50 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.framework.signators;
+
+import java.io.UnsupportedEncodingException;
+
+import at.gv.egiz.pdfas.framework.input.DataSource;
+import at.gv.egiz.pdfas.framework.input.PdfDataSource;
+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.exceptions.PDFDocumentException;
+import at.knowcenter.wag.egov.egiz.exceptions.PresentableException;
+import at.knowcenter.wag.egov.egiz.framework.SignResult;
+import at.knowcenter.wag.egov.egiz.framework.Signator;
+import at.knowcenter.wag.egov.egiz.framework.SignatorFactory;
+import at.knowcenter.wag.egov.egiz.pdf.IncrementalUpdateInformation;
+import at.knowcenter.wag.egov.egiz.pdf.TablePos;
+import at.knowcenter.wag.egov.egiz.sig.SignatureDataImpl;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUPostConnection;
+
+/**
+ * Signs a document textually.
+ *
+ * <p>
+ * In prepareSign, the document text is extracted and normalized.
+ * </p>
+ * <p>
+ * In finishSign, the signed SignatureObject is transformed into a Signature
+ * block, which is then written as an Incremental Update.
+ * </p>
+ *
+ * @author wprinz
+ */
+public class DetachedfTextualSignator_1_0_0 implements Signator
+{
+ /**
+ * 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;
+ }
+
+ /**
+ * Default constructor.
+ */
+ public DetachedfTextualSignator_1_0_0()
+ {
+ // Default constructor.
+ }
+
+ /**
+ * <p>
+ * The parameter has_SIG_ID is not used by this Signator because it doesn't
+ * pre-format the signature block.
+ * </p>
+ *
+ * @see at.knowcenter.wag.egov.egiz.framework.Signator#prepareSign(byte[],
+ * String, TablePos, boolean)
+ */
+ 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, "cp1252");
+ iui.nonTextObjectInfos = PdfAS.extractNonTextualObjects(pdf);
+ // logger_.debug("signed_text = " + document_text);
+
+ DataSource ds = new TextDataSourceImpl(document_text);
+ iui.signature_data = new SignatureDataImpl(ds, MIME_TYPE, "UTF-8"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ 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);
+ }
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/TextualSignator_1_0_0.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/TextualSignator_1_0_0.java
new file mode 100644
index 0000000..ff92cd1
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/TextualSignator_1_0_0.java
@@ -0,0 +1,136 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: TextualSignator_1_0_0.java,v 1.3 2006/10/31 08:07:50 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.framework.signators;
+
+import java.util.ArrayList;
+
+import at.gv.egiz.pdfas.framework.input.DataSource;
+import at.gv.egiz.pdfas.framework.input.PdfDataSource;
+import at.gv.egiz.pdfas.impl.input.TextDataSourceImpl;
+import at.gv.egiz.pdfas.impl.signator.IncrementalUpdateHelper;
+import at.knowcenter.wag.egov.egiz.PdfAS;
+import at.knowcenter.wag.egov.egiz.PdfASID;
+import at.knowcenter.wag.egov.egiz.exceptions.PresentableException;
+import at.knowcenter.wag.egov.egiz.framework.SignResult;
+import at.knowcenter.wag.egov.egiz.framework.Signator;
+import at.knowcenter.wag.egov.egiz.framework.SignatorFactory;
+import at.knowcenter.wag.egov.egiz.pdf.IncrementalUpdateInformation;
+import at.knowcenter.wag.egov.egiz.pdf.PositioningInstruction;
+import at.knowcenter.wag.egov.egiz.pdf.TablePos;
+import at.knowcenter.wag.egov.egiz.pdf.TextualSignature;
+import at.knowcenter.wag.egov.egiz.sig.SignatureDataImpl;
+import at.knowcenter.wag.egov.egiz.sig.SignatureObject;
+import at.knowcenter.wag.egov.egiz.sig.signatureobject.SignatureObjectHelper;
+
+import com.lowagie.text.pdf.PdfPTable;
+
+/**
+ * Signs a document textually.
+ *
+ * <p>
+ * In prepareSign, the document text is extracted and normalized.
+ * </p>
+ * <p>
+ * In finishSign, the signed SignatureObject is transformed into a Signature
+ * block, which is then written as an Incremental Update.
+ * </p>
+ *
+ * @deprecated moved to new-framework
+ *
+ * @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.
+ }
+
+ /**
+ * <p>
+ * The parameter has_SIG_ID is not used by this Signator because it doesn't
+ * pre-format the signature block.
+ * </p>
+ *
+ * @see at.knowcenter.wag.egov.egiz.framework.Signator#prepareSign(byte[],
+ * String, TablePos, boolean)
+ */
+ 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);
+ iui.nonTextObjectInfos = PdfAS.extractNonTextualObjects(pdf);
+ // logger_.debug("signed_text = " + document_text);
+
+ DataSource ds = new TextDataSourceImpl(document_text);
+ iui.signature_data = new SignatureDataImpl(ds, "text/plain", "UTF-8");
+
+ 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
+ {
+ // PdfAS.prefixID(iui.signed_signature_object, PdfAS.TEXT_ID);
+
+ iui.signed_signature_object.kz = getMyId().toString();
+
+ SignatureObject so = SignatureObjectHelper.convertSignSignatureObjectToSignatureObject(iui.signed_signature_object, iui.signature_type);
+
+ PdfPTable pdf_table = PdfAS.createPdfPTableFromSignatureObject(so);
+
+ PositioningInstruction pi = PdfAS.determineTablePositioning(iui.pos, iui.signature_type, iui.original_document, pdf_table);
+
+ IncrementalUpdateInformation signed_iui = IncrementalUpdateHelper.writeIncrementalUpdate(iui.original_document, pdf_table, iui.signature_type, pi, null, null, null, null, null);
+
+ SignResult sign_result = new SignResult(PdfAS.PDF_MIME_TYPE, signed_iui.signed_pdf);
+ return sign_result;
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/TextualSignator_1_1_0.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/TextualSignator_1_1_0.java
new file mode 100644
index 0000000..42a5856
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/signators/TextualSignator_1_1_0.java
@@ -0,0 +1,53 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: TextualSignator_1_0_0.java,v 1.3 2006/10/31 08:07:50 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.framework.signators;
+
+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/knowcenter/wag/egov/egiz/framework/verificators/BinaryVerificator_1_0_0.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/verificators/BinaryVerificator_1_0_0.java
new file mode 100644
index 0000000..1ec1568
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/verificators/BinaryVerificator_1_0_0.java
@@ -0,0 +1,396 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: BinaryVerificator_1_0_0.java,v 1.3 2006/10/11 08:03:22 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.framework.verificators;
+
+import java.io.ByteArrayOutputStream;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.gv.egiz.pdfas.framework.input.PdfDataSource;
+import at.gv.egiz.pdfas.impl.input.ByteArrayPdfDataSourceImpl;
+import at.gv.egiz.pdfas.impl.vfilter.helper.VerificationFilterBinaryHelper;
+
+import org.apache.log4j.Logger;
+
+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.framework.Verificator;
+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.
+ *
+ * @deprecated moved to the new framework
+ *
+ * @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 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.knowcenter.wag.egov.egiz.framework.Verificator#parseBlock(byte[],
+ * at.knowcenter.wag.exactparser.parsing.results.FooterParseResult, int)
+ */
+ public List parseBlock(byte[] pdf, FooterParseResult block, int start_of_whole_block) throws PresentableException
+ {
+ 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);
+ 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);
+ }
+
+ 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 (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.
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ for (int i = 0; i < cert.length; i++)
+ {
+ if (cert[i] != 0)
+ {
+ baos.write(cert[i]);
+ }
+ }
+ byte[] b64 = baos.toByteArray();
+
+ 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);
+
+ // 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;
+ }
+ }
+
+ // FIXME This blows up the session !!!!!
+ PdfDataSource ds = 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;
+ }
+
+ /**
+ * 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/knowcenter/wag/egov/egiz/framework/verificators/BinaryVerificator_1_1_0.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/verificators/BinaryVerificator_1_1_0.java
new file mode 100644
index 0000000..c1d94c1
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/verificators/BinaryVerificator_1_1_0.java
@@ -0,0 +1,44 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.framework.verificators;
+
+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/knowcenter/wag/egov/egiz/framework/verificators/TextualVerificator_1_0_0.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/verificators/TextualVerificator_1_0_0.java
new file mode 100644
index 0000000..58302be
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/verificators/TextualVerificator_1_0_0.java
@@ -0,0 +1,147 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: TextualVerificator_1_0_0.java,v 1.5 2006/11/28 07:45:09 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.framework.verificators;
+
+import java.io.ByteArrayInputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import at.knowcenter.wag.egov.egiz.PdfAS;
+import at.knowcenter.wag.egov.egiz.PdfASID;
+import at.knowcenter.wag.egov.egiz.cfg.ConfigLogger;
+import at.knowcenter.wag.egov.egiz.exceptions.PresentableException;
+import at.knowcenter.wag.egov.egiz.framework.SignatorFactory;
+import at.knowcenter.wag.egov.egiz.framework.Verificator;
+import at.knowcenter.wag.egov.egiz.pdf.AbsoluteTextSignature;
+import at.knowcenter.wag.egov.egiz.pdf.SignatureHolder;
+import at.knowcenter.wag.exactparser.parsing.results.FooterParseResult;
+
+
+/**
+ * The textual verificator.
+ *
+ * <p>
+ * All holders of the document so far including the block itself are extracted.
+ * If at least one has been found it is checked that this one doesn't belong to
+ * a previous block.
+ * </p>
+ * <p>
+ * Note that the KZ is not explicitely checked here, so this algorithm will find
+ * all blocks.
+ * </p>
+ * <p>
+ * Note that it will not find old style blocks as they don't have the SIG_KZ.
+ * </p>
+ *
+ * @deprecated moved to the new framework
+ *
+ * @author wprinz
+ */
+public class TextualVerificator_1_0_0 implements Verificator
+{
+ /**
+ * The Pdf-AS ID of this Verificator.
+ */
+ public static final PdfASID MY_ID = new PdfASID(SignatorFactory.VENDOR, SignatorFactory.TYPE_TEXTUAL, SignatorFactory.VERSION_1_0_0);
+
+ /**
+ * The logger definition.
+ */
+ private static final Logger logger_ = ConfigLogger.getLogger(TextualVerificator_1_0_0.class);
+
+ /**
+ * Default constructor.
+ */
+ public TextualVerificator_1_0_0()
+ {
+ // Default constructor.
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.framework.Verificator#parseBlock(byte[],
+ * at.knowcenter.wag.exactparser.parsing.results.FooterParseResult, int)
+ */
+ public List parseBlock(byte[] pdf, FooterParseResult block,
+ int start_of_whole_block) throws PresentableException
+ {
+ String block_text = PdfAS.extractNormalizedTextTextual(pdf, block.next_index);
+
+ logger_.debug("Scanning block:");
+ //List signature_holders = PdfAS.extractSignatureHoldersTextual(block_text, false);
+ List signature_holders = AbsoluteTextSignature.extractSignatureHoldersFromText(block_text);
+ logger_.debug(": end of Scanning block");
+
+ // logger_.debug("signature_holders = " + signature_holders.size());
+
+ if (signature_holders.isEmpty())
+ {
+ return signature_holders;
+ }
+
+ List text_holder_candidates = null;
+ if (start_of_whole_block > 0)
+ {
+ text_holder_candidates = new ArrayList();
+
+ String prev_text = PdfAS.extractNormalizedTextTextual(pdf, start_of_whole_block);
+
+ logger_.debug("Scanning prev block:");
+ //List prev_signature_holders = PdfAS.extractSignatureHoldersTextual(prev_text, false);
+ List prev_signature_holders = AbsoluteTextSignature.extractSignatureHoldersFromText(prev_text);
+ logger_.debug(": end of Scanning prev block");
+
+ // logger_.debug("prev_signature_holders = " +
+ // prev_signature_holders.size());
+
+ for (int i = prev_signature_holders.size(); i < signature_holders.size(); i++)
+ {
+ SignatureHolder holder = (SignatureHolder) signature_holders.get(i);
+ text_holder_candidates.add(holder);
+ }
+ }
+ else
+ {
+ logger_.debug("there is no prev - so all found signatures are possible candidates.");
+ text_holder_candidates = signature_holders;
+ }
+
+ List text_holders = new ArrayList();
+ for (int i = 0; i < text_holder_candidates.size(); i++)
+ {
+ SignatureHolder holder = (SignatureHolder) text_holder_candidates.get(i);
+ if (!holder.getSignatureObject().isTextual())
+ {
+ logger_.debug("Skipping found signature block because it's not textual.");
+ continue;
+ }
+ text_holders.add(holder);
+ }
+
+ return text_holders;
+ }
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/verificators/TextualVerificator_pdfasold.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/verificators/TextualVerificator_pdfasold.java
new file mode 100644
index 0000000..98940d6
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/framework/verificators/TextualVerificator_pdfasold.java
@@ -0,0 +1,106 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: TextualVerificator_pdfasold.java,v 1.3 2006/10/11 08:03:22 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.framework.verificators;
+
+import java.io.ByteArrayInputStream;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import at.knowcenter.wag.egov.egiz.PdfAS;
+import at.knowcenter.wag.egov.egiz.cfg.ConfigLogger;
+import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException;
+import at.knowcenter.wag.egov.egiz.exceptions.PresentableException;
+import at.knowcenter.wag.egov.egiz.framework.Verificator;
+import at.knowcenter.wag.exactparser.parsing.results.FooterParseResult;
+
+
+/**
+ * This Verificator extracts a PDF-AS old signature from the original document.
+ *
+ * @author wprinz
+ */
+public class TextualVerificator_pdfasold implements Verificator
+{
+ /**
+ * The logger definition.
+ */
+ private static final Logger logger_ = ConfigLogger.getLogger(TextualVerificator_1_0_0.class);
+
+ /**
+ * Default Constructor.
+ */
+ public TextualVerificator_pdfasold()
+ {
+ // Default Constructor.
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.framework.Verificator#parseBlock(byte[], at.knowcenter.wag.exactparser.parsing.results.FooterParseResult, int)
+ */
+ public List parseBlock(byte[] pdf, FooterParseResult block,
+ int start_of_whole_block) throws PresentableException
+ {
+ if (start_of_whole_block != 0)
+ {
+ throw new PDFDocumentException(201, "The PDF-AS-old Verificator can only be applied on original documents.");
+ }
+
+ String normalized_text = PdfAS.extractNormalizedTextTextual(pdf, block.next_index);
+
+ logger_.debug("Scanning block:");
+ List signature_holders = PdfAS.extractSignatureHoldersTextual(normalized_text, true);
+ logger_.debug(": end of Scanning block");
+
+
+// List signature_holders = new ArrayList();
+//
+// SignatureTypes sig_types = SignatureTypes.getInstance();
+// List signatureTypes_ = sig_types.getSignatureTypeDefinitions();
+//
+// boolean can_separate = true;
+// int endIndex = normalized_text.length();
+// String signed_text = normalized_text;
+//
+// SignatureBlock sig_block = new SignatureBlock(signatureTypes_);
+// can_separate = sig_block.separateBlockFromRawText(signed_text, true);
+// if (can_separate)
+// {
+// endIndex = sig_block.getStartIndex();
+// signed_text = signed_text.substring(0, endIndex);
+//
+// SignatureObject sig_object = sig_block.getSignatureObject();
+//
+// SignatureHolder holder = new SignatureHolder();
+// holder.signed_text = signed_text;
+// holder.signature_object = sig_object;
+// signature_holders.add(0, holder);
+// }
+
+ return signature_holders;
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/api/LDAPAPIException.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/api/LDAPAPIException.java
new file mode 100644
index 0000000..9074ded
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/api/LDAPAPIException.java
@@ -0,0 +1,77 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.ldap.api;
+
+/**
+ * @author <a href="mailto:thomas.knall@iaik.tugraz.at">Thomas Knall</a>
+ */
+public class LDAPAPIException extends Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ private Exception exception;
+
+ public Exception getException() {
+ return this.exception;
+ }
+
+ public String getMessage() {
+ String message = super.getMessage();
+ if (message == null && exception != null) {
+ return exception.getMessage();
+ } else {
+ return message;
+ }
+ }
+
+ public LDAPAPIException(String message, Exception exception) {
+ super(message);
+ this.exception = exception;
+ }
+
+ public LDAPAPIException(String message) {
+ super(message);
+ this.exception = null;
+ }
+
+ public LDAPAPIException(Exception exception) {
+ super();
+ this.exception = exception;
+ }
+
+ public LDAPAPIException() {
+ super();
+ this.exception = null;
+
+ }
+
+ public String toString() {
+ if (exception != null) {
+ return exception.toString();
+ } else {
+ return super.toString();
+ }
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/api/LDAPAPIFactory.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/api/LDAPAPIFactory.java
new file mode 100644
index 0000000..51ae84f
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/api/LDAPAPIFactory.java
@@ -0,0 +1,55 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.ldap.api;
+
+import org.apache.log4j.Logger;
+
+import at.knowcenter.wag.egov.egiz.ldap.client.LDAPIssuerNameFilter;
+import at.knowcenter.wag.egov.egiz.sig.LDAPAPI;
+
+/**
+ * @author <a href="mailto:thomas.knall@iaik.tugraz.at">Thomas Knall</a>
+ */
+public abstract class LDAPAPIFactory {
+
+ private static LDAPAPIFactory ldapAPIfactoryInstance;
+ private final Logger log = Logger.getLogger(LDAPAPIFactory.class);
+
+ protected LDAPAPIFactory() {
+ }
+
+ public static synchronized LDAPAPIFactory getInstance(LDAPIssuerNameFilter ldapIssuerNameFilter) {
+ if (ldapAPIfactoryInstance == null) {
+ ldapAPIfactoryInstance = new LDAPAPIFactoryImpl(ldapIssuerNameFilter);
+ }
+ return ldapAPIfactoryInstance;
+ }
+
+ public static LDAPAPIFactory getInstance() {
+ return getInstance(null);
+ }
+
+ public abstract LDAPAPI createLDAPAPI(String implClassURI) throws LDAPAPIException;
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/api/LDAPAPIFactoryImpl.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/api/LDAPAPIFactoryImpl.java
new file mode 100644
index 0000000..61fbaed
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/api/LDAPAPIFactoryImpl.java
@@ -0,0 +1,92 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.ldap.api;
+
+import java.util.Hashtable;
+
+import org.apache.log4j.Logger;
+
+import at.knowcenter.wag.egov.egiz.ldap.client.LDAPIssuerNameFilter;
+import at.knowcenter.wag.egov.egiz.sig.LDAPAPI;
+
+/**
+ * @author <a href="mailto:thomas.knall@iaik.tugraz.at">Thomas Knall</a>
+ */
+public class LDAPAPIFactoryImpl extends LDAPAPIFactory {
+
+ private static final Logger log = Logger.getLogger(LDAPAPIFactoryImpl.class);
+
+ // mapping <full qualified class name, LDAPAPI implementation>
+// private Hashtable<String, LDAPAPI> ldapImpls;
+ private Hashtable ldapImpls;
+
+ private LDAPIssuerNameFilter ldapIssuerNameFilter;
+
+ protected LDAPAPIFactoryImpl(LDAPIssuerNameFilter ldapIssuerNameFilter) {
+ this.ldapImpls = new Hashtable();
+ this.ldapIssuerNameFilter = ldapIssuerNameFilter;
+ }
+
+ private LDAPAPI instantiatelAPIImpl(String implClassURI) throws LDAPAPIException {
+ if (implClassURI == null) {
+ throw new NullPointerException("URI of implementing class must not be null.");
+ }
+ if (implClassURI.length() == 0) {
+ throw new IllegalArgumentException("URI of implementing class must not be empty.");
+ }
+ log.info("Trying to instantiate \"" + LDAPAPI.class.getName() + "\" implementation \"" + implClassURI + "\"...");
+ LDAPAPI ldapAPIImpl = null;
+ try {
+ Class clazz = Class.forName(implClassURI);
+ Object ldapAPIImplObj = clazz.newInstance();
+ if (!(ldapAPIImplObj instanceof LDAPAPI)) {
+ throw new LDAPAPIException("Declared class does not implement \"" + LDAPAPI.class.getName() + "\".");
+ }
+ ldapAPIImpl = (LDAPAPI) ldapAPIImplObj;
+ log.info("LDAPAPI implementation successfully instantiated.");
+ ldapAPIImpl.setIssuerNameFilter(this.ldapIssuerNameFilter);
+ } catch (InstantiationException e) {
+ throw new LDAPAPIException("Declared implementation of \"" + LDAPAPI.class.getName() + "\" cannot be instantiated.");
+ } catch (IllegalAccessException e) {
+ throw new LDAPAPIException("Declared implementation of \"" + LDAPAPI.class.getName() + "\" cannot be instantiated (illegal access).");
+ } catch (ClassNotFoundException e) {
+ throw new LDAPAPIException("Unable to find class \"" + implClassURI + "\" as implementation of \"" + LDAPAPI.class.getName() + "\".");
+ }
+ return ldapAPIImpl;
+ }
+
+ public synchronized LDAPAPI createLDAPAPI(String implClassURI) throws LDAPAPIException {
+ if (implClassURI == null || implClassURI.length() == 0) {
+ // use internal implementation
+ implClassURI = LDAPAPIImpl.class.getName();
+ }
+ LDAPAPI impl = (LDAPAPI) this.ldapImpls.get(implClassURI);
+ if (impl == null) {
+ impl = this.instantiatelAPIImpl(implClassURI);
+ this.ldapImpls.put(implClassURI, impl);
+ }
+ return impl;
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/api/LDAPAPIImpl.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/api/LDAPAPIImpl.java
new file mode 100644
index 0000000..57c471f
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/api/LDAPAPIImpl.java
@@ -0,0 +1,148 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.ldap.api;
+
+import iaik.utils.Util;
+import iaik.x509.X509Certificate;
+
+import java.math.BigInteger;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.exceptions.SettingNotFoundException;
+import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
+import at.knowcenter.wag.egov.egiz.ldap.client.LDAPClient;
+import at.knowcenter.wag.egov.egiz.ldap.client.LDAPClientFactory;
+import at.knowcenter.wag.egov.egiz.ldap.client.LDAPException;
+import at.knowcenter.wag.egov.egiz.ldap.client.LDAPIssuerNameFilter;
+import at.knowcenter.wag.egov.egiz.ldap.client.LDAPMapping;
+import at.knowcenter.wag.egov.egiz.sig.LDAPAPI;
+
+/**
+ * @author <a href="mailto:thomas.knall@iaik.tugraz.at">Thomas Knall</a>
+ */
+public class LDAPAPIImpl implements LDAPAPI {
+
+ private final Logger log = Logger.getLogger(this.getClass());
+
+ /**
+ * Prefix for specific entry in config properties file.
+ */
+ private static final String PROP_LDAP_PREFIX = "ldap_mapping";
+
+ private static final String PROP_ISSUER_NAME_POSTFIX = "issuer_name";
+
+ private static final String PROP_LDAP_URL_POSTFIX = "url";
+
+ private static final String PROP_SERIAL_ATTR_POSTFIX = "serial_attr";
+
+ private static final String LDAP_FACTORY_IDENTIFIER = "PDF-AS LDAP Support";
+
+ private LDAPClientFactory ldapClientFactory;
+
+ private LDAPIssuerNameFilter ldapIssuerNameFilter;
+
+ protected LDAPAPIImpl() {
+ this.ldapClientFactory = null;
+ this.ldapIssuerNameFilter = null;
+ }
+
+ private void initializeFactoryImpl() {
+ if (this.ldapClientFactory == null) {
+ try {
+ SettingsReader settings = SettingsReader.getInstance();
+
+ this.ldapClientFactory = LDAPClientFactory.getInstance(LDAP_FACTORY_IDENTIFIER);
+ this.ldapClientFactory.setLDAPIssuerNameFilter(this.ldapIssuerNameFilter);
+
+ List mappingKeys = settings.getKeys(PROP_LDAP_PREFIX);
+ if (mappingKeys != null) {
+ Iterator it = mappingKeys.iterator();
+ while (it.hasNext()) {
+ String keyPrefix = PROP_LDAP_PREFIX + "." + (String) it.next() + ".";
+ String issuerName = settings.getSetting(keyPrefix + PROP_ISSUER_NAME_POSTFIX);
+ String ldapURL = settings.getSetting(keyPrefix + PROP_LDAP_URL_POSTFIX);
+ String serialAttr = settings.getSetting(keyPrefix + PROP_SERIAL_ATTR_POSTFIX,
+ null);
+
+ LDAPMapping ldapMapping = new LDAPMapping(issuerName, ldapURL, serialAttr);
+ this.ldapClientFactory.registerMapping(ldapMapping);
+ }
+ } else {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(PROP_LDAP_PREFIX).append(".foo.").append(PROP_ISSUER_NAME_POSTFIX)
+ .append(", ");
+ buffer.append(PROP_LDAP_PREFIX).append(".foo.").append(PROP_LDAP_URL_POSTFIX)
+ .append(", ");
+ buffer.append(PROP_LDAP_PREFIX).append(".foo.").append(PROP_SERIAL_ATTR_POSTFIX);
+ this.log.warn("There are no LDAP mappings (" + buffer.toString()
+ + ") declared within config file.");
+ }
+
+ } catch (SettingsException e) {
+ this.log.error(e.getMessage(), e);
+ } catch (SettingNotFoundException e) {
+ this.log.error(e.getMessage(), e);
+ } catch (LDAPException e) {
+ this.log.error(e.getMessage(), e);
+ }
+ ;
+ }
+ }
+
+ public byte[] loadBase64CertificateFromLDAP(String serialNumber, String issuer) {
+ this.initializeFactoryImpl();
+ byte[] base64CertData = null;
+ try {
+ List clients = this.ldapClientFactory.createClients(issuer);
+ Iterator clientIt = clients.iterator();
+ X509Certificate x509certificate = null;
+ while (clientIt.hasNext() && x509certificate == null) {
+ LDAPClient client = (LDAPClient) clientIt.next();
+ try {
+ x509certificate = client.retrieveCertificate(new BigInteger(serialNumber));
+ } catch (LDAPException e) {
+ this.log.error(e.getMessage(), e);
+ }
+ }
+ if (x509certificate != null) {
+ base64CertData = Util.Base64Encode(x509certificate.toByteArray());
+ }
+ } catch (LDAPException e) {
+ this.log.error(e.getMessage(), e);
+ }
+ return base64CertData;
+ }
+
+ public void setIssuerNameFilter(LDAPIssuerNameFilter filter) throws LDAPAPIException {
+ if (this.ldapClientFactory != null) {
+ throw new LDAPAPIException("LDAPIssuerNameFilter must be applied before mappings are registered.");
+ }
+ this.ldapIssuerNameFilter = filter;
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/client/LDAPClient.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/client/LDAPClient.java
new file mode 100644
index 0000000..1425856
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/client/LDAPClient.java
@@ -0,0 +1,88 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.ldap.client;
+
+import iaik.x509.X509Certificate;
+
+import java.math.BigInteger;
+import java.net.URL;
+
+/**
+ * @author <a href="mailto:thomas.knall@iaik.tugraz.at">Thomas Knall</a>
+ */
+public interface LDAPClient {
+
+ /**
+ * Returns the ldap url this client was registered for.
+ *
+ * @return The ldap url linked with this client.
+ */
+ URL getUrl();
+
+ /**
+ * Sets the ldap url this client should be registered for.
+ *
+ * @param ldapURL
+ * The ldap url linked with this client.
+ */
+ void setUrl(URL ldapURL);
+
+ /**
+ * Returns the attribute name that represents the serial number.
+ *
+ * @return The attribute name representing the serial number.
+ */
+ String getSerialNumberAttrName();
+
+ /**
+ * Sets the attribute name that represents the serial number.
+ *
+ * @param serialNumberAttrName
+ * The attribute name representing the serial number.
+ */
+ void setSerialNumberAttrName(String serialNumberAttrName);
+
+ /**
+ * Retrieves the certificate(s) matching the filter {@code filter}.
+ *
+ * @param filter
+ * The filter for the ldap request.
+ * @return An array of certificates matching the filter {@code filter}.
+ * @throws LDAPException
+ * Is thrown in case of error.
+ */
+ X509Certificate[] retrieveCertificates(String filter) throws LDAPException;
+
+ /**
+ * Retriebes the certificate with the serial number {@code serialNumber}.
+ *
+ * @param serialNumber
+ * The serial number of the required certificate.
+ * @return The certificate with the serial number {@code serialNumber}.
+ * @throws LDAPException
+ * Is thrown in case of error.
+ */
+ X509Certificate retrieveCertificate(BigInteger serialNumber) throws LDAPException;
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/client/LDAPClientFactory.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/client/LDAPClientFactory.java
new file mode 100644
index 0000000..d88d0b8
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/client/LDAPClientFactory.java
@@ -0,0 +1,102 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.ldap.client;
+
+import iaik.asn1.structures.Name;
+
+import java.util.Hashtable;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+
+/**
+ * @author <a href="mailto:thomas.knall@iaik.tugraz.at">Thomas Knall</a>
+ */
+public abstract class LDAPClientFactory {
+
+ private final Logger log = Logger.getLogger(getClass());
+
+ protected static final String DEFAULT_IDENTIFIER = "default LDAPClientFactory";
+
+ /**
+ * Mapping of category/identifier to LDAPClientFactory.
+ * Allows the usage of multiple independently configured LDAPClientFactoryImpls.
+ */
+// private static Hashtable<String, LDAPClientFactory> ldapClientFactoryInstances = new Hashtable<String, LDAPClientFactory>();
+ private static Hashtable ldapClientFactoryInstances = new Hashtable();
+
+ private LDAPMappingStore ldapMappingStore;
+
+ protected LDAPClientFactory() {
+ this.ldapMappingStore = new LDAPMappingStore();
+ }
+
+ public List getMappings(String issuerName) throws LDAPException {
+ return this.ldapMappingStore.getMappings(issuerName);
+ }
+
+ public List getMapping(Name name) {
+ return this.ldapMappingStore.getMappings(name);
+ }
+
+ public void resetMappings() {
+ this.ldapMappingStore.clearStore();
+ }
+
+ public boolean hasBeenConfigured() {
+ return !this.ldapMappingStore.isEmpty();
+ }
+
+ public synchronized void registerMapping(LDAPMapping ldapMapping) {
+ this.ldapMappingStore.addMapping(ldapMapping);
+ }
+
+ public void setLDAPIssuerNameFilter(LDAPIssuerNameFilter filter) throws LDAPException {
+ if (this.hasBeenConfigured()) {
+ throw new LDAPException("Not allowed to set filter after registration of mappings.");
+ }
+ this.ldapMappingStore = new LDAPMappingStore(filter);
+ }
+
+ public boolean isLDAPIssuerNameFilter() {
+ return this.ldapMappingStore.isLDAPIssuerNameFilter();
+ }
+
+ public static synchronized LDAPClientFactory getInstance(String identifier) {
+ LDAPClientFactory ldapClientFactoryInstance = (LDAPClientFactory) ldapClientFactoryInstances.get(identifier);
+ if (ldapClientFactoryInstance == null) {
+ ldapClientFactoryInstance = new LDAPClientFactoryImpl();
+ ldapClientFactoryInstances.put(identifier, ldapClientFactoryInstance);
+ }
+ return ldapClientFactoryInstance;
+ }
+
+ public static synchronized LDAPClientFactory getInstance() {
+ return getInstance(DEFAULT_IDENTIFIER);
+ }
+
+ public abstract List createClients(String issuerName) throws LDAPException;
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/client/LDAPClientFactoryImpl.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/client/LDAPClientFactoryImpl.java
new file mode 100644
index 0000000..ae3cbc1
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/client/LDAPClientFactoryImpl.java
@@ -0,0 +1,118 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.ldap.client;
+
+import iaik.asn1.ObjectID;
+import iaik.asn1.structures.Name;
+import iaik.utils.RFC2253NameParser;
+import iaik.utils.RFC2253NameParserException;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.log4j.Logger;
+
+/**
+ * @author <a href="mailto:thomas.knall@iaik.tugraz.at">Thomas Knall</a>
+ */
+public final class LDAPClientFactoryImpl extends LDAPClientFactory {
+
+ private final Logger log = Logger.getLogger(getClass());
+
+ private Hashtable ldapClients;
+
+ protected LDAPClientFactoryImpl() {
+ this.ldapClients = new Hashtable();
+ }
+
+ public static String rfc2253Name2Domain(Name name) {
+ Object[] values = name.getRDNValues(ObjectID.domainComponent);
+ if (values == null) {
+ return null;
+ }
+ StringBuffer buffer = new StringBuffer();
+ for (int i = 0; i < values.length; i++) {
+ buffer.append(values[i]);
+ if (i+1 < values.length) {
+ buffer.append(".");
+ }
+ }
+ return buffer.toString();
+ }
+
+ public static String rfc2253Name2Domain(String nameString) throws RFC2253NameParserException {
+ RFC2253NameParser nameParser = new RFC2253NameParser(nameString);
+ return rfc2253Name2Domain(nameParser.parse());
+ }
+
+ private List instantiateLDAPClients(String issuerName) throws LDAPException {
+ if (!super.hasBeenConfigured()) {
+ log.warn(super.getClass().getName() + " has not been configured yet.");
+ }
+ List ldapClients = new ArrayList();
+ List mappings = super.getMappings(issuerName);
+ if (mappings == null || mappings.isEmpty()) {
+ try {
+ String alternativeURLString = rfc2253Name2Domain(issuerName);
+ if (alternativeURLString == null || alternativeURLString.length() == 0) {
+ throw new LDAPException("Neither issuer name \"" + issuerName + "\" has been registered nor domain components were provided.");
+ }
+ alternativeURLString = "ldap://" + alternativeURLString;
+ log.warn("Issuer name \"" + issuerName + "\" has not been registered; trying to instantiate client for url \"" + alternativeURLString + "\"...");
+ LDAPClient client = new LDAPClientImpl(alternativeURLString);
+ ldapClients.add(client);
+ } catch (RFC2253NameParserException e) {
+ throw new LDAPException(e);
+ }
+ } else {
+ log.debug("Instantiating LDAP clients for " + ArrayUtils.toString(mappings.toArray()) + ".");
+ Iterator mappingIt = mappings.iterator();
+ while (mappingIt.hasNext()) {
+ LDAPMapping mapping = (LDAPMapping) mappingIt.next();
+ ldapClients.add(new LDAPClientImpl(mapping));
+ }
+ }
+ return ldapClients;
+ }
+
+ public synchronized List createClients(String issuerName) throws LDAPException {
+ if (issuerName == null) {
+ throw new NullPointerException("Issuer name must not be null.");
+ }
+ if (issuerName.length() == 0) {
+ throw new IllegalArgumentException("Issuer name must not be empty.");
+ }
+ List ldapClientList = (List) ldapClients.get(issuerName);
+ if (ldapClientList == null) {
+ ldapClientList = instantiateLDAPClients(issuerName);
+ ldapClients.put(issuerName, ldapClientList);
+ }
+ return Collections.unmodifiableList(ldapClientList);
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/client/LDAPClientImpl.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/client/LDAPClientImpl.java
new file mode 100644
index 0000000..808a345
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/client/LDAPClientImpl.java
@@ -0,0 +1,214 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.ldap.client;
+
+import iaik.x509.X509Certificate;
+import iaik.x509.net.ldap.LdapURLConnection;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.apache.log4j.Logger;
+
+public final class LDAPClientImpl implements LDAPClient {
+
+ // constants
+ protected static final String DEFAULT_LDAP_ATTR_SERIAL_NUMBER = "eidCertificateSerialNumber";
+ private static final iaik.x509.net.ldap.Handler LDAP_HANDLER = new iaik.x509.net.ldap.Handler();
+
+ private static final long TIME_ON_BLACKLIST_IN_SECONDS = 300; // block failed urls for 5 min
+ private static final int READ_TIMEOUT = 15;
+ private static final int CONNECTION_TIMEOUT = 15;
+
+ private Logger log = Logger.getLogger(getClass());
+
+ // fields
+ private URL url;
+ private String serialNumberAttrName;
+ private long timeStampForBlackList;
+
+ // constructors
+ protected LDAPClientImpl() {
+ this.setSerialNumberAttrName(DEFAULT_LDAP_ATTR_SERIAL_NUMBER);
+ this.timeStampForBlackList = 0;
+ }
+
+ protected LDAPClientImpl(URL url) {
+ this();
+ this.setUrl(url);
+ }
+
+ protected LDAPClientImpl(String urlString) throws LDAPException {
+ this();
+ try {
+ this.setUrl(new URL(null, urlString, LDAP_HANDLER));
+ } catch (MalformedURLException e) {
+ throw new LDAPException(e);
+ }
+ }
+
+ protected LDAPClientImpl(LDAPMapping ldapMapping) {
+ this();
+ this.setUrl(ldapMapping.getLdapURL());
+ this.setSerialNumberAttrName(ldapMapping.getSerialNumberAttrName());
+ }
+
+
+ // getter/setter
+
+ /*
+ * @see at.iaik.commons.ldap.LDAPClient#getUrl()
+ */
+ public URL getUrl() {
+ return this.url;
+ }
+
+ /*
+ * @see at.iaik.commons.ldap.LDAPClient#setUrl(java.net.URL)
+ */
+ public void setUrl(URL ldapURL) {
+ if (ldapURL == null) {
+ throw new NullPointerException("LDAP url must not be null.");
+ }
+ this.url = ldapURL;
+ }
+
+ /*
+ * @see at.iaik.commons.ldap.LDAPClient#getSerialNumberAttrName()
+ */
+ public String getSerialNumberAttrName() {
+ return this.serialNumberAttrName;
+ }
+
+ /*
+ * @see at.iaik.commons.ldap.LDAPClient#setSerialNumberAttrName(java.lang.String)
+ */
+ public void setSerialNumberAttrName(String serialNumberAttrName) {
+ if (serialNumberAttrName != null && serialNumberAttrName.length() == 0) {
+ throw new IllegalArgumentException("Serial number attribute name must not be empty");
+ }
+ this.serialNumberAttrName = serialNumberAttrName != null ? serialNumberAttrName : DEFAULT_LDAP_ATTR_SERIAL_NUMBER;
+ }
+
+ // service methods
+
+ /*
+ * @see at.iaik.commons.ldap.LDAPClient#retrieveCertificates(java.lang.String)
+ */
+ public X509Certificate[] retrieveCertificates(String filter) throws LDAPException {
+ if (filter == null) {
+ throw new NullPointerException("Filter string must not be null.");
+ }
+ if (filter.length() == 0) {
+ throw new IllegalArgumentException("Filter string must not be empty.");
+ }
+
+ X509Certificate[] certs = new X509Certificate[] { };
+
+ long now = System.currentTimeMillis();
+ if (this.timeStampForBlackList + TIME_ON_BLACKLIST_IN_SECONDS * 1000 >= now) {
+ long remaining = TIME_ON_BLACKLIST_IN_SECONDS - ((now - this.timeStampForBlackList) / 1000);
+ log.warn("LDAP connections to URL \"" + this.getUrl().toString() + "\" are blocked for " + remaining + " (" + TIME_ON_BLACKLIST_IN_SECONDS + ") seconds due to previous errors.");
+ return certs;
+ }
+
+ LdapURLConnection ldapURLConnection = null;
+ try {
+ this.validateData();
+ ldapURLConnection = (LdapURLConnection) this.url.openConnection();
+ log.debug("Setting timeout for LDAPClient: connection timeout = " + CONNECTION_TIMEOUT + " seconds, read timeout = " + READ_TIMEOUT + " seconds.");
+ ldapURLConnection.setReadTimeout(READ_TIMEOUT * 1000);
+ ldapURLConnection.setConnectTimeout(CONNECTION_TIMEOUT * 1000);
+
+ // search for end enity certificates
+ ldapURLConnection.setRequestProperty(
+ LdapURLConnection.RP_ATTRIBUTE_DESCRIPTION,
+ LdapURLConnection.AD_USER_CERTIFICATE
+ );
+
+ // search subtree
+ ldapURLConnection.setRequestProperty(
+ LdapURLConnection.RP_SEARCH_SCOPE,
+ LdapURLConnection.SEARCH_SCOPE_SUBTREE
+ );
+
+ //set filter
+ ldapURLConnection.setRequestProperty(
+ LdapURLConnection.RP_FILTER,
+ filter
+ );
+
+ // connect to the ldap server an read results
+ log.debug("Connecting to \"" + this.url.toString() + "\".");
+ certs = (X509Certificate[]) ldapURLConnection.getContent();
+ log.debug("Result of LDAP query received (" + (certs != null ? certs.length : 0) + " result(s)).");
+ } catch (IOException e) {
+ this.timeStampForBlackList = System.currentTimeMillis();
+ log.warn("Unable to get certificate from \"" + this.getUrl().toString() + "\". LDAPClient is now blocking that URL for " + TIME_ON_BLACKLIST_IN_SECONDS + " seconds.");
+ throw new LDAPException(e);
+ } finally {
+ if (ldapURLConnection != null) {
+ ldapURLConnection.disconnect();
+ }
+ }
+ return certs;
+ }
+
+ /*
+ * @see at.iaik.commons.ldap.LDAPClient#retrieveCertificate(java.math.BigInteger)
+ */
+ public X509Certificate retrieveCertificate(BigInteger serialNumber) throws LDAPException {
+ if (serialNumber == null) {
+ throw new NullPointerException("Serial number must not be null");
+ }
+ this.validateData();
+ X509Certificate[] certs = retrieveCertificates("(" + this.serialNumberAttrName + "=" + serialNumber + ")");
+ if (certs.length > 1) {
+ throw new LDAPException("There was more than one certificate with serial number " + serialNumber + ".");
+ } else if (certs.length == 0) {
+ return null;
+ }
+ return certs[0];
+ }
+
+ // misc
+ public void validateData() throws LDAPException {
+ if (this.url == null) {
+ throw new LDAPException("LDAP URL must not be null.");
+ }
+ if (this.serialNumberAttrName == null || this.serialNumberAttrName.length() == 0) {
+ throw new LDAPException("LDAP key for serial number is null or empty.");
+ }
+ }
+
+ public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("ldapURL = ").append(this.url);
+ buffer.append(", serialNumberAttrName = ").append(this.serialNumberAttrName);
+ return buffer.toString();
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/client/LDAPException.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/client/LDAPException.java
new file mode 100644
index 0000000..3b36e6d
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/client/LDAPException.java
@@ -0,0 +1,50 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.ldap.client;
+
+
+/**
+ * @author <a href="mailto:thomas.knall@iaik.tugraz.at">Thomas Knall</a>
+ */
+public class LDAPException extends Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ public LDAPException() {
+ super();
+ }
+
+ public LDAPException(Exception exception) {
+ super(exception);
+ }
+
+ public LDAPException(String message, Exception exception) {
+ super(message, exception);
+ }
+
+ public LDAPException(String message) {
+ super(message);
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/client/LDAPIssuerNameFilter.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/client/LDAPIssuerNameFilter.java
new file mode 100644
index 0000000..e483d2c
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/client/LDAPIssuerNameFilter.java
@@ -0,0 +1,43 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.ldap.client;
+
+import iaik.asn1.structures.Name;
+
+/**
+ * @author <a href="mailto:thomas.knall@iaik.tugraz.at">Thomas Knall</a>
+ */
+public interface LDAPIssuerNameFilter {
+
+ /**
+ * Applies some kind of filtering on the distinguished name. This can be used
+ * for normalization.
+ *
+ * @param name
+ * The original distinguished name.
+ * @return The new filtered distinguished name.
+ */
+ Name applyFilter(Name name);
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/client/LDAPMapping.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/client/LDAPMapping.java
new file mode 100644
index 0000000..502d88b
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/client/LDAPMapping.java
@@ -0,0 +1,181 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.ldap.client;
+
+import iaik.asn1.structures.Name;
+import iaik.utils.RFC2253NameParser;
+import iaik.utils.RFC2253NameParserException;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Properties;
+
+import org.apache.log4j.Logger;
+
+/**
+ * @author <a href="mailto:thomas.knall@iaik.tugraz.at">Thomas Knall</a>
+ */
+public class LDAPMapping {
+
+ // constants
+ public static final String PROPERTIES_KEY_ISSUER_NAME = "issuer.name";
+ public static final String PROPERTIES_KEY_LDAP_URL = "ldap.url";
+ public static final String PROPERTIES_KEY_SERIAL_ATTR_NAME = "serialnumber.attrname";
+
+ private final Logger log = Logger.getLogger(getClass());
+ private static final iaik.x509.net.ldap.Handler LDAP_HANDLER;
+
+ // fields
+ private Name issuerName;
+ private URL ldapURL;
+ private String serialNumberAttrName;
+
+ // static initialization
+ static {
+ LDAP_HANDLER = new iaik.x509.net.ldap.Handler();
+ }
+
+ // constructors
+ protected LDAPMapping() {
+ this.setSerialNumberAttrName(LDAPClientImpl.DEFAULT_LDAP_ATTR_SERIAL_NUMBER);
+ }
+
+ public LDAPMapping(Name issuerName, URL ldapURL) {
+ this(issuerName, ldapURL, null);
+ }
+
+ public LDAPMapping(Name issuerName, URL ldapURL, String serialNumberAttrName) {
+ this();
+ this.setIssuerName(issuerName);
+ this.setLdapURL(ldapURL);
+ this.setSerialNumberAttrName(serialNumberAttrName);
+ }
+
+ public LDAPMapping(String issuerNameString, String ldapURLString) throws LDAPException {
+ this(issuerNameString, ldapURLString, null);
+ }
+
+ public LDAPMapping(String issuerNameString, String ldapURLString, String serialNumberAttrName) throws LDAPException {
+ this();
+ this.setIssuerName(issuerNameString);
+ this.setLdapURL(ldapURLString);
+ this.setSerialNumberAttrName(serialNumberAttrName);
+ }
+
+ public LDAPMapping(Properties properties) throws LDAPException {
+ this();
+ if (properties == null) {
+ throw new NullPointerException("Properties must not be null.");
+ }
+ String in = properties.getProperty(PROPERTIES_KEY_ISSUER_NAME);
+ String sn = properties.getProperty(PROPERTIES_KEY_LDAP_URL);
+ String snan = properties.getProperty(PROPERTIES_KEY_SERIAL_ATTR_NAME);
+ if (in == null || in.length() == 0) {
+ throw new LDAPException("Property \"" + PROPERTIES_KEY_ISSUER_NAME + "\" must not be null or empty.");
+ }
+ if (sn == null || sn.length() == 0) {
+ throw new LDAPException("Property \"" + PROPERTIES_KEY_LDAP_URL + "\" must not be null or empty.");
+ }
+ this.setIssuerName(in);
+ this.setLdapURL(sn);
+ this.setSerialNumberAttrName(snan);
+ }
+
+ // getter/setter
+ public Name getIssuerName() {
+ return this.issuerName;
+ }
+
+ public String getIssuerNameAsString() {
+ return this.issuerName.getName();
+ }
+
+ public void setIssuerName(Name issuerName) {
+ if (issuerName == null) {
+ throw new NullPointerException("Issuer name must not be null.");
+ }
+ this.issuerName = issuerName;
+ }
+
+ public void setIssuerName(String issuerNameString) throws LDAPException {
+ RFC2253NameParser parser = new RFC2253NameParser(issuerNameString.trim());
+ try {
+ this.setIssuerName(parser.parse());
+ } catch (RFC2253NameParserException e) {
+ throw new LDAPException(e);
+ }
+ }
+
+ public URL getLdapURL() {
+ return this.ldapURL;
+ }
+
+ public void setLdapURL(URL ldapURL) {
+ if (ldapURL == null) {
+ throw new NullPointerException("LDAP url must not be null.");
+ }
+ this.ldapURL = ldapURL;
+ }
+
+ public void setLdapURL(String ldapURLString) throws LDAPException {
+ try {
+ this.setLdapURL(new URL(null, ldapURLString.trim(), LDAP_HANDLER));
+ } catch (MalformedURLException e) {
+ throw new LDAPException(e);
+ }
+ }
+
+ public String getSerialNumberAttrName() {
+ return this.serialNumberAttrName;
+ }
+
+ public void setSerialNumberAttrName(String serialNumberAttrName) {
+ if (serialNumberAttrName != null && serialNumberAttrName.length() == 0) {
+ throw new IllegalArgumentException("Serial number attribute name must not be empty");
+ }
+ this.serialNumberAttrName = serialNumberAttrName != null ? serialNumberAttrName.trim() : LDAPClientImpl.DEFAULT_LDAP_ATTR_SERIAL_NUMBER;
+ }
+
+ // misc
+ public void validateData() throws LDAPException {
+ if (this.issuerName == null) {
+ throw new LDAPException("Issuer name must not be null.");
+ }
+ if (this.ldapURL == null) {
+ throw new LDAPException("LDAP url must not be null.");
+ }
+ if (serialNumberAttrName == null || serialNumberAttrName.length() == 0) {
+ throw new LDAPException("Serial number attribute name must not be null or empty");
+ }
+ }
+
+ public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("issuerName = ").append(this.issuerName != null ? this.issuerName.getName() : null);
+ buffer.append(", ldapURL = ").append(this.ldapURL);
+ buffer.append(", serialNumberAttrName = ").append(this.serialNumberAttrName);
+ return buffer.toString();
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/client/LDAPMappingStore.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/client/LDAPMappingStore.java
new file mode 100644
index 0000000..f36dc8c
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/ldap/client/LDAPMappingStore.java
@@ -0,0 +1,102 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.ldap.client;
+
+import iaik.asn1.structures.Name;
+import iaik.utils.RFC2253NameParser;
+import iaik.utils.RFC2253NameParserException;
+
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+/**
+ * @author <a href="mailto:thomas.knall@iaik.tugraz.at">Thomas Knall</a>
+ */
+public class LDAPMappingStore {
+
+// private Hashtable<Name, LDAPMapping> storedMappings;
+ private Hashtable storedMappings;
+ private LDAPIssuerNameFilter issuerNameFilter;
+ private Logger log = Logger.getLogger(getClass());
+
+ public LDAPMappingStore(LDAPIssuerNameFilter issuerNameFilter) {
+ this.storedMappings = new Hashtable();
+ this.issuerNameFilter = issuerNameFilter;
+ }
+
+ public LDAPMappingStore() {
+ this(null);
+ }
+
+ public void clearStore() {
+ this.storedMappings = new Hashtable();
+ }
+
+ public boolean isEmpty() {
+ return this.storedMappings.isEmpty();
+ }
+
+ public boolean isLDAPIssuerNameFilter() {
+ return this.issuerNameFilter != null;
+ }
+
+ public void addMapping(LDAPMapping mapping) {
+ Name name = mapping.getIssuerName();
+ if (issuerNameFilter != null) {
+ name = this.issuerNameFilter.applyFilter(name);
+ }
+ List mappingList = (List) this.storedMappings.get(name);
+ if (mappingList == null) {
+ mappingList = new ArrayList();
+ this.storedMappings.put(name, mappingList);
+ }
+ log.debug("Adding mapping \"" + mapping + "\" for \"" + name.getName() + "\".");
+ mappingList.add(mapping);
+ }
+
+ public List getMappings(Name name) {
+ if (issuerNameFilter != null) {
+ name = this.issuerNameFilter.applyFilter(name);
+ }
+ return (List) this.storedMappings.get(name);
+ }
+
+ public List getMappings(String nameString) throws LDAPException {
+ RFC2253NameParser parser = new RFC2253NameParser(nameString);
+ Name name;
+ try {
+ name = parser.parse();
+ } catch (RFC2253NameParserException e) {
+ throw new LDAPException(e);
+ }
+ if (issuerNameFilter != null) {
+ name = this.issuerNameFilter.applyFilter(name);
+ }
+ return this.getMappings(name);
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/AbsoluteTextSignature.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/AbsoluteTextSignature.java
new file mode 100644
index 0000000..fd59d34
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/AbsoluteTextSignature.java
@@ -0,0 +1,956 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: AbsoluteTextSignature.java,v 1.1 2006/10/31 08:08:33 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.pdf;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+import org.apache.log4j.Logger;
+
+import at.knowcenter.wag.egov.egiz.PdfAS;
+import at.knowcenter.wag.egov.egiz.cfg.ConfigLogger;
+import at.knowcenter.wag.egov.egiz.exceptions.SignatureException;
+import at.knowcenter.wag.egov.egiz.exceptions.SignatureTypesException;
+import at.knowcenter.wag.egov.egiz.framework.FoundBlock;
+import at.knowcenter.wag.egov.egiz.framework.FoundKey;
+import at.knowcenter.wag.egov.egiz.sig.SignatureObject;
+import at.knowcenter.wag.egov.egiz.sig.SignatureTypeDefinition;
+import at.knowcenter.wag.egov.egiz.sig.SignatureTypes;
+
+/**
+ * Contains methods and helpers that implement the absolute text signature.
+ *
+ * @author wprinz
+ */
+public class AbsoluteTextSignature
+{
+
+ /**
+ * The logger definition.
+ */
+ private static final Logger logger = ConfigLogger.getLogger(AbsoluteTextSignature.class);
+
+ /**
+ * Returns a List of SignatureTypeDefinitions that can be extracted from text.
+ *
+ * <p>
+ * These SignatureTypeDefinitions are all text extractable, which means that they define all required fields as visible.
+ * </p>
+ * <p>
+ * This method filters out all SignatureTypeDefinitions that are not text extractable.
+ * </p>
+ *
+ * @return Returns a List of SignatureTypeDefinitions that can be extracted from text.
+ * @throws SignatureTypesException F.e.
+ */
+ public static List getSignatureTypesForTextAnalysis() throws SignatureTypesException
+ {
+ SignatureTypes sig_types = SignatureTypes.getInstance();
+ List allSignatureTypes = sig_types.getSignatureTypeDefinitions();
+
+ List textSignatureTypes = new ArrayList(allSignatureTypes.size());
+ Iterator it = allSignatureTypes.iterator();
+ while (it.hasNext())
+ {
+ SignatureTypeDefinition std = (SignatureTypeDefinition) it.next();
+ if (!std.isTextExtractable())
+ {
+ logger.debug("The profile " + std.getType() + " is not text extractable and is thereby not used for text analysis.");
+ continue;
+ }
+ textSignatureTypes.add(std);
+ }
+
+ return textSignatureTypes;
+ }
+
+ /**
+ * Extracts all signature holders from a given text.
+ *
+ * <p>
+ * First the latest signature holder is extracted. Then the latest signature
+ * holder in the rest text, which is the second latest one, is extracted. Then
+ * the third latest signature holder is extracted and so forth until no more
+ * signature holders are found.
+ * </p>
+ *
+ * @param text
+ * The text.
+ * @return Returns the List of extracted signature holders ordered by their
+ * date ascendingly (the lowest, earliest date first, the latest,
+ * newest date last). An empty list is returned if no signature
+ * holders were found.
+ * @throws SignatureException
+ * F.e.
+ * @throws SignatureTypesException
+ * F.e.
+ */
+ public static List extractSignatureHoldersFromText(String text) throws SignatureException, SignatureTypesException
+ {
+ List holders = new ArrayList();
+ String current_text = text;
+ for (;;)
+ {
+ TextualSignatureHolder signature_holder = extractLatestBlock(current_text);
+ if (signature_holder == null)
+ {
+ break;
+ }
+ holders.add(0, signature_holder);
+ current_text = signature_holder.getSignedText();
+ }
+ return holders;
+ }
+
+ /**
+ * Extracts the latest signature block from the given text and creates a
+ * SignatureHolder object that can be verified.
+ *
+ * @param text
+ * The text.
+ * @return Returns the SignatureObject extracted from the text, or null, if no
+ * latest block was found.
+ * @throws SignatureException
+ * F.e.
+ * @throws SignatureTypesException
+ * F.e.
+ */
+ public static TextualSignatureHolder extractLatestBlock(String text) throws SignatureException, SignatureTypesException
+ {
+ FoundBlock latest_block = findLatestBlock(text);
+ if (latest_block == null)
+ {
+ return null;
+ }
+ String reconstructed_text = cutOutBlock(text, latest_block);
+ SignatureObject so = createSignatureObjectFromFoundBlock(text, latest_block);
+ TextualSignatureHolder tsh = new TextualSignatureHolder(reconstructed_text, so);
+ return tsh;
+ }
+
+ /**
+ * Finds the latest signature block for a given text.
+ *
+ * <p>
+ * The latest block is the one with the highest, most recent date. Usually
+ * this block will be extracted (cut out) of the text which will result in the
+ * originally signed text of this signature to be verified using the cut out
+ * data.
+ * </p>
+ *
+ * @param text
+ * The text to be analyzed.
+ * @return Returns the latest found block or null, if there was none.
+ * @throws SignatureException
+ * F.e.
+ * @throws SignatureTypesException
+ * F.e.
+ */
+ public static FoundBlock findLatestBlock(String text) throws SignatureException, SignatureTypesException
+ {
+ List signatureTypes_ = getSignatureTypesForTextAnalysis();
+
+ List found_potential_candidates = new ArrayList();
+
+ for (int i = 0; i < signatureTypes_.size(); i++)
+ {
+ SignatureTypeDefinition block_type = (SignatureTypeDefinition) signatureTypes_.get(i);
+ List found_candidates_for_type = findPotentialSignaturesForProfile(text, block_type);
+
+ found_potential_candidates.addAll(found_candidates_for_type);
+ }
+
+ if (found_potential_candidates.isEmpty())
+ {
+ logger.debug("no candidates found at all");
+ return null;
+ }
+
+ List found_candidates = new ArrayList();
+ logger.debug("checking block integrity");
+ for (int i = 0; i < found_potential_candidates.size(); i++)
+ {
+ FoundBlock found_block = (FoundBlock) found_potential_candidates.get(i);
+ String date_value = getDateValue(text, found_block);
+ try
+ {
+ EGIZDate date = EGIZDate.parseFromString(date_value);
+
+ logger.debug("found_block = " + date + " - " + found_block);
+
+ checkBlockIntegrity(text, found_block);
+ found_candidates.add(found_block);
+ }
+ catch (Exception e)
+ {
+ logger.debug("Exception while checking the integrity of the found block " + found_block + ". Ignoring this block.", e);
+ }
+ }
+
+ sortFoundBlocksByDate(text, found_candidates);
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("sorted blocks:");
+ for (int i = 0; i < found_candidates.size(); i++)
+ {
+ FoundBlock found_block = (FoundBlock) found_candidates.get(i);
+
+ String date_value = getDateValue(text, found_block);
+ EGIZDate date = EGIZDate.parseFromString(date_value);
+
+ logger.debug(" #" + i + ": " + date + " - " + found_block);
+ }
+ }
+
+ List latest_blocks = filterLastDateEqualBlocks(text, found_candidates);
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("latest blocks:");
+ for (int i = 0; i < latest_blocks.size(); i++)
+ {
+ FoundBlock found_block = (FoundBlock) latest_blocks.get(i);
+
+ String date_value = getDateValue(text, found_block);
+ EGIZDate date = EGIZDate.parseFromString(date_value);
+
+ logger.debug(" #" + i + ": " + date + " - " + found_block);
+ }
+ }
+
+ // The semantic equality check has been outdated by the
+ // advanced choosing algorithm.
+ // boolean semantic_equality =
+ // PdfAS.checkForSemanticEquality(latest_blocks);
+ // logger.debug("semantic_equality = " + semantic_equality);
+ // if (!semantic_equality)
+ // {
+ // throw new SignatureException(314, "The latest blocks weren't semantically
+ // equal.");
+ // }
+
+ FoundBlock latest_block = chooseMostPossibleBlock(latest_blocks);
+
+ logger.debug("latest block = " + latest_block);
+ return latest_block;
+ }
+
+ /**
+ * Finds the List of potential blocks within the given text for the given
+ * profile.
+ *
+ * @param text
+ * The text, in which potential block are to be sought.
+ * @param block_type
+ * The profile for which the text is to be sought.
+ * @return Returns the List of potential FoundBlocks or an empty List if none
+ * could be found.
+ */
+ public static List findPotentialSignaturesForProfile(String text,
+ SignatureTypeDefinition block_type)
+ {
+ logger.debug("find potential signatures for " + block_type.getType());
+ List found_blocks = new ArrayList();
+
+ final boolean old_style = false;
+
+ Vector keys = block_type.getRevertSortedKeys();
+ Vector captions = block_type.getRevertSortedCaptions();
+
+ String last_key = (String) keys.get(0);
+ logger.debug("last_key = " + last_key);
+ String last_caption = (String) captions.get(0);
+ logger.debug("last_caption = " + last_caption);
+ String current_last_caption= last_caption;
+ List found_last_captions = findIndicesWithStartingNL(text, last_caption);
+ if (last_key.equals(SignatureTypes.SIG_ID))
+ {
+ logger.debug("Last key is SIG_ID, so it may not be present. Searching for the previous to last key.");
+ String prevlast_key = (String) keys.get(1);
+ String prevlast_caption = (String) captions.get(1);
+ current_last_caption = prevlast_caption;
+ List found_prevlast_captions = findIndicesWithStartingNL(text, prevlast_caption);
+ if (!found_prevlast_captions.isEmpty())
+ {
+ found_last_captions.addAll(found_prevlast_captions);
+ }
+ }
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("found " + found_last_captions.size() + " last captions.");
+ for (int i = 0; i < found_last_captions.size(); i++)
+ {
+ logger.debug(" found last caption at index " + found_last_captions.get(i));
+ }
+ }
+
+ for (int lci = 0; lci < found_last_captions.size(); lci++)
+ {
+ int last_caption_index = ((Integer) found_last_captions.get(lci)).intValue();
+ logger.debug("resolving signature block from last caption index " + last_caption_index);
+ int potential_block_end = findEndOfValue(text, last_caption_index);
+ if (potential_block_end == (last_caption_index + current_last_caption.length()+1))
+ {
+ potential_block_end = findEndOfValue(text, potential_block_end);
+ }
+
+ // FIXME: complete HOTFIX
+ /*
+ int extendedValueEnd = potential_block_end;
+ String cv;
+ do {
+ extendedValueEnd = findEndOfValue(text, extendedValueEnd);
+ cv = text.substring(last_caption_index + current_last_caption.length()+1, extendedValueEnd);
+ } while (extendedValueEnd < text.length());
+ */
+
+ logger.debug("potential_block_end = " + potential_block_end);
+ List found_keys = PdfAS.findBlockInText(text.substring(0, potential_block_end), block_type, old_style); // findRestKeys(text,
+ // keys,
+ // captions,
+ // last_caption_index);
+
+ if (found_keys == null)
+ {
+ logger.debug("Not all other captions could be found for the last_caption_index " + last_caption_index + " ==> discarding this index.");
+
+ continue;
+ }
+
+ // sort found keys ascendingly
+ PdfAS.sortFoundKeysAscendingly(found_keys);
+
+ boolean reverse_check_ok = reverseCheckFoundKeys(text, found_keys);
+ if (!reverse_check_ok)
+ {
+ logger.debug("The reverse check ruled this list of found keys out ==> they are discarded.");
+
+ continue;
+ }
+
+ logger.debug("The reverse check proved this list of found keys out ==> adding them as potential candidates.");
+
+ FoundBlock found_block = new FoundBlock();
+ found_block.std = block_type;
+ found_block.found_keys = found_keys;
+ found_block.end_index = potential_block_end;//findEndOfValue(text, last_caption_index);
+ found_blocks.add(found_block);
+ }
+
+ logger.debug("found " + found_blocks.size() + " potential signatures for " + block_type.getType());
+ return found_blocks;
+ }
+
+ /**
+ * Finds all indices of the given subtext (starting at a new line) within a
+ * given text.
+ *
+ * <p>
+ * This is usually used to find the indices of the last captions.
+ * </p>
+ *
+ * @param text
+ * The text to be searched.
+ * @param subtext
+ * The subtext to be sought.
+ * @return Returns the List of found indices.
+ */
+ public static List findIndicesWithStartingNL(String text, String subtext)
+ {
+ List found_indices = new ArrayList();
+
+ // // for some reason "^" + subtext doesn't work as a pattern
+ // String pattern = "\n" + subtext;
+ // Pattern p = Pattern.compile(pattern);
+ // Matcher m = p.matcher(text);
+ //
+ // while (m.find())
+ // {
+ // int found_index = m.start() + 1; // +1 removes the newline
+ // found_indices.add(new Integer(found_index));
+ // }
+
+ int search_from_index = 0;
+ for (;;)
+ {
+ int found_index = text.indexOf("\n" + subtext, search_from_index);
+ if (found_index < 0)
+ {
+ break;
+ }
+ found_index += 1; // The +1 compensates the "\n"
+ found_indices.add(new Integer(found_index));
+ search_from_index = found_index + subtext.length();
+ }
+ return found_indices;
+ }
+
+ /**
+ * Finds the other keys/captions according to their order starting from the
+ * last_caption index upwards.
+ *
+ * @param text
+ * The text.
+ * @param keys
+ * The list of keys.
+ * @param captions
+ * The list of captions.
+ * @param last_caption_index
+ * The index of the last caption.
+ * @return Returns the List of found keys, if all keys could be found, or null
+ * if not all keys could be found.
+ */
+ public static List findRestKeys(String text, List keys, List captions,
+ int last_caption_index)
+ {
+ List found_keys = new ArrayList();
+
+ FoundKey last_caption_found_key = new FoundKey((String) keys.get(0), (String) captions.get(0), last_caption_index);
+ found_keys.add(last_caption_found_key);
+
+ String rest_text = text.substring(0, last_caption_index);
+
+ for (int i = 1; i < captions.size(); i++)
+ {
+ String sought_caption = (String) captions.get(i);
+ int index = rest_text.lastIndexOf(sought_caption);
+
+ if (index < 0)
+ {
+ return null;
+ }
+ FoundKey found_key = new FoundKey((String) keys.get(i), (String) captions.get(i), index);
+ found_keys.add(0, found_key);
+
+ rest_text = rest_text.substring(0, index);
+ }
+
+ return found_keys;
+ }
+
+ /**
+ * Performs a reverse (top to bottom) search for the found keys and checks
+ * that these indices are the same as those that were found during the regular
+ * (bottom up) search.
+ * <p>
+ * If a reverse check proves that the found keys are not at the same positions
+ * as during regular search, this list of found keys should be discarded.
+ * </p>
+ *
+ * @param text
+ * The text.
+ * @param found_keys
+ * The found keys to be reversely checked.
+ * @return Returns true, if all (also the non required) captions could be
+ * found at the same indices as during regular search, false
+ * otherwise.
+ */
+ public static boolean reverseCheckFoundKeys(String text, List found_keys)
+ {
+ int search_from_index = ((FoundKey) found_keys.get(0)).start_index;
+ for (int i = 0; i < found_keys.size(); i++)
+ {
+ FoundKey found_key = (FoundKey) found_keys.get(i);
+
+ int reverse_found_index = text.indexOf(found_key.caption, search_from_index);
+
+ // dferbas fix #331 ??
+
+ if (reverse_found_index < 0)
+ {
+ throw new RuntimeException("The caption " + found_key.caption + " wasn't found in the text during reverse checking - there is something wrong.");
+ }
+
+ if (reverse_found_index != found_key.start_index)
+ {
+ logger.debug("The index for caption " + found_key.caption + " wasn't proved during reverse checking.");
+ return false;
+ }
+ search_from_index = found_key.start_index + found_key.caption.length();
+ }
+ return true;
+ }
+
+ /**
+ * Finds the end of the value in the text.
+ *
+ * <p>
+ * This simply scans for a '\n' from a given start index. The line up to and
+ * inclusive the '\n' is considered to be the value.
+ * </p>
+ * <p>
+ * Note that this method does NOT find the accurate value, if the value goes
+ * over multiple lines! This may bear a serious problem. Usually this method
+ * is only used to finding the end of the last value in a found block, because
+ * mid- values are exactly determined by their start index and the start of
+ * the next caption. Nevertheless, if the last value spans over multiple
+ * lines, this method will not retrieve it completely.
+ * </p>
+ *
+ * @param text
+ * The text.
+ * @param start_index
+ * The start index from where the end of the value is sought.
+ * @return Returns the end index of the value, which is the index of the first
+ * character not belonging to the value anymore (the character after
+ * the '\n').
+ */
+ public static int findEndOfValue(String text, int start_index)
+ {
+ int newline_index = text.indexOf('\n', start_index);
+ if (newline_index < 0)
+ {
+ return text.length();
+ }
+ return newline_index + 1;
+ }
+
+ /**
+ * Checks the integrity of a found block.
+ *
+ * <p>
+ * This is an assertive function.
+ * </p>
+ *
+ * @param text
+ * The text.
+ * @param found_block
+ * The found block.
+ */
+ public static void checkBlockIntegrity(String text, FoundBlock found_block)
+ {
+ for (int i = 0; i < found_block.found_keys.size() - 1; i++)
+ {
+ FoundKey this_key = (FoundKey) found_block.found_keys.get(i);
+ FoundKey next_key = (FoundKey) found_block.found_keys.get(i + 1);
+
+ int this_end_index = findEndOfValue(text, this_key.start_index);
+ if (this_end_index != next_key.start_index)
+ {
+ logger.debug("multi line value: " + this_key);
+ // throw new RuntimeException("The end index of found key " + this_key +
+ // " doesn't match the start index of found key " + next_key);
+ }
+ }
+
+ FoundKey last_key = (FoundKey) found_block.found_keys.get(found_block.found_keys.size() - 1);
+ int end_of_block = findEndOfValue(text, last_key.start_index);
+ if (end_of_block == (last_key.start_index+last_key.caption.length()+1))
+ {
+ end_of_block = findEndOfValue(text,end_of_block);
+ }
+ if (end_of_block != found_block.end_index)
+ {
+ throw new RuntimeException("The end index of last key " + last_key + " doesn't match the end index of the block " + found_block);
+ }
+ }
+
+ /**
+ * Cuts out the given found block from the text.
+ *
+ * @param text
+ * The text.
+ * @param block
+ * The found block.
+ * @return Returns the rest text without the block.
+ */
+ public static String cutOutBlock(String text, FoundBlock block)
+ {
+ int block_start_index = ((FoundKey) block.found_keys.get(0)).getStartIndex();
+ int block_end_index = block.end_index;
+
+ if (block_start_index == 0 && block_end_index == text.length())
+ {
+ // the block is the whole text - the rest text is empty.
+ // This may happen if a (no-text) empty document contains a binary signature.
+ // Then the "signed text" of the binary signature is empty.
+ return "";
+ }
+
+ if (block_end_index == text.length())
+ {
+ // if the block is at the end of the text, remove the "\n" before the
+ // block as well.
+ String pre = text.substring(0, block_start_index - 1);
+ return pre;
+ }
+
+ String pre = text.substring(0, block_start_index);
+ String post = text.substring(block_end_index);
+
+ String rest_text = pre + post;
+ return rest_text;
+ }
+
+ /**
+ * Returns the value of the date field as String.
+ *
+ * @param text
+ * The text.
+ * @param block
+ * The found block.
+ * @return Returns the date value.
+ */
+ public static String getDateValue(String text, FoundBlock block)
+ {
+ FoundKey date_key = block.getDateFoundKey();
+ int date_value_start_index = date_key.start_index + date_key.caption.length();
+ int date_value_end_index = findEndOfValue(text, date_value_start_index);
+ if (date_value_end_index == (date_value_start_index+1))
+ {
+ date_value_end_index = findEndOfValue(text, date_value_end_index);
+ }
+ String date_value = text.substring(date_value_start_index, date_value_end_index).trim();
+ logger.debug("DateString="+date_value);
+ return date_value;
+ }
+
+ /**
+ * Creates a SignatureObject from a found block by extracting the
+ * corresponding values.
+ *
+ * @param text
+ * The text.
+ * @param found_block
+ * The found block.
+ * @return Returns the created SignatureObject.
+ * @throws SignatureTypesException
+ * F.e.
+ * @throws SignatureException
+ * F.e.
+ */
+ public static SignatureObject createSignatureObjectFromFoundBlock(
+ String text, FoundBlock found_block) throws SignatureTypesException, SignatureException
+ {
+ SignatureObject signatureObject = new SignatureObject();
+
+ signatureObject.setSigType(found_block.std.getType());
+ signatureObject.initByType();
+
+ int end_index = found_block.end_index;
+ for (int i = found_block.found_keys.size() - 1; i >= 0; i--)
+ {
+ FoundKey cur_key = (FoundKey) found_block.found_keys.get(i);
+ int start_index = cur_key.getStartIndex() + cur_key.caption.length();
+
+ String value = text.substring(start_index, end_index);
+
+ signatureObject.setSigValueCaption(cur_key.getKey(), value, cur_key.caption);
+
+ end_index = cur_key.getStartIndex();
+ }
+
+ return signatureObject;
+
+ }
+
+ /**
+ * Parses the EGIZDate from a found block and the given text.
+ *
+ * @param text
+ * The text.
+ * @param found_block
+ * The found block.
+ * @return Returns the parsed EGIZDate.
+ */
+ public static EGIZDate getDateFromFoundBlock(String text,
+ FoundBlock found_block)
+ {
+ String date_value = getDateValue(text, found_block);
+ EGIZDate date = EGIZDate.parseFromString(date_value);
+ return date;
+ }
+
+ /**
+ * Sorts the List of found blocks by date.
+ *
+ * @param text
+ * The text.
+ * @param found_blocks
+ * The List of found blocks.
+ */
+ public static void sortFoundBlocksByDate(final String text, List found_blocks)
+ {
+ Collections.sort(found_blocks, new Comparator()
+ {
+ public int compare(Object arg0, Object arg1)
+ {
+ FoundBlock fb0 = (FoundBlock) arg0;
+ FoundBlock fb1 = (FoundBlock) arg1;
+
+ EGIZDate date0 = getDateFromFoundBlock(text, fb0);
+ EGIZDate date1 = getDateFromFoundBlock(text, fb1);
+ return date0.compareTo(date1);
+ }
+ });
+ }
+
+ /**
+ * Given a List of FoundBlock objects, this method returns the last blocks of
+ * this list that have the same date.
+ *
+ * <p>
+ * Usually a date sorted list (earliest first, latest last) will be provided
+ * to this method. Then the last date equal blocks are returned, which are the
+ * last blocks.
+ * </p>
+ *
+ * @param text
+ * The text to retrieve the values of the fields from.
+ * @param found_blocks
+ * The List of FoundBlock objects.
+ * @return Returns the List of the last date equal blocks.
+ */
+ public static List filterLastDateEqualBlocks(String text, List found_blocks)
+ {
+ List latest_blocks = new ArrayList();
+ latest_blocks.add(found_blocks.get(found_blocks.size() - 1));
+ for (int i = found_blocks.size() - 2; i >= 0; i--)
+ {
+ FoundBlock this_block = (FoundBlock) found_blocks.get(i);
+ FoundBlock succ_block = (FoundBlock) found_blocks.get(i + 1);
+
+ EGIZDate this_date = getDateFromFoundBlock(text, this_block);
+ EGIZDate succ_date = getDateFromFoundBlock(text, succ_block);
+
+ if (!this_date.equals(succ_date))
+ {
+ break;
+ }
+ latest_blocks.add(0, this_block);
+ }
+
+ return latest_blocks;
+ }
+ /**
+ * Chooses the most possible (best choice) block of the list of blocks.
+ *
+ * <p>
+ * The strategy to find the most possible block is to choose the very one
+ * block with the maximum number of captions. This block has extracted most
+ * information from the text.
+ * </p>
+ * <p>
+ * If there are still multiple blocks with the same number of cations, the
+ * blocks are compared caption-wise. The block with all captions being longer
+ * or equal to all other blocks' captions wins.
+ * </p>
+ *
+ * @param found_blocks
+ * The List of semantically equal blocks.
+ * @return Returns the best choice FoundBlock.
+ * @throws SignatureException
+ */
+ public static FoundBlock chooseMostPossibleBlock(List found_blocks) throws SignatureException
+ {
+ // int largest_block_index = 0;
+ // FoundBlock largest_block = (FoundBlock) found_blocks.get(0);
+ //
+ // for (int i = 1; i < found_blocks.size(); i++)
+ // {
+ // FoundBlock current_block = (FoundBlock) found_blocks.get(i);
+ //
+ // if (current_block.found_keys.size() > largest_block.found_keys.size())
+ // {
+ // largest_block = current_block;
+ // largest_block_index = i;
+ // }
+ // }
+
+ List vertically_largest = filterVerticallyLargestBlocks(found_blocks);
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("vertically largest blocks:");
+ for (int i = 0; i < vertically_largest.size(); i++)
+ {
+ FoundBlock found_block = (FoundBlock) vertically_largest.get(i);
+ logger.debug(" #" + i + ": " + found_block);
+ }
+ }
+
+ List horizontally_largest = filterHorizontallyLargestBlocks(vertically_largest);
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("horizontally largest blocks:");
+ for (int i = 0; i < horizontally_largest.size(); i++)
+ {
+ FoundBlock found_block = (FoundBlock) horizontally_largest.get(i);
+ logger.debug(" #" + i + ": " + found_block);
+ }
+ }
+ FoundBlock largest_block = (FoundBlock) horizontally_largest.get(0);
+ logger.debug("Chose largest block: " + largest_block);
+ return largest_block;
+ }
+
+ /**
+ * Filters out all blocks but the vertically largest ones.
+ *
+ * <p>
+ * A vertically largest block has the most found keys.
+ * </p>
+ *
+ * @param found_blocks
+ * The List of FoundBlock objects to be filtered.
+ * @return Returns the List of the vertically largest FoundBlock objects.
+ */
+ public static List filterVerticallyLargestBlocks(List found_blocks)
+ {
+ // determine the size of the largest block(s)
+ int largest_size = Integer.MIN_VALUE;
+ for (int i = 0; i < found_blocks.size(); i++)
+ {
+ FoundBlock fb = (FoundBlock) found_blocks.get(i);
+ final int current_size = fb.found_keys.size();
+ if (current_size > largest_size)
+ {
+ largest_size = current_size;
+ }
+ }
+
+ // keep all blocks that have the largest_size
+ List largest_blocks = new ArrayList();
+ for (int i = 0; i < found_blocks.size(); i++)
+ {
+ FoundBlock fb = (FoundBlock) found_blocks.get(i);
+ if (fb.found_keys.size() < largest_size)
+ {
+ continue;
+ }
+ largest_blocks.add(fb);
+ }
+ return largest_blocks;
+ }
+
+ /**
+ * Filters out all blocks but the horizonally largest ones.
+ *
+ * <p>
+ * A vertically largest block has the most found keys.
+ * </p>
+ *
+ * @param found_blocks
+ * The List of FoundBlock objects to be filtered. All of these
+ * FoundBlock objects must have the same number of found keys.
+ * @return Returns the List of the horizontally largest FoundBlock objects.
+ * @throws SignatureException
+ */
+ public static List filterHorizontallyLargestBlocks(List found_blocks) throws SignatureException
+ {
+ List horizontally_largest = new ArrayList();
+ FoundBlock largest_block = (FoundBlock) found_blocks.get(0);
+ horizontally_largest.add(largest_block);
+
+ for (int i = 1; i < found_blocks.size(); i++)
+ {
+ FoundBlock fb = (FoundBlock) found_blocks.get(i);
+
+ if (isHorizontallyEqual(fb, largest_block))
+ {
+ horizontally_largest.add(fb);
+ continue;
+ }
+
+ if (isHorizontallyLarger(fb, largest_block))
+ {
+ horizontally_largest = new ArrayList();
+ largest_block = fb;
+ horizontally_largest.add(largest_block);
+ }
+ else
+ {
+ if (!isHorizontallyLarger(largest_block, fb))
+ {
+ // The block is neither equal nor larger nor lower.
+ // We cannot exactly determine which one to use.
+ throw new SignatureException(315, "The blocks are neither larger nor lower nor equal. Cannot decide which one to pick. fb = " + fb + ", largest_block = " + largest_block);
+ }
+ }
+
+ }
+
+ return horizontally_largest;
+ }
+
+ protected static boolean isHorizontallyEqual(FoundBlock fb0, FoundBlock fb1)
+ {
+ final int num_keys = fb0.found_keys.size();
+ if (num_keys != fb1.found_keys.size())
+ {
+ throw new IllegalArgumentException("Cannot compare FoundBlock keys: fb0 doesn't have the same number of keys as fb1. " + fb0.found_keys.size() + " vs. " + fb1.found_keys.size());
+ }
+
+ for (int i = 0; i < num_keys; i++)
+ {
+ FoundKey fk0 = (FoundKey) fb0.found_keys.get(i);
+ FoundKey fk1 = (FoundKey) fb1.found_keys.get(i);
+
+ if (fk0.caption.length() != fk1.caption.length())
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ protected static boolean isHorizontallyLarger(FoundBlock fb0, FoundBlock fb1)
+ {
+ final int num_keys = fb0.found_keys.size();
+ if (num_keys != fb1.found_keys.size())
+ {
+ throw new IllegalArgumentException("Cannot compare FoundBlock keys: fb0 doesn't have the same number of keys as fb1. " + fb0.found_keys.size() + " vs. " + fb1.found_keys.size());
+ }
+
+ boolean larger = false;
+
+ for (int i = 0; i < num_keys; i++)
+ {
+ FoundKey fk0 = (FoundKey) fb0.found_keys.get(i);
+ FoundKey fk1 = (FoundKey) fb1.found_keys.get(i);
+
+ if (fk0.caption.length() == fk1.caption.length())
+ {
+ continue;
+ }
+
+ if (fk0.caption.length() > fk1.caption.length())
+ {
+ larger = true;
+ continue;
+ }
+
+ // if (fk0.caption.length() < fk1.caption.length())
+ return false;
+ }
+
+ return larger;
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/ActualTablePos.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/ActualTablePos.java
new file mode 100644
index 0000000..6c0e56c
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/ActualTablePos.java
@@ -0,0 +1,42 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.pdf;
+
+/**
+ * The actual table position where the signature was placed after signation.
+ * @author wprinz
+ */
+public class ActualTablePos
+{
+ public int page;
+
+ public float x;
+
+ public float y;
+
+ public float width;
+
+ public float height;
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/AdobeSignatureHelper.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/AdobeSignatureHelper.java
new file mode 100644
index 0000000..e337e71
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/AdobeSignatureHelper.java
@@ -0,0 +1,272 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.pdf;
+
+import java.util.HashMap;
+import java.util.Iterator;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.Logger;
+
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.gv.egiz.pdfas.framework.signator.SignatorInformation;
+import at.gv.egiz.pdfas.utils.OgnlUtil;
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.exceptions.PresentableException;
+import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
+import at.knowcenter.wag.egov.egiz.sig.SignatureObject;
+
+import com.lowagie.text.Rectangle;
+import com.lowagie.text.pdf.AcroFields;
+import com.lowagie.text.pdf.PdfDictionary;
+import com.lowagie.text.pdf.PdfFormField;
+import com.lowagie.text.pdf.PdfName;
+import com.lowagie.text.pdf.PdfNumber;
+import com.lowagie.text.pdf.PdfObject;
+import com.lowagie.text.pdf.PdfSignature;
+import com.lowagie.text.pdf.PdfSignatureAppearance;
+import com.lowagie.text.pdf.PdfStamper;
+import com.lowagie.text.pdf.PdfString;
+
+/**
+ * Helper class for creating adobe signature attributes.
+ *
+ * @author dferbas
+ *
+ */
+public class AdobeSignatureHelper {
+ private static final String ADOBE_SIGN_FIELDNAME_KEY = "adobeSignFieldValue";
+
+ private static final String ADOBE_SIGN_REASONNAME_KEY = "adobeSignReasonValue";
+
+ private static final String ADOBE_SIG_ENABLED_KEY = "adobeSignEnabled";
+
+ private static Logger logger = Logger.getLogger(AdobeSignatureHelper.class);
+
+ public static final String ADOBE_SIG_FILTER = "Adobe.PDF-AS";
+
+ public static final String ADOBE_SIG_TEXT_KEY = "adobeSignText";
+
+ private static final String ADOBE_VERIFY_URL_KEY = "verifyURL";
+
+ /**
+ * Writes Adobe-pdf signature entry with itext
+ *
+ * @param stamper
+ * @param si
+ * @param so
+ * @param atp
+ * @throws PresentableException
+ */
+ public static void createAdobeSignatureField(PdfStamper stamper, SignatorInformation si,
+ SignatureObject so, ActualTablePos atp, StructContentHelper structHelper) throws PresentableException {
+
+ try {
+ logger.debug("Creating adobe signature field.");
+ PdfSignatureAppearance sap = stamper.getSignatureAppearance();
+
+ String profileId = so.getSignatureTypeDefinition().getType();
+ String fieldName = getAdobeFieldName(profileId);
+ // find field num
+ /*
+ int nexSigNum = 1;
+ String finalFieldName = fieldName + " #" + nexSigNum;
+
+ while (stamper.getAcroFields().getField(finalFieldName) != null) {
+ nexSigNum++;
+ finalFieldName = fieldName + " #" + nexSigNum;
+ }
+ */
+
+ AcroFields af = stamper.getAcroFields();
+ Iterator signatureNamesIt = af.getSignatureNames().iterator();
+ PdfName referenceFilterName = new PdfName(ADOBE_SIG_FILTER);
+ int nextSigNum = 1;
+ while (signatureNamesIt.hasNext()) {
+ PdfDictionary dictionary = (PdfDictionary) af.getSignatureDictionary((String) signatureNamesIt.next());
+ PdfObject filterName = dictionary.get(PdfName.FILTER);
+ if (filterName != null && filterName.isName()) {
+ PdfName name = (PdfName) filterName;
+ if (referenceFilterName.equals(name)) {
+ nextSigNum++;
+ }
+ }
+ }
+ String finalFieldName = fieldName + " #" + nextSigNum;
+
+ sap.setCrypto(null, null, null, null);
+ // supress overlay text for visible signatures
+ sap.setLayer2Text("");
+ sap.setLayer4Text("");
+
+ // the following line marks the sig block as adobe sig
+ // sap.setVisibleSignature(createRectangleFromTablePos(iui.actualTablePos),
+ // iui.actualTablePos.page, "PDF-AS-Signatur");
+ sap.setVisibleSignature(new Rectangle(0, 0, 0, 0), atp.page, finalFieldName);
+ String subfilter = "unknown";
+ if (so != null && so.getKZ() != null) {
+ subfilter = so.getKZ().toString();
+ } else if (si != null) {
+ subfilter = si.getSignSignatureObject().kz;
+ }
+ PdfSignature sig = new PdfSignature(new PdfName(ADOBE_SIG_FILTER), new PdfName(subfilter));
+ // the following fields are not shown by the reader, because its is no
+ // Standard filter
+ // sig.setLocation("location is not visible");
+ // sig.setReason("reason is not visible");
+
+ // contact field is used to embed signature verification url for adobe handler
+ String verifyURL = getVerifyUrl(profileId);
+ if (!StringUtils.isEmpty(verifyURL)) {
+ sig.setContact(getVerifyUrl(profileId));
+ } else {
+ logger.debug("No verify URL set -> verify URL is not embedded.");
+ }
+ // sig.setDate(new PdfDate());
+
+ String reason = getAdobeReasonName(profileId);
+ if (!StringUtils.isEmpty(reason)) {
+ sig.setReason(reason);
+ }
+
+
+ /* disabled in order to align adobe signature appearance for textual signatures with binary signatures
+ if (si != null) {
+ XMLGregorianCalendar c = DatatypeFactory.newInstance().newXMLGregorianCalendar(
+ si.getSignSignatureObject().date);
+ sig.setDate(new PdfDate(c.toGregorianCalendar()));
+ }
+ */
+
+ sig.setName(getAdobeSignText(profileId, si));
+ sap.setCryptoDictionary(sig);
+ sap.setCertificationLevel(PdfSignatureAppearance.NOT_CERTIFIED);
+
+ // content element is mandatory but empty
+ HashMap exc = new HashMap();
+ exc.put(PdfName.CONTENTS, new Integer(2));
+
+ PdfNumber parentNum = structHelper.buildAdobeSigStructParent();
+ if (parentNum != null) {
+ PdfFormField sigField = PdfFormField.createSignature(stamper.getWriter());
+ sap.setSigFormField(sigField);
+ sigField.put(PdfName.STRUCTPARENT, parentNum);
+ structHelper.buildAdobeSigStruct(sigField, finalFieldName);
+ }
+ sap.preClose(exc); // *2+2
+
+ PdfDictionary dic = new PdfDictionary();
+ dic.put(PdfName.CONTENTS, new PdfString((String) null).setHexWriting(true));
+ sap.close(dic);
+ } catch (Exception ex) {
+ logger.error("error", ex);
+ throw new PresentableException(ErrorCode.CANNOT_WRITE_PDF,
+ "Error creating adobe signature attribute", ex);
+ }
+ }
+
+
+ /**
+ * Returns if adobe signature is enabled for the passed signature profile.
+ * Config key: {@value #ADOBE_SIG_ENABLED_KEY}
+ * @param sigProfile
+ * @return
+ */
+ public static boolean isAdobeSignatureFieldEnabled(String sigProfile) {
+ return "true".equalsIgnoreCase(
+ getDefaultableConfigProperty(sigProfile, ADOBE_SIG_ENABLED_KEY, "false"));
+ }
+
+ protected static Rectangle createRectangleFromTablePos(ActualTablePos pos) {
+ return new Rectangle(pos.x, pos.y, pos.x + pos.width, pos.y - pos.height);
+ }
+
+ private static String getAdobeFieldName(String sigProfile) {
+ return getDefaultableConfigProperty(sigProfile, ADOBE_SIGN_FIELDNAME_KEY, "PDF-AS Signatur");
+ }
+
+ private static String getAdobeReasonName(String sigProfile) {
+ return getDefaultableConfigProperty(sigProfile, ADOBE_SIGN_REASONNAME_KEY, "Informationen zur Prüfung finden Sie unter http://www.signaturpruefung.gv.at");
+ }
+
+ private static String getVerifyUrl(String sigProfile) {
+ return getDefaultableConfigProperty(sigProfile, ADOBE_VERIFY_URL_KEY, "http://www.signaturpruefung.gv.at");
+ }
+
+ public static String getDefaultableConfigProperty(String sigProfile, String propName, String defaultValue) {
+ String confVal;
+ try {
+ confVal = SettingsReader.getInstance().getSetting(
+ "sig_obj." + sigProfile + "." + propName,
+ "default." + propName,
+ defaultValue);
+ } catch (SettingsException e) {
+ logger.warn("error reading " + propName + " from config. Using default: " + defaultValue, e);
+ return defaultValue;
+ }
+ return confVal;
+ }
+
+ /**
+ * Evaluate name for adobe signature field. Get from config. Evaluate ognl if
+ * ok.
+ *
+ * @param sigProfile
+ * @param si
+ * @return
+ */
+ private static String getAdobeSignText(String sigProfile, SignatorInformation si) {
+ String defaultName = "PDF-AS";
+ try {
+ logger.debug("reading adobe sig name for profile: " + sigProfile);
+ String propKey = ADOBE_SIG_TEXT_KEY + ".textual";
+ if (si == null) {
+ propKey = propKey.replaceAll("textual", "binary");
+ }
+ String adobeStr = getDefaultableConfigProperty(sigProfile, propKey, defaultName);
+
+ HashMap ognlCtx = new HashMap();
+ OgnlUtil ognl = new OgnlUtil(ognlCtx);
+ if (ognl.containsExpression(adobeStr)) {
+ if (si == null) {
+ logger
+ .error(ADOBE_SIG_TEXT_KEY
+ + " ognl expressions not allowed for binary signatures (SignatorInformation not available)");
+ return defaultName;
+ }
+ ognlCtx.put("si", si);
+ ognlCtx.put("sso", si.getSignSignatureObject());
+ String res = ognl.compileMessage(adobeStr);
+ return res;
+ } else {
+ return adobeStr;
+ }
+
+ } catch (Exception ex) {
+ logger.warn("error creating adobe sign text, using default '" + defaultName + "'", ex);
+ return defaultName;
+ }
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/BinaryBlockInfo.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/BinaryBlockInfo.java
new file mode 100644
index 0000000..2087712
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/BinaryBlockInfo.java
@@ -0,0 +1,61 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: BinaryBlockInfo.java,v 1.1 2006/08/25 17:10:08 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.pdf;
+
+import java.util.List;
+
+/**
+ * Helper class that holds information about a binary signature block.
+ *
+ * @author wprinz
+ */
+public class BinaryBlockInfo
+{
+ /**
+ * The signed size, in bytes.
+ *
+ * <p>
+ * This includes the block itself.
+ * </p>
+ */
+ public int signed_size = -1;
+
+ /**
+ * The List of ReplaceInfo objects that specify the replaced strings.
+ */
+ public List replaces = null;
+
+// /**
+// * The start of the /ODS number in the PDF.
+// */
+// public int ods_start = -1;
+//
+// /**
+// * The start of the \replaces array in the PDF.
+// */
+// public int array_start = -1;
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/BinarySignature.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/BinarySignature.java
new file mode 100644
index 0000000..ece9525
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/BinarySignature.java
@@ -0,0 +1,2145 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: BinarySignature.java,v 1.4 2006/10/11 07:57:58 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.pdf;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+
+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.pdf.CaptionNotFoundException;
+import at.gv.egiz.pdfas.exceptions.pdf.KZSettingNotFoundException;
+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.placeholder.SignaturePlaceholderContext;
+import at.gv.egiz.pdfas.placeholder.SignaturePlaceholderData;
+import at.gv.egiz.pdfas.utils.PDFASUtils;
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException;
+import at.knowcenter.wag.egov.egiz.exceptions.PlaceholderException;
+import at.knowcenter.wag.egov.egiz.exceptions.PresentableException;
+import at.knowcenter.wag.egov.egiz.exceptions.SettingNotFoundException;
+import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
+import at.knowcenter.wag.egov.egiz.sig.SignatureFieldDefinition;
+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.tools.CodingHelper;
+import at.knowcenter.wag.exactparser.ByteArrayUtils;
+
+import com.lowagie.text.BadElementException;
+import com.lowagie.text.Document;
+import com.lowagie.text.DocumentException;
+import com.lowagie.text.Image;
+import com.lowagie.text.Rectangle;
+import com.lowagie.text.pdf.BadPdfFormatException;
+import com.lowagie.text.pdf.PRStream;
+import com.lowagie.text.pdf.PdfArray;
+import com.lowagie.text.pdf.PdfContentByte;
+import com.lowagie.text.pdf.PdfDictionary;
+import com.lowagie.text.pdf.PdfImage;
+import com.lowagie.text.pdf.PdfIndirectObject;
+import com.lowagie.text.pdf.PdfIndirectReference;
+import com.lowagie.text.pdf.PdfName;
+import com.lowagie.text.pdf.PdfNumber;
+import com.lowagie.text.pdf.PdfObject;
+import com.lowagie.text.pdf.PdfPTable;
+import com.lowagie.text.pdf.PdfReader;
+import com.lowagie.text.pdf.PdfStamper;
+import com.lowagie.text.pdf.PdfStamperImp;
+import com.lowagie.text.pdf.PdfString;
+import com.lowagie.text.pdf.PdfTemplate;
+
+/**
+ * Contains various extension functions to digitally sign documents.
+ *
+ * <p>
+ * These functions are used to replace parts of the original Egiz plain text
+ * signature mechanism.
+ * </p>
+ *
+ * @author wprinz
+ */
+public abstract class BinarySignature
+{
+//23.11.2010 changed by exthex - added replacePlaceholder(PdfStamper stamper, int pageNr, String placeholderName) method
+
+ protected static Log logger = LogFactory.getLog(BinarySignature.class);
+ /**
+ * The tolerance area of the line break algorithm.
+ *
+ * @see Placeholder#replacePlaceholderWithTolerance(byte[], List, byte[], int)
+ */
+ public static final int LINE_BREAK_TOLERANCE = 10;
+
+ /**
+ * The number of bytes left out for the certificate placeholder.
+ */
+ public static final int CERTIFICATE_PLACEHOLDER_LENGTH = 10000;
+
+ /**
+ * The number of bytes left out for the timestamp placeholder.
+ */
+ public static final int TIMESTAMP_PLACEHOLDER_LENGTH = 5000;
+
+ /**
+ * The placeholder character used to fill out Strings in the layout process.
+ */
+ public static final byte LAYOUT_PLACEHOLDER = 'w';
+
+ /**
+ * This placeholder is used to fill out holes between the byte ranges before
+ * the document is signed.
+ */
+ public static final byte SIGN_PLACEHOLDER = 0;
+
+ /**
+ * The nil brev used to define an unrecognized value.
+ */
+ public static final byte[] BREV_NIL = { 'n', 'i', 'l' };
+
+ /**
+ * The date brev.
+ */
+ public static final byte[] BREV_DAT = { 'd', 'a', 't' };
+
+ /**
+ * The issure brev.
+ */
+ public static final byte[] BREV_ISS = { 'i', 's', 's' };
+
+ /**
+ * The serial number brev.
+ */
+ public static final byte[] BREV_SNR = { 's', 'n', 'r' };
+
+ /**
+ * The value brev.
+ */
+ public static final byte[] BREV_VAL = { 'v', 'a', 'l' };
+
+ /**
+ * The SIG_ID brev.
+ */
+ public static final byte[] BREV_SID = { 's', 'i', 'd' };
+
+ /**
+ * The SIG_ALG brev.
+ */
+ public static final byte[] BREV_ALG = { 'a', 'l', 'g' };
+
+ /**
+ * No explicit encoding.
+ */
+ public static final byte[] ENCODING_NIL = { 'n', 'i', 'l' };
+
+ /**
+ * PDF WinAnsiEncoding.
+ */
+ public static final byte[] ENCODING_WIN = { 'w', 'i', 'n' };
+
+ /**
+ * URL encoding.
+ */
+ public static final byte[] ENCODING_URL = { 'u', 'r', 'l' };
+
+ /**
+ * The PDFName of the Egiz Dictionary.
+ *
+ * <p>
+ * Used to locate and identify the Egiz Dictionary in the document.
+ * </p>
+ */
+ public static final PdfName EGIZ_DICT_NAME = new PdfName("EGIZSigDict");
+
+ /**
+ * The PDFName of the Original Document Size (ODS) field in an Egiz
+ * Dictionary.
+ *
+ * <p>
+ * The ODS must be a positive integral number.
+ * </p>
+ */
+ public static final PdfName EGIZ_ODS_NAME = new PdfName("ODS");
+
+ /**
+ * The PDFName of the Kennzeichnung attribute.
+ */
+ public static final PdfName EGIZ_KZ_NAME = new PdfName("ID");
+
+ /**
+ * The PDFName of the /replaces field in an Egiz Dictionary.
+ */
+ public static final PdfName EGIZ_REPLACES_NAME = new PdfName("replaces");
+
+ /**
+ * The PDFName of the /encodings field in an Egiz Dictionary.
+ */
+ public static final PdfName EGIZ_ENCODINGS_NAME = new PdfName("encodings");
+
+ /**
+ * The PDFName of the byte ranges array.
+ */
+ public static final PdfName EGIZ_BYTERANGES_NAME = new PdfName("ByteRange");
+
+ /**
+ * The PdfName of the certificate array.
+ */
+ public static final PdfName EGIZ_CERTIFICATE_NAME = new PdfName("Cert");
+
+ /**
+ * The PdfName of the Timestamp
+ */
+ public static final PdfName EGIZ_TIMESTAMP_NAME = new PdfName("TimeStamp");
+
+ /**
+ * The PdfName of the data array that contains various egiz-dict data.
+ */
+ public static final PdfName EGIZ_DATA_NAME = new PdfName("Data");
+
+ /**
+ * The PDFName of the Signature XObject field in an Egiz Dictionary.
+ *
+ * <p>
+ * This must be an indirect reference to the XObject containing the Signature
+ * table.
+ * </p>
+ */
+ public static final PdfName EGIZ_XOBJ_NAME = new PdfName("SigXObject");
+
+ /**
+ * The number placeholder that is used to give numbers a fixed length.
+ */
+ protected static final PdfNumber NUMBER_PLACEHOLDER = new PdfNumber(999999999);
+
+ /**
+ * Extracts the signature text only.
+ *
+ * <p>
+ * The signature text is the text of the Signature XObject.
+ * </p>
+ *
+ * @param egiz_dict
+ * The Egiz Dictionary.
+ *
+ * @return Returns the signature text.
+ */
+ public static String extractSignatureTextOnly(PdfDictionary egiz_dict) throws IOException
+ {
+ PdfIndirectReference xobj_ir = (PdfIndirectReference) egiz_dict.get(EGIZ_XOBJ_NAME);
+ PRStream temp_stream = (PRStream) PdfReader.getPdfObject(xobj_ir);
+
+ byte[] stream_bytes = PdfReader.getStreamBytes(temp_stream);
+
+ return Utils.extractPureTextFromContentStream(stream_bytes);
+ }
+
+ /**
+ * Retrieves the size of the original document from the Egiz Dictionary.
+ *
+ * @param egiz_dict
+ * The Egiz Dictionary.
+ * @return Returns the size (in bytes) of the original document.
+ */
+ public static int getOriginalDocumentSizeFromEgizDict(PdfDictionary egiz_dict)
+ {
+ PdfObject ods_obj = egiz_dict.get(EGIZ_ODS_NAME);
+ PdfNumber ods_number = (PdfNumber) PdfReader.getPdfObject(ods_obj);
+
+ return ods_number.intValue();
+ }
+
+ /**
+ * Retrieves the previous Egiz dictionary from the given one, if a previous
+ * dictionary exists.
+ *
+ * @param egiz_dict
+ * The Egiz Dictionary.
+ * @return Returns the previous Egiz Dictionary, or null if there is none.
+ */
+ public static PdfDictionary getPreviousFromEgizDict(PdfDictionary egiz_dict)
+ {
+ PdfObject prev_obj = egiz_dict.get(PdfName.PREV);
+ PdfDictionary previous_dict = (PdfDictionary) PdfReader.getPdfObject(prev_obj);
+ return previous_dict;
+ }
+
+ /**
+ * Retrieves the Egiz Dictionary from the document if present.
+ *
+ * @param reader
+ * The reader to retrieve the dictionary from.
+ * @return Returns the Egiz Dictionary, if present, or returns null, if no
+ * egiz dictionary was found.
+ */
+ public static PdfDictionary getEgizDictFromReader(PdfReader reader)
+ {
+ PdfIndirectReference dict_ir = getEgizDictIndRefFromReader(reader);
+ if (dict_ir == null)
+ {
+ return null;
+ }
+
+ PdfDictionary egiz_dict = (PdfDictionary) PdfReader.getPdfObject(dict_ir);
+
+ return egiz_dict;
+ }
+
+ /**
+ * Retrieves the Egiz Dictionary's indirect reference from the reader.
+ *
+ * @param reader
+ * The reader.
+ * @return Returns the indirect reference of the Egiz Dictionary, or null, if
+ * none exists.
+ */
+ public static PdfIndirectReference getEgizDictIndRefFromReader(PdfReader reader)
+ {
+ PdfDictionary catalog = reader.getCatalog();
+ PdfIndirectReference dict_ir = (PdfIndirectReference) catalog.get(EGIZ_DICT_NAME);
+ return dict_ir;
+ }
+
+ /**
+ * Retrieves the chain of Egiz Dictionaries from the reader.
+ *
+ * <p>
+ * The first element in the List will be the top most (oldest) Egiz
+ * Dictionary. The last element in the List will be the bottom most (latest)
+ * Egiz Dictionary. If the list is empty, no dictionary could be found at all,
+ * which means that the document is not digitally signed.
+ * </p>
+ *
+ * @param reader
+ * The reader.
+ * @return Returns the List of PdfDictionaries from the document.
+ */
+ public static List getEgizDictChainFromReader(PdfReader reader)
+ {
+ List dicts = new ArrayList();
+
+ PdfDictionary current_dict = getEgizDictFromReader(reader);
+ if (current_dict != null)
+ {
+ dicts.add(0, current_dict);
+
+ while ((current_dict = getPreviousFromEgizDict(current_dict)) != null)
+ {
+ dicts.add(0, current_dict);
+ }
+ }
+
+ return dicts;
+ }
+
+ /**
+ * Builds a digest of the given data.
+ *
+ * @param data
+ * The data to be digested.
+ * @param length
+ * The length of the data portion that should be used for digesting.
+ * This allows to build the digest only over parts of the data.
+ * @return Returns the created digest.
+ * @throws PDFDocumentException
+ * Forwarded exception.
+ */
+ public static byte[] buildDigest(final byte[] data, final int length) throws PDFDocumentException
+ {
+ MessageDigest sha_512 = null;
+ try
+ {
+ sha_512 = MessageDigest.getInstance("SHA-512");
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ e.printStackTrace();
+ throw new PDFDocumentException(202, "Digest algorithm not supported - NoSuchAlgorithmException", e);
+ }
+
+ sha_512.reset();
+ sha_512.update(data, 0, length);
+ byte[] digest = sha_512.digest();
+
+ return digest;
+ }
+
+ /**
+ * Retrieves the signable text from the given document.
+ *
+ * @param data
+ * The data.
+ * @param ods
+ * The original document size.
+ * @return Returns the signable text.
+ */
+ public static String retrieveSignableTextFromData(final byte[] data, final int ods)
+ {
+ // byte[] digest = buildDigest(data, ods);
+ String raw_text = CodingHelper.encodeBase64(data);// digest); // data);
+
+ return raw_text;
+ }
+
+ /**
+ * Fills the holes in the byte ranges with the SIGN_PLACEHOLDER.
+ *
+ * @param data
+ * The given byte ranged data.
+ * @param byte_ranges
+ * The byte ranges.
+ * @return Returns the filled text.
+ */
+ public static byte[] prepareDataToSign(final byte[] data, final List byte_ranges)
+ {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ Iterator it = byte_ranges.iterator();
+ int last_end = 0;
+ while (it.hasNext())
+ {
+ StringInfo si = (StringInfo) it.next();
+
+ for (int i = last_end; i < si.string_start; i++)
+ {
+ baos.write(SIGN_PLACEHOLDER);
+ }
+
+ baos.write(data, si.string_start, si.string_length);
+
+ last_end = si.string_start + si.string_length;
+ }
+ byte[] data_to_sign = baos.toByteArray();
+
+ return data_to_sign;
+ }
+
+ // TODO old code - remove
+ // /**
+ // * Extracts the binary 'text' of a document.
+ // *
+ // * <p>
+ // * If the document contains an Egiz Dictionary, which means that it is
+ // already
+ // * signed, the binary text is the Base64 coded string of the original
+ // document
+ // * followed by the Ascii representation of the signature block.
+ // * </p>
+ // * <p>
+ // * If the document does not contain an Egiz Dictionary, which means that it
+ // is
+ // * unsigned, only the binary Base64 coded original document is returned as
+ // * binary text.
+ // * </p>
+ // * <p>
+ // * This function is intented for being used instead of the "text extraction"
+ // * mechanism used in the plain text Egiz project.
+ // * </p>
+ // *
+ // * @param doc
+ // * The file.
+ // * @return Returns the binary text of the document.
+ // * @throws PDFDocumentException
+ // * Forwarded exception.
+ // */
+ // public static String extractTextBinary(File doc) throws
+ // PDFDocumentException
+ // {
+ // try
+ // {
+ // FileInputStream fis = new FileInputStream(doc);
+ // return extractTextBinary(fis);
+ // }
+ // catch (FileNotFoundException e)
+ // {
+ // throw new PDFDocumentException(202, e);
+ // }
+ // }
+ //
+ // /**
+ // * Extracts the text binary.
+ // *
+ // * @param is
+ // * @return Returns the binary text.
+ // * @throws PDFDocumentException
+ // */
+ // public static String extractTextBinary(InputStream is) throws
+ // PDFDocumentException
+ // {
+ // try
+ // {
+ // // for some stupid reason this produces a read error if the is comes from
+ // // a
+ // // multipart servlet form..???
+ // ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ // int i = -1;
+ // int acc = 0;
+ // byte[] b = new byte[1000];
+ // while ((i = is.read(b)) > 0)
+ // {
+ // acc += i;
+ // System.out.print(" " + i);
+ // baos.write(b, 0, i);
+ // }
+ // System.out.println("acc = " + acc);
+ // byte[] pdf = baos.toByteArray();
+ //
+ // return extractTextBinary(pdf);
+ // }
+ // catch (IOException e)
+ // {
+ // throw new PDFDocumentException(202, e);
+ // }
+ // }
+ //
+ // /**
+ // * Extracts the signable text from a binary pdf document.
+ // *
+ // * <p>
+ // * The signable text is the text that will be signed or verified afterwards.
+ // * </p>
+ // *
+ // * @param pdf
+ // * The pdf document.
+ // * @return Returns the extracted text String.
+ // * @throws PDFDocumentException
+ // * Forwarded exception.
+ // */
+ // public static String extractTextBinary(final byte[] pdf) throws
+ // PDFDocumentException
+ // {
+ // try
+ // {
+ // PdfReader reader = new PdfReader(new ByteArrayInputStream(pdf));
+ // PdfDictionary egiz_dict = getEgizDictFromReader(reader);
+ // if (egiz_dict == null)
+ // {
+ // System.out.println("NO Egiz Dict found - whole doc = original doc");
+ //
+ // int ods = pdf.length;
+ // return retrieveSignableTextFromData(pdf, ods);
+ // }
+ //
+ // String sig_text = extractSignatureTextOnly(egiz_dict);
+ //
+ // int ods = getOriginalDocumentSizeFromEgizDict(egiz_dict);
+ //
+ // String raw_text = retrieveSignableTextFromData(pdf, ods);
+ // raw_text += "\n";
+ // raw_text += sig_text;
+ //
+ // return raw_text;
+ // }
+ // catch (IOException e)
+ // {
+ // throw new PDFDocumentException(202, e);
+ // }
+ // }
+
+ // TODO obsolete code - remove
+ // /**
+ // * Retrieves the List of SignatureHolders containing the information of all
+ // * digital signatures of the given document.
+ // *
+ // * <p>
+ // * If the List of SignatureHolders is empty, the document is not signed
+ // * anyways.
+ // * </p>
+ // *
+ // * @param pdf
+ // * The complete pdf document.
+ // * @return Returns the List of SignatureHolders.
+ // * @throws PDFDocumentException
+ // * @throws SignatureTypesException
+ // * @throws SignatureException
+ // */
+ // public static List extractSignatureHoldersBinary(final byte[] pdf) throws
+ // PDFDocumentException, SignatureTypesException, SignatureException
+ // {
+ // try
+ // {
+ // PdfReader reader = new PdfReader(new ByteArrayInputStream(pdf));
+ // List chain = getEgizDictChainFromReader(reader);
+ //
+ // List signatures = new ArrayList();
+ // Iterator it = chain.iterator();
+ // while (it.hasNext())
+ // {
+ // PdfDictionary dict = (PdfDictionary) it.next();
+ //
+ // int ods = getOriginalDocumentSizeFromEgizDict(dict);
+ // String signature_text = extractSignatureTextOnly(dict);
+ //
+ // SignatureTypes sig_types = SignatureTypes.getInstance();
+ // List types = sig_types.getSignatureTypeDefinitions();
+ // SignatureBlock sig_block = new SignatureBlock(types);
+ // boolean could_separate = sig_block.separateBlockFromRawText(signature_text,
+ // false);
+ //
+ // if (could_separate)
+ // {
+ // SignatureObject sig_object = sig_block.getSignatureObject();
+ //
+ // SignatureHolder holder = new BinarySignatureHolder(pdf, ods, sig_object);
+ // signatures.add(holder);
+ // }
+ // }
+ //
+ // return signatures;
+ // }
+ // catch (IOException e)
+ // {
+ // throw new PDFDocumentException(201, e);
+ // }
+ // }
+
+ // /**
+ // * Signs a document with the given signature table using the Incremental
+ // * Update method.
+ // *
+ // * <p>
+ // * The table containing the signature text will be appended. As specified by
+ // * the parameters, the signature will be appended to the last page, or a
+ // plain
+ // * new page will be created for the signature to hold.
+ // * </p>
+ // * <p>
+ // * The table will be completely wrapped by an XObject, which will also be
+ // * indirectly referenced by the Egiz Dictionary. This will ease the
+ // * verification process.
+ // * </p>
+ // * <p>
+ // * An Egiz Dictionary will be added to the new document that contains
+ // * information about the signature. Basically the size of the original
+ // * document and the reference of the signature table.
+ // * </p>
+ // *
+ // * @param original_document
+ // * The file name of the original document.
+ // * @param new_document
+ // * The file name of the new document to be created.
+ // * @param pdf_table
+ // * The PdfPTable that contains the signature block.
+ // * @param pos_x
+ // * The x position where the table should be inserted.
+ // * @param pos_y
+ // * The y position where the table should be inserted (on the last
+ // * page). If this is negative, a new page will be appended to the
+ // * document. Then the table will be inserted on that new page using
+ // * the absolute value of pos_y. Note that pos_y specifies the top
+ // * line of the table.
+ // * @throws PresentableException
+ // * Forwarded exception.
+ // *
+ // * @see #writeIncrementalUpdate(byte[], PdfPTable, float, float, boolean)
+ // */
+ // public static void writeIncrementalUpdate(String original_document,
+ // String new_document, PdfPTable pdf_table, float pos_x, float pos_y,
+ // int egiz_dict_num_replaces) throws PresentableException
+ // {
+ // try
+ // {
+ // File original_document_file = new File(original_document);
+ // FileInputStream fis = new FileInputStream(original_document_file);
+ // byte[] pdf = new byte[(int) original_document_file.length()];
+ // fis.read(pdf);
+ // fis.close();
+ //
+ // byte[] signed_pdf = writeIncrementalUpdate(pdf, pdf_table, pos_x, pos_y,
+ // egiz_dict_num_replaces);
+ //
+ // File new_document_file = new File(new_document);
+ // FileOutputStream fos = new FileOutputStream(new_document_file);
+ // fos.write(signed_pdf);
+ // fos.close();
+ // }
+ // catch (IOException e)
+ // {
+ // throw new PresentableException(e);
+ // }
+ // }
+
+ protected static int getLineBreakTolerance(IncrementalUpdateInformation iui) throws PDFDocumentException
+ {
+ SettingsReader settings;
+ try
+ {
+ settings = SettingsReader.getInstance();
+ }
+ catch (SettingsException e)
+ {
+ throw new PDFDocumentException(e.getErrorCode(), e);
+ }
+ String phLineBreakTolerance = SignatureTypeDefinition.readPhLenStringFromSettings(settings, iui.signProfile, "line_break_tolerance");
+ int lineBreakTolerance = LINE_BREAK_TOLERANCE;
+ if (phLineBreakTolerance != null)
+ {
+ lineBreakTolerance = Integer.parseInt(phLineBreakTolerance);
+ }
+ return lineBreakTolerance;
+ }
+
+ protected static int getCertificatePlaceholderLength(IncrementalUpdateInformation iui) throws SettingNotFoundException
+ {
+ SettingsReader settings;
+ try
+ {
+ settings = SettingsReader.getInstance();
+ }
+ catch (SettingsException e)
+ {
+ throw new SettingNotFoundException(e);
+ }
+ String certPhLen = SignatureTypeDefinition.readPhLenStringFromSettings(settings, iui.signProfile, "certificate");
+ int certLen = CERTIFICATE_PLACEHOLDER_LENGTH;
+ if (certPhLen != null)
+ {
+ certLen = Integer.parseInt(certPhLen);
+ }
+ return certLen;
+ }
+
+ protected static int getTimestampPlaceholderLength(IncrementalUpdateInformation iui) throws SettingNotFoundException
+ {
+ SettingsReader settings;
+ try
+ {
+ settings = SettingsReader.getInstance();
+ }
+ catch (SettingsException e)
+ {
+ throw new SettingNotFoundException(e);
+ }
+ String phLen = SignatureTypeDefinition.readPhLenStringFromSettings(settings, iui.signProfile, "timestamp");
+ int tsLen = TIMESTAMP_PLACEHOLDER_LENGTH;
+ if (phLen != null)
+ {
+ tsLen = Integer.parseInt(phLen);
+ }
+ return tsLen;
+ }
+
+ /**
+ * Signs a document with the given signature table using the Incremental
+ * Update method.
+ *
+ * <p>
+ * The table containing the signature text will be appended. As specified by
+ * the parameters, the signature will be appended to the last page, or a plain
+ * new page will be created for the signature to hold.
+ * </p>
+ * <p>
+ * The table will be completely wrapped by an XObject, which will also be
+ * indirectly referenced by the Egiz Dictionary. This will ease the
+ * verification process.
+ * </p>
+ * <p>
+ * An Egiz Dictionary will be added to the new document that contains
+ * information about the signature. Basically the size of the original
+ * document and the reference of the signature table.
+ * </p>
+ *
+ * @param original_document
+ * The original document.
+ * @param pdf_table
+ * The PdfPTable that contains the signature block.
+ * @param pi
+ * The PositioningInstruction telling the algorithm where to place
+ * the signature block.
+ * @param invisible_field_definitions
+ * List of invisible field definitions to be added to the egiz dict.
+ * May be null or empty, if there are no invisible fields.
+ * @param invisibleKZString
+ * If not null, thins String is the KZ String to be written into the
+ * /Data array.
+ * @return Returns the new document.
+ * @throws PresentableException
+ * Forwarded exception.
+ */
+ public static IncrementalUpdateInformation writeIncrementalUpdate(PdfDataSource original_document, DataSink written_pdf, 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
+ {
+ try
+ {
+ IncrementalUpdateInformation iui = new IncrementalUpdateInformation();
+ iui.original_document = original_document;
+ iui.start_index = original_document.getLength();
+ iui.signProfile = profile;
+ iui.timeStamper = timeStamper;
+
+ Document.compress = true; // exthex : compress now, excluding the xobject later
+
+ // System.out.println("wprinz: STAMPING PDF");
+
+ // InputStream is = original_document.createInputStream();
+ byte[] pdf_data = original_document.getAsByteArray();
+ PdfReader reader = new PdfReader(pdf_data);
+ PDFASUtils.checkReaderPermissions(reader);
+ // is.close();
+
+ OutputStream baos = written_pdf.createOutputStream("application/pdf");
+ // ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ // IMPORTANT: append the new content to the original document using
+ // incremental updated
+ // The stamper allows this by setting append = true
+ boolean adobeSigField = AdobeSignatureHelper.isAdobeSignatureFieldEnabled(so.getSignatureTypeDefinition().getType());
+ PdfStamper stamper = null;
+ if (adobeSigField) {
+ stamper = PdfStamper.createSignature(reader, baos, '\0', null, true);
+ } else {
+ stamper = new PdfStamper(reader, baos, '\0', true);
+ }
+
+ if (pi.isMakeNewPage())
+ {
+ int pdf_page_num = reader.getNumberOfPages();
+
+ Rectangle psize = reader.getPageSizeWithRotation(pdf_page_num);
+ Rectangle rect = new Rectangle(psize);
+ stamper.insertPage(pdf_page_num + 1, rect);
+ }
+
+ if (pi.getPage() < 1 || pi.getPage() > stamper.getReader().getNumberOfPages())
+ {
+ throw new PDFDocumentException(224, "The provided page (=" + pi.getPage() + ") is out of range.");
+ }
+
+ if (SignaturePlaceholderContext.isSignaturePlaceholderDataSet() &&
+ SignaturePlaceholderContext.getSignaturePlaceholderData().getPlaceholderName() != null)
+ {
+ replacePlaceholder(stamper, pi.getPage(), SignaturePlaceholderContext.getSignaturePlaceholderData().getPlaceholderName());
+ }
+
+ PdfContentByte content = stamper.getOverContent(pi.getPage());
+ // content = StampContent einer PageStamp.
+
+ // System.out.println("table_width = " + pdf_table.getTotalWidth() + ",
+ // table_height = " + pdf_table.getTotalHeight());
+
+ PdfTemplate table_template = content.createTemplate(pdf_table.getTotalWidth(), pdf_table.getTotalHeight());
+ table_template.setCompress(Boolean.FALSE); // do not compress sigblock because we rewrite it afterwards for bin sig
+
+ // exthex
+ StructContentHelper structHelper = new StructContentHelper(stamper, content, pi.getPage());
+ structHelper.prepareStructData(table_template);
+
+ pdf_table.writeSelectedRows(0, -1, 0, pdf_table.getTotalHeight(), table_template);
+
+ // table_template.moveTo(0, 0);
+ // table_template.lineTo(pdf_table.getTotalWidth(),
+ // pdf_table.getTotalHeight());
+ // table_template.stroke();
+ // table_template.moveTo(0, 0);
+ // table_template.lineTo(100, 100);
+ // table_template.stroke();
+
+ // pdf_table.writeSelectedRows(0, -1, SIGNATURE_BORDER / 2,
+ // table_position, content);
+
+
+ structHelper.beginSigBlockContent();
+
+ content.addTemplate(table_template, pi.getX(), pi.getY() - pdf_table.getTotalHeight());
+
+ structHelper.endSigBlockContent();
+
+
+ ActualTablePos atp = new ActualTablePos();
+ atp.page = pi.getPage();
+ atp.x = pi.getX();
+ atp.y = pi.getY(); // TODO is this correct or flipped?
+ atp.width = pdf_table.getTotalWidth();
+ atp.height = pdf_table.getTotalHeight();
+ iui.actualTablePos = atp;
+
+ structHelper.buildFigureStructData(so, table_template);
+ structHelper.buildSigBlockStructData();
+ structHelper.finishMainStructData();
+
+ structHelper.buildVerifyLinkStructData(table_template, atp);
+
+ // For debugging print a 100x100 grid
+ // {
+ // Rectangle psize = reader.getPageSizeWithRotation(pos.page);
+ // float page_width = psize.width();
+ // float page_height = psize.height();
+ // for (float x = 0; x < page_width; x += 100)
+ // {
+ // content.moveTo(x, 0);
+ // content.lineTo(x, page_height);
+ // content.stroke();
+ // }
+ // for (float y = 0; y < page_height; y += 100)
+ // {
+ // content.moveTo(0, y);
+ // content.lineTo(page_width, y);
+ // content.stroke();
+ // }
+ // }
+
+ // content.setLineWidth(10.0f);
+ // content.moveTo(0, 0);
+ // content.lineTo(100, 100);
+ // content.stroke();
+
+ // PdfIndirectReference page_ref =
+ // stamper.getWriter().getPageReference(signature_page);
+ // System.out.println("page_ref = " + page_ref.toString());
+
+ // PdfObject page_obj = PdfReader.getPdfObject(page_ref);
+ // System.out.println("page_obj = " + page_obj);
+
+ // PdfDictionary page_dict = (PdfDictionary) page_obj;
+ // PdfObject resources_obj = page_dict.get(PdfName.RESOURCES);
+ // System.out.println("resources_obj = " + resources_obj);
+ // PdfDictionary resources = (PdfDictionary)
+ // PdfReader.getPdfObject(resources_obj);
+ // for (Iterator it = resources.getKeys().iterator(); it.hasNext();)
+ // {
+ // PdfName key = (PdfName) it.next();
+ // PdfObject value = resources.get(key);
+ // System.out.println(" " + key + " = " + value);
+ // }
+
+ // add the EGIZ dict:
+ if (variable_field_definitions != null)
+ {
+ createEgizDict(stamper, table_template, iui, variable_field_definitions, all_field_definitions, invisible_field_definitions, invisibleKZString);
+ }
+
+ if (adobeSigField) {
+ AdobeSignatureHelper.createAdobeSignatureField(stamper, si, so, atp, structHelper); // here..., stamper is closed
+ } else {
+ stamper.close();
+ }
+ // System.out.println("wprinz: STAMPING FINISHED");
+
+ // just to make sure the stream is really closed
+ baos.close();//
+ //org.apache.commons.io.FileUtils.writeByteArrayToFile(new java.io.File("C:/out.pdf"), ((at.gv.egiz.pdfas.impl.output.ByteArrayDataSink) written_pdf).getByteArray());
+ // iui.signed_pdf = baos.toByteArray();
+
+ structHelper.removeCurrent();
+ return iui;
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ throw new PresentableException(ErrorCode.CANNOT_WRITE_PDF, e);
+ }
+ catch (DocumentException e)
+ {
+ e.printStackTrace();
+ throw new PresentableException(ErrorCode.CANNOT_WRITE_PDF, e);
+ }
+ }
+
+ private static void replacePlaceholder(PdfStamper stamper, int pageNr, String placeholderName) throws BadElementException, MalformedURLException, IOException, BadPdfFormatException, PresentableException {
+ Image img = Image.getInstance(SignaturePlaceholderData.class.getResource("empty.jpg"));
+ PdfImage pImg = new PdfImage(img, "Imwurscht", null);
+ PdfStamperImp stamperImp = (PdfStamperImp)stamper.getWriter();
+ PdfIndirectObject ind = stamperImp.addToBody(pImg);
+
+ PdfDictionary resources = stamper.getReader().getPageN(pageNr).getAsDict(PdfName.RESOURCES);
+ if (ind != null && resources != null)
+ {
+ PdfDictionary xobjDict = resources.getAsDict(PdfName.XOBJECT);
+ if (xobjDict != null)
+ {
+ xobjDict.put(new PdfName(placeholderName), ind.getIndirectReference());
+ stamperImp.markUsed(resources);
+ }
+ else
+ {
+ throw new PresentableException(ErrorCode.CANNOT_WRITE_PDF, new NullPointerException("Image dictionary not found in document structure!"));
+ }
+ }
+ else
+ {
+ throw new PresentableException(ErrorCode.CANNOT_WRITE_PDF, new NullPointerException("Resource dictionary not found in document structure!"));
+ }
+ }
+
+
+ /**
+ * Creates the EGIZ Dictionary and adds it to the document.
+ *
+ * @param stamper
+ * The PdfStamper.
+ * @param table_template
+ * The Template of the Signature block.
+ * @param iui
+ * The IncrementalUpdateInformation.
+ * @param variable_field_definitions
+ * The field definitions.
+ * @throws IOException
+ * @throws SettingNotFoundException
+ * @throws CaptionNotFoundException
+ */
+ protected static void createEgizDict(PdfStamper stamper, PdfTemplate table_template, IncrementalUpdateInformation iui, List variable_field_definitions, List all_field_definitions,
+ List invisible_field_definitions, String invisibleKZString) throws IOException, SettingNotFoundException, CaptionNotFoundException
+ {
+ // iui.temp_ir = table_template.getIndirectReference();
+ iui.temp_ir_number = table_template.getIndirectReference().getNumber();
+ iui.temp_ir_generation = table_template.getIndirectReference().getGeneration();
+
+ byte[] content_stream = table_template.toPdf(null);
+ iui.content_stream_length = content_stream.length;
+
+ iui.replaces = determineReplacesInContentStream(content_stream, 0, content_stream.length, variable_field_definitions);
+ if (invisibleKZString == null)
+ {
+ iui.kz_list = determineKZ(content_stream, 0, content_stream.length, all_field_definitions);
+ }
+ else
+ {
+ StringInfo si = new StringInfo();
+ si.string_start = -1;
+ si.string_length = invisibleKZString.length();
+
+ iui.kz_list = new ArrayList();
+ iui.kz_list.add(si);
+ }
+
+ // PdfIndirectReference previous_egiz_dict_ind_ref =
+ // getEgizDictIndRefFromReader(reader);
+
+ PdfDictionary egiz_dict = new PdfDictionary(EGIZ_DICT_NAME);
+ egiz_dict.put(EGIZ_XOBJ_NAME, table_template.getIndirectReference());
+ egiz_dict.put(EGIZ_ODS_NAME, NUMBER_PLACEHOLDER);
+
+ // /ID
+ PdfArray kz_array = new PdfArray();
+ for (int i = 0; i < iui.kz_list.size(); i++)
+ {
+ kz_array.add(NUMBER_PLACEHOLDER); // start
+ kz_array.add(NUMBER_PLACEHOLDER); // length
+ }
+ egiz_dict.put(EGIZ_KZ_NAME, kz_array);
+
+ // ByteRanges
+ int num_replaces = calcNumReps(iui.replaces);
+ int num_holes = num_replaces + 1 + 1;
+ // +1 = the /encodings hole
+ // +1 = the /Cert
+ // +1 = the /Timestamp
+ if (iui.timeStamper != null) {
+ num_holes += 1;
+ }
+ boolean has_hidden_variable_fields = invisible_field_definitions != null && !invisible_field_definitions.isEmpty();
+ if (has_hidden_variable_fields)
+ {
+ num_holes += invisible_field_definitions.size();
+ }
+ int num_byte_ranges = num_holes + 1;
+
+ PdfArray byte_ranges_array = new PdfArray();
+ for (int i = 0; i < num_byte_ranges; i++)
+ {
+ byte_ranges_array.add(NUMBER_PLACEHOLDER); // start
+ byte_ranges_array.add(NUMBER_PLACEHOLDER); // length
+ }
+ egiz_dict.put(EGIZ_BYTERANGES_NAME, byte_ranges_array);
+
+ PdfArray encodings_array = new PdfArray();
+ encodings_array.add(new PdfName(new String(ENCODING_NIL))); // the
+ // /encodings
+ encodings_array.add(new PdfName(new String(ENCODING_NIL))); // the /Cert
+
+ // array itself
+ PdfArray replaces_array = new PdfArray();
+ replaces_array.add(new PdfName(new String(BREV_NIL, "US-ASCII"))); // the
+ // /encodings
+ replaces_array.add(new PdfName(new String(BREV_NIL, "US-ASCII"))); // the
+ // /Cert
+
+ if (iui.timeStamper != null) {
+ encodings_array.add(new PdfName(new String(ENCODING_NIL))); // the /Timestamp
+ replaces_array.add(new PdfName(new String(BREV_NIL, "US-ASCII"))); // the /timestamp
+
+ }
+
+ // hidden replaces
+ List hidden_replaces = null;
+ if (has_hidden_variable_fields)
+ {
+ hidden_replaces = new ArrayList();
+
+ Iterator it = invisible_field_definitions.iterator();
+ while (it.hasNext())
+ {
+ SignatureFieldDefinition sfd = (SignatureFieldDefinition) it.next();
+ byte[] brev = typeToBrev(sfd.field_name);
+ encodings_array.add(new PdfName(new String(ENCODING_WIN, "US-ASCII")));
+ replaces_array.add(new PdfName(new String(brev, "US-ASCII")));
+
+ ReplaceInfo ri = new ReplaceInfo();
+ ri.brev = brev;
+ ri.enc = ENCODING_WIN;
+ ri.sfd = sfd;
+ ri.replaces = new ArrayList();
+
+ StringInfo si = new StringInfo();
+ si.string_start = -1; // to be determined later on
+ si.string_length = sfd.placeholder_length;
+ ri.replaces.add(si);
+
+ hidden_replaces.add(ri);
+ }
+ }
+
+ // content stream replaces
+ Iterator it = iui.replaces.iterator();
+ while (it.hasNext())
+ {
+ ReplaceInfo ri = (ReplaceInfo) it.next();
+ for (int i = 0; i < ri.replaces.size(); i++)
+ {
+ byte[] brev = typeToBrev(ri.sfd.field_name);
+ encodings_array.add(new PdfName(new String(ENCODING_WIN, "US-ASCII")));
+ replaces_array.add(new PdfName(new String(brev, "US-ASCII")));
+ }
+ }
+ egiz_dict.put(EGIZ_REPLACES_NAME, replaces_array);
+
+ egiz_dict.put(EGIZ_ENCODINGS_NAME, encodings_array);
+
+ PdfArray cert_array = new PdfArray();
+ iui.cert_length = getCertificatePlaceholderLength(iui);
+ byte[] cert_bytes = new byte[iui.cert_length];
+ for (int i = 0; i < cert_bytes.length; i++)
+ {
+ cert_bytes[i] = 0;
+ }
+ PdfString cert_placeholder = new PdfString(cert_bytes);
+ cert_array.add(cert_placeholder);
+ egiz_dict.put(EGIZ_CERTIFICATE_NAME, cert_array);
+
+ // Timestamp
+ if (iui.timeStamper != null) {
+ // only if handler is available
+ PdfArray timestamp_array = new PdfArray();
+ iui.timestamp_length = getTimestampPlaceholderLength(iui);
+ byte[] timestamp_bytes = new byte[iui.timestamp_length];
+ for (int i = 0; i < timestamp_bytes.length; i++)
+ {
+ timestamp_bytes[i] = 0;
+ }
+ PdfString timestamp_placeholder = new PdfString(timestamp_bytes);
+ timestamp_array.add(timestamp_placeholder);
+ egiz_dict.put(EGIZ_TIMESTAMP_NAME, timestamp_array);
+ }
+
+
+ // /Data array with hidden information
+ if (has_hidden_variable_fields || invisibleKZString != null)
+ {
+ PdfArray hidden_fields_array = new PdfArray();
+
+ if (invisibleKZString != null)
+ {
+ PdfString str = new PdfString(invisibleKZString);
+ hidden_fields_array.add(str);
+ }
+
+ if (has_hidden_variable_fields)
+ {
+ iui.replaces.addAll(0, hidden_replaces);
+
+ for (int i = 0; i < invisible_field_definitions.size(); i++)
+ {
+ SignatureFieldDefinition sfd = (SignatureFieldDefinition) invisible_field_definitions.get(i);
+ byte[] placeholder = new byte[sfd.placeholder_length];
+ for (int phIdx = 0; phIdx < placeholder.length; phIdx++)
+ {
+ placeholder[phIdx] = SIGN_PLACEHOLDER;
+ }
+ PdfString str = new PdfString(placeholder);
+ hidden_fields_array.add(str);
+ }
+ }
+
+ egiz_dict.put(EGIZ_DATA_NAME, hidden_fields_array);
+ }
+
+
+ PdfIndirectObject dict_ref = stamper.getWriter().addToBody(egiz_dict);
+ // iui.egiz_dict_ir = dict_ref.getIndirectReference();
+ iui.egiz_dict_ir_number = dict_ref.getIndirectReference().getNumber();
+ iui.egiz_dict_ir_generation = dict_ref.getIndirectReference().getGeneration();
+
+ PdfIndirectReference root_ref = (PdfIndirectReference) stamper.getReader().getTrailer().get(PdfName.ROOT);
+ PdfDictionary root = (PdfDictionary) PdfReader.getPdfObject(root_ref);
+ // root.put(EGIZ_DICT_NAME, dict_ref.getIndirectReference());
+ ((PdfStamperImp) stamper.getWriter()).markUsed(root);
+
+ // PdfDictionary extra_cata = stamper.getWriter().getExtraCatalog();
+ // extra_cata.put(dict_type, dict_ref.getIndirectReference());
+
+ ((PdfStamperImp) stamper.getWriter()).setEgizDictTrailerInfo(EGIZ_DICT_NAME, dict_ref.getIndirectReference());
+ }
+
+ /**
+ * Converts a field name (type) to the corresponding BREV.
+ *
+ * @param type
+ * The field name (type).
+ * @return Returns the corresponding BREV, or BREV_NIL if the type is not
+ * recognized.
+ */
+ protected static byte[] typeToBrev(String type)
+ {
+ if (type.equals(SignatureTypes.SIG_DATE))
+ {
+ return BREV_DAT;
+ }
+ if (type.equals(SignatureTypes.SIG_ISSUER))
+ {
+ return BREV_ISS;
+ }
+ if (type.equals(SignatureTypes.SIG_VALUE))
+ {
+ return BREV_VAL;
+ }
+ if (type.equals(SignatureTypes.SIG_NUMBER))
+ {
+ return BREV_SNR;
+ }
+ if (type.equals(SignatureTypes.SIG_ID))
+ {
+ return BREV_SID;
+ }
+ if (type.equals(SignatureTypes.SIG_ALG))
+ {
+ return BREV_ALG;
+ }
+
+
+ return BREV_NIL;
+ }
+
+ /**
+ * Updates the information in the egiz dictionary to reflect the real offsets
+ * of the byte ranges.
+ *
+ * <p>
+ * This replaces the "dummy numbers" in the egiz dictionary with the correct
+ * values.
+ * </p>
+ *
+ * @param iui
+ * The IncrementalUpdateInformation.
+ * @throws PDFDocumentException
+ */
+ public static void markByteRanges(IncrementalUpdateInformation iui) throws PDFDocumentException
+ {
+ try
+ {
+ iui.byte_ranges = new ArrayList();
+
+ int num_digits = Integer.toString(NUMBER_PLACEHOLDER.intValue()).length();
+ byte[] signed_pdf = iui.signed_pdf;
+
+ String str = iui.egiz_dict_ir_number + " " + iui.egiz_dict_ir_generation + " obj";
+ byte[] obj_bytes = ArrayUtils.add(str.getBytes("US-ASCII"), 0, (byte) 0x0A);
+ int obj_index = ByteArrayUtils.lastIndexOf(signed_pdf, obj_bytes);
+ int obj_start = obj_index + obj_bytes.length;
+
+ String ods_str = "/ODS ";
+ byte[] ods_bytes = ods_str.getBytes("US-ASCII");
+ int ods_index = ByteArrayUtils.indexOf(signed_pdf, obj_start, ods_bytes);
+ int ods_start = ods_index + ods_bytes.length;
+
+ String kz_str = "/ID[";
+ byte[] kz_bytes = kz_str.getBytes("US-ASCII");
+ int kz_index = ByteArrayUtils.indexOf(signed_pdf, obj_start, kz_bytes);
+ int kz_start = kz_index + kz_bytes.length;
+
+ String br_str = "/ByteRange[";
+ byte[] br_bytes = br_str.getBytes("US-ASCII");
+ int br_index = ByteArrayUtils.indexOf(signed_pdf, obj_start, br_bytes);
+ int array_start = br_index + br_bytes.length;
+
+ String enc_str = "/encodings[";
+ byte[] enc_bytes = enc_str.getBytes("US-ASCII");
+ int enc_index = ByteArrayUtils.indexOf(signed_pdf, obj_start, enc_bytes);
+ int enc_start = enc_index + enc_bytes.length;
+
+ String cert_str = "/Cert[(";
+ byte[] cert_bytes = cert_str.getBytes("US-ASCII");
+ int cert_index = ByteArrayUtils.indexOf(signed_pdf, obj_start, cert_bytes);
+ int cert_start = cert_index + cert_bytes.length;
+
+ //Timestamp
+ int timestamp_index = 0;
+ int timestamp_start = 0;
+ if (iui.timeStamper != null) {
+ String timestamp_str = "/TimeStamp[(";
+ byte[] timestamp_bytes = timestamp_str.getBytes("US-ASCII");
+ timestamp_index = ByteArrayUtils.indexOf(signed_pdf, obj_start, timestamp_bytes);
+ timestamp_start = timestamp_index + timestamp_bytes.length;
+ }
+
+ replaceNumber(signed_pdf, ods_start, signed_pdf.length, num_digits);
+
+
+ int cur_pos = array_start;
+ int cur_br_start = 0;
+
+
+ // write the /encodings byte range
+ {
+ int num_replaces = calcNumReps(iui.replaces);
+ int num_holes = num_replaces + 1 + 1;
+ // +1 = the /encodings hole
+ // +1 = the /Cert
+ // +1 = the /Timestamp
+ if (iui.timeStamper != null) {
+ num_holes += 1;
+ }
+
+ int enc_length = (1 + 3) * num_holes;
+
+ StringInfo byte_range = new StringInfo();
+ byte_range.string_start = cur_br_start;
+ byte_range.string_length = enc_start;
+ iui.byte_ranges.add(byte_range);
+
+ replaceNumber(signed_pdf, cur_pos, byte_range.string_start, num_digits);
+ cur_pos += num_digits;
+ cur_pos += 1;
+ replaceNumber(signed_pdf, cur_pos, byte_range.string_length, num_digits);
+ cur_pos += num_digits;
+ cur_pos += 1;
+
+ cur_br_start = enc_start + enc_length;
+
+ iui.enc_start = enc_start;
+ iui.enc_length = enc_length;
+ }
+
+ // write the /Cert byte range
+ {
+ StringInfo byte_range = new StringInfo();
+ byte_range.string_start = cur_br_start;
+ byte_range.string_length = cert_start - cur_br_start;
+ iui.byte_ranges.add(byte_range);
+
+ replaceNumber(signed_pdf, cur_pos, byte_range.string_start, num_digits);
+ cur_pos += num_digits;
+ cur_pos += 1;
+ replaceNumber(signed_pdf, cur_pos, byte_range.string_length, num_digits);
+ cur_pos += num_digits;
+ cur_pos += 1;
+
+ cur_br_start = cert_start + iui.cert_length;
+
+ iui.cert_start = cert_start;
+ }
+
+ // write the /Timestamp byte range
+ if (iui.timeStamper != null) {
+ StringInfo byte_range = new StringInfo();
+ byte_range.string_start = cur_br_start;
+ byte_range.string_length = timestamp_start - cur_br_start;
+ iui.byte_ranges.add(byte_range);
+
+ replaceNumber(signed_pdf, cur_pos, byte_range.string_start, num_digits);
+ cur_pos += num_digits;
+ cur_pos += 1;
+ replaceNumber(signed_pdf, cur_pos, byte_range.string_length, num_digits);
+ cur_pos += num_digits;
+ cur_pos += 1;
+
+ cur_br_start = timestamp_start + iui.timestamp_length;
+
+ iui.timestamp_start = timestamp_start;
+ }
+
+ // determine the /Data byte ranges if any
+ List ifd = iui.invisible_field_definitions;
+ if (!ifd.isEmpty() || iui.invisibleKZString != null)
+ {
+ String data_str = "/Data[(";
+ byte[] data_bytes = data_str.getBytes("US-ASCII");
+ int data_index = ByteArrayUtils.indexOf(signed_pdf, obj_start, data_bytes);
+ int data_start = data_index + data_bytes.length;
+
+ int hole_start = data_start;
+
+ if (iui.invisibleKZString != null)
+ {
+ StringInfo si = (StringInfo) iui.kz_list.get(0);
+ si.string_start = hole_start;
+
+ hole_start += si.string_length + 2;
+ }
+
+ for (int i = 0; i < ifd.size(); i++)
+ {
+ ReplaceInfo ri = (ReplaceInfo) iui.replaces.get(i);
+ StringInfo si = (StringInfo) ri.replaces.get(0);
+ si.string_start = hole_start;
+
+ hole_start += si.string_length + 2;
+ }
+
+ }
+
+ Iterator rit = iui.replaces.iterator();
+ while (rit.hasNext())
+ {
+ ReplaceInfo ri = (ReplaceInfo) rit.next();
+
+ // byte [] value_bytes = ri.value.getBytes("ISO-8859-1");
+ // int write_pos = 0;
+
+ Iterator sit = ri.replaces.iterator();
+ while (sit.hasNext())
+ {
+ StringInfo si = (StringInfo) sit.next();
+
+ StringInfo byte_range = new StringInfo();
+ byte_range.string_start = cur_br_start;
+ byte_range.string_length = si.string_start - cur_br_start;
+ iui.byte_ranges.add(byte_range);
+
+ replaceNumber(signed_pdf, cur_pos, byte_range.string_start, num_digits);
+ cur_pos += num_digits;
+ cur_pos += 1;
+ replaceNumber(signed_pdf, cur_pos, byte_range.string_length, num_digits);
+ cur_pos += num_digits;
+ cur_pos += 1;
+
+ cur_br_start = si.string_start + si.string_length;
+ }
+
+ }
+
+ StringInfo byte_range = new StringInfo();
+ byte_range.string_start = cur_br_start;
+ byte_range.string_length = signed_pdf.length - cur_br_start;
+ iui.byte_ranges.add(byte_range);
+
+ replaceNumber(signed_pdf, cur_pos, byte_range.string_start, num_digits);
+ cur_pos += num_digits;
+ cur_pos += 1;
+ replaceNumber(signed_pdf, cur_pos, byte_range.string_length, num_digits);
+ cur_pos += num_digits;
+ cur_pos += 1;
+
+
+ // update the Kennzeichnung byte ranges
+ cur_pos = kz_start;
+ for (int i = 0; i < iui.kz_list.size(); i++)
+ {
+ StringInfo si = (StringInfo) iui.kz_list.get(i);
+
+ replaceNumber(signed_pdf, cur_pos, si.string_start, num_digits);
+ cur_pos += num_digits;
+ cur_pos += 1;
+ replaceNumber(signed_pdf, cur_pos, si.string_length, num_digits);
+ cur_pos += num_digits;
+ cur_pos += 1;
+ }
+
+ }
+ catch (IOException e)
+ {
+ throw new PDFDocumentException(201, e);
+ }
+
+ }
+
+ /**
+ * Replaces the certificate placeholder with the certificate from the signed
+ * Signature Object.
+ *
+ * @param iui
+ * The IncrementalUpdateInformation.
+ * @throws PDFDocumentException
+ */
+ public static void replaceCertificate(IncrementalUpdateInformation iui) throws PDFDocumentException
+ {
+ X509Certificate certificate = iui.signed_signature_object.getX509Certificate();
+ try
+ {
+ byte[] der = certificate.getEncoded();
+ byte[] encoded = CodingHelper.encodeBase64(der).getBytes("US-ASCII");
+ byte[] escaped = Placeholder.escapePDFString(encoded);
+ if (escaped.length > iui.cert_length)
+ {
+ throw new PlaceholderException("certificate", escaped.length - iui.cert_length);
+ }
+ System.arraycopy(escaped, 0, iui.signed_pdf, iui.cert_start, escaped.length);
+ }
+ catch (CertificateEncodingException e)
+ {
+ throw new PDFDocumentException(300, e);
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ throw new PDFDocumentException(300, e);
+ }
+
+ // X509Cert cert = iui.signed_signature_object.getX509Cert();
+ // // X509Certificate certificate = cert.getX509Certificate();
+ // try
+ // {
+ // byte[] encoded = cert.getCertString().getBytes("US-ASCII"); //
+ // certificate.getEncoded();
+ // byte[] escaped = Placeholder.escapePDFString(encoded);
+ // if (escaped.length > iui.cert_length)
+ // {
+ // throw new PlaceholderException("certificate", escaped.length -
+ // iui.cert_length);
+ // }
+ // System.arraycopy(escaped, 0, iui.signed_pdf, iui.cert_start,
+ // escaped.length);
+ // }
+ // // catch (CertificateEncodingException e)
+ // // {
+ // // throw new PDFDocumentException(300, e);
+ // // }
+ // catch (UnsupportedEncodingException e)
+ // {
+ // throw new PDFDocumentException(300, e);
+ // }
+ }
+
+ /**
+ * Replaces the timestam placeholder with the timestamp from the signed
+ * Signature Object.
+ *
+ * @param iui
+ * The IncrementalUpdateInformation.
+ * @throws PDFDocumentException
+ */
+ public static void replaceTimestamp(IncrementalUpdateInformation iui) throws PDFDocumentException
+ {
+ String timestamp = iui.signed_signature_object.getSigTimeStamp();
+ if (timestamp != null) {
+ byte[] escaped = Placeholder.escapePDFString(timestamp.getBytes());
+ if (escaped.length > iui.timestamp_length)
+ {
+ throw new PlaceholderException("timestamp", escaped.length - iui.timestamp_length);
+ }
+ System.arraycopy(escaped, 0, iui.signed_pdf, iui.timestamp_start, escaped.length);
+ }
+ }
+
+ /**
+ * Replaces the placeholders with values from the signed SignatureObject.
+ *
+ * @param iui
+ * The IncrementalUpdateInformation.
+ * @throws PDFDocumentException
+ */
+ public static void replacePlaceholders(IncrementalUpdateInformation iui) throws PDFDocumentException
+ {
+ final int lineBreakTolerance = getLineBreakTolerance(iui);
+
+ final byte[] signed_pdf = iui.signed_pdf;
+
+ // int num_replaces = calcNumReps(iui.replaces);
+ // int num_holes = num_replaces + 1 + 1; // +1 = the /encodings hole; +1 =
+ // the
+ // /Cert
+
+ int encoding_entry_index = 0;
+ {// /encodings itself
+ int enc_offset = iui.enc_start + encoding_entry_index * 4;
+ signed_pdf[enc_offset] = '/';
+ System.arraycopy(ENCODING_NIL, 0, signed_pdf, enc_offset + 1, ENCODING_NIL.length);
+ encoding_entry_index++;
+ }
+ {// /Cert itself
+ int enc_offset = iui.enc_start + encoding_entry_index * 4;
+ signed_pdf[enc_offset] = '/';
+ System.arraycopy(ENCODING_NIL, 0, signed_pdf, enc_offset + 1, ENCODING_NIL.length);
+ encoding_entry_index++;
+ }
+ if (iui.signed_signature_object.getSigTimeStamp() != null)
+ {// /Timestamp itself
+ int enc_offset = iui.enc_start + encoding_entry_index * 4;
+ signed_pdf[enc_offset] = '/';
+ System.arraycopy(ENCODING_NIL, 0, signed_pdf, enc_offset + 1, ENCODING_NIL.length);
+ encoding_entry_index++;
+ }
+
+ for (int i = 0; i < iui.replaces.size(); i++)
+ {
+ ReplaceInfo ri = (ReplaceInfo) iui.replaces.get(i);
+
+ try
+ {
+ String value = ri.value;
+
+ if (value == null)
+ {
+ value = "";
+ }
+
+ byte[] encoding = ENCODING_WIN;
+ byte[] replace_bytes = Placeholder.applyWinAnsiEncoding(value);
+
+ String restored_value = Placeholder.unapplyWinAnsiEncoding(replace_bytes);
+ if (!value.equals(restored_value))
+ {
+ // debug:
+ logger.warn("WinAnsiEncoding doesn't fit - using URL instead!");
+ // /debug!
+
+ replace_bytes = Placeholder.applyURLEncoding(value);
+
+ encoding = ENCODING_URL;
+ }
+
+ for (int string_index = 0; string_index < ri.replaces.size(); string_index++)
+ {
+ int enc_offset = iui.enc_start + encoding_entry_index * 4;
+ signed_pdf[enc_offset] = '/';
+ System.arraycopy(encoding, 0, signed_pdf, enc_offset + 1, encoding.length);
+ encoding_entry_index++;
+ }
+
+ Placeholder.replacePlaceholderWithTolerance(signed_pdf, ri.replaces, replace_bytes, lineBreakTolerance);
+ }
+ catch (PlaceholderException e)
+ {
+ throw new PlaceholderException(ri.sfd.field_name, e.getMissing());
+ }
+
+ }
+ }
+
+ /**
+ * Calculates the number of actual String replaces from a given ReplaceInfo
+ * list.
+ * <p>
+ * This is used to determine the number of actual replaces that has to be
+ * carried out. Accordingly to this number, entries in the dictionary are
+ * created.
+ * </p>
+ *
+ * @param replaces
+ * The ReplaceInfo list.
+ * @return Returns the number of string replaces.
+ */
+ protected static int calcNumReps(List replaces)
+ {
+ int number = 0;
+ Iterator it = replaces.iterator();
+ while (it.hasNext())
+ {
+ ReplaceInfo ri = (ReplaceInfo) it.next();
+ number += ri.replaces.size();
+ }
+ return number;
+ }
+
+ /**
+ * Determines the List of ReplaceInfo objects of replaces in the content
+ * stream regarding the given field definitions.
+ *
+ * <p>
+ * This method collects all variable String fields in a content stream and
+ * orders them according to their start offset.
+ * </p>
+ *
+ * @param pdf
+ * The PDF.
+ * @param begin
+ * The start of the content stream.
+ * @param end
+ * The end of the content stream.
+ * @param field_definitions
+ * The field definitions that are counceled to find out which and
+ * where varaible strings are.
+ * @return Returns the list of ReplaceInfo objects specifying the variable
+ * areas.
+ * @throws CaptionNotFoundException
+ */
+ protected static List determineReplacesInContentStream(final byte[] pdf, int begin, int end, List field_definitions) throws CaptionNotFoundException
+ {
+ List replaces = new ArrayList();
+ try
+ {
+
+ List strings = Placeholder.parseStrings(pdf, begin, end);
+
+ for (int index = 0; index < field_definitions.size(); index++)
+ {
+ SignatureFieldDefinition sfd = (SignatureFieldDefinition) field_definitions.get(index);
+
+ if (sfd.placeholder_length > 0)
+ {
+ ReplaceInfo ri = new ReplaceInfo();
+ ri.sfd = sfd;
+ ri.replaces = new ArrayList();
+
+ byte[] caption = sfd.caption.getBytes("ISO-8859-1");
+
+ int caption_index = findIndex(strings, caption);
+ if (caption_index < 0)
+ {
+ throw new CaptionNotFoundException(sfd.caption);
+ }
+ int start_index = skipStrings(strings, caption_index, caption);
+ int next_index = findFirstNotPlaceholder(strings, start_index);
+
+ for (int i = start_index; i < next_index; i++)
+ {
+ StringInfo si = (StringInfo) strings.get(i);
+ ri.replaces.add(si);
+ }
+
+ replaces.add(ri);
+ }
+ }
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ logger.error(e.getMessage(), e);
+ }
+
+ // sort replaces
+ Collections.sort(replaces, new Comparator() {
+ public int compare(Object arg0, Object arg1)
+ {
+ ReplaceInfo ri0 = (ReplaceInfo) arg0;
+ ReplaceInfo ri1 = (ReplaceInfo) arg1;
+ int start0 = ((StringInfo) ri0.replaces.get(0)).string_start;
+ int start1 = ((StringInfo) ri1.replaces.get(0)).string_start;
+ return start0 - start1;
+ }
+ });
+
+ return replaces;
+ }
+
+ /**
+ * Determines the Kennzeichnug in the content stream.
+ *
+ * @param pdf
+ * The PDF.
+ * @param begin
+ * The start of the content stream.
+ * @param end
+ * The end of the content stream.
+ * @param field_definitions
+ * The field definitions.
+ * @return Returns the List of StringInfo objects representing the KZ field.
+ * @throws SettingNotFoundException
+ * F.e.
+ */
+ protected static List determineKZ(final byte[] pdf, int begin, int end, List field_definitions) throws SettingNotFoundException
+ {
+ try
+ {
+ List strings = Placeholder.parseStrings(pdf, begin, end);
+
+ for (int index = 0; index < field_definitions.size(); index++)
+ {
+ SignatureFieldDefinition sfd = (SignatureFieldDefinition) field_definitions.get(index);
+
+ if (sfd.field_name.equals(SignatureTypes.SIG_KZ))
+ {
+ List kz_list = new ArrayList();
+
+ byte[] caption = sfd.caption.getBytes("ISO-8859-1");
+
+ int caption_index = findIndex(strings, caption);
+ int start_index = skipStrings(strings, caption_index, caption);
+
+ int end_index = -1;
+ for (end_index = start_index; end_index < strings.size(); end_index++)
+ {
+ StringInfo si = (StringInfo) strings.get(end_index);
+
+ if (startsWithCaption(si, field_definitions))
+ {
+ break;
+ }
+
+ kz_list.add(si);
+ }
+
+ return kz_list;
+ }
+ }
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ logger.error(e.getMessage(), e);
+ }
+ throw new KZSettingNotFoundException("Field " + SignatureTypes.SIG_KZ + " not found.");
+ }
+
+ /**
+ * Finds the index of the StringInfo within the StringInfo list that has the
+ * given content (caption).
+ *
+ * @param strings
+ * The list of StringInfos.
+ * @param caption
+ * The text to be matched to the strings.
+ * @return Returns the index of the found string, or -1 if no string matched.
+ */
+ protected static int findIndex(List strings, byte[] caption)
+ {
+ for (int i = 0; i < strings.size(); i++)
+ {
+ if (isCaption(strings, i, caption))
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ protected static boolean isCaption(List strings, int index, byte[] caption)
+ {
+ try
+ {
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ for (int i = index; i < strings.size(); i++)
+ {
+ StringInfo si = (StringInfo) strings.get(i);
+ baos.write(si.copyStringBytes());
+ }
+ byte[] str_data = baos.toByteArray();
+ byte[] unescaped = Placeholder.unescapePDFString(str_data);
+ if (ByteArrayUtils.compareByteArrays(unescaped, 0, caption))
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ catch (IOException e)
+ {
+ logger.error(e.getMessage(), e);
+ return false;
+ }
+
+ }
+
+ protected static int skipStrings(List strings, int index, byte[] caption)
+ {
+ int length = 0;
+ for (int i = index; i < strings.size(); i++)
+ {
+ StringInfo si = (StringInfo) strings.get(i);
+ length += si.string_length;
+
+ if (length >= caption.length)
+ {
+ return i + 1;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Tells, if the given StringInfo contains only placeholder characters.
+ *
+ * @param si
+ * The StringInfo.
+ * @param placeholder
+ * The placeholder character.
+ * @return Returns true, if the string contains only the given placeholder
+ * characters, false otherwise.
+ */
+ protected static boolean isPlaceholder(StringInfo si, byte placeholder)
+ {
+ byte[] string_bytes = si.copyStringBytes();
+ for (int i = 0; i < string_bytes.length; i++)
+ {
+ if (string_bytes[i] != placeholder)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ protected static boolean startsWithCaption(StringInfo si, List field_definitions)
+ {
+ try
+ {
+ for (int i = 0; i < field_definitions.size(); i++)
+ {
+ SignatureFieldDefinition sfd = (SignatureFieldDefinition) field_definitions.get(i);
+
+ String caption = sfd.caption;
+ String str = si.getString("ISO-8859-1");
+
+ if (caption.startsWith(str))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ logger.error(e.getMessage(), e);
+ return false;
+ }
+ }
+
+ /**
+ * Finds the first string after and at the given index not being a placeholder
+ * string.
+ *
+ * @param strings
+ * The list of StringInfos.
+ * @param start
+ * The index where to start the search.
+ * @return Returns the index of the first not placeholder string, or
+ * strings.size() if no more non placeholder strings could be found.
+ */
+ protected static int findFirstNotPlaceholder(List strings, int start)
+ {
+ for (int i = start; i < strings.size(); i++)
+ {
+ StringInfo si = (StringInfo) strings.get(i);
+ if (!isPlaceholder(si, LAYOUT_PLACEHOLDER))
+ {
+ return i;
+ }
+ }
+ return strings.size();
+ }
+
+ /**
+ * Restores the given String to its placeholder.
+ *
+ * @param pdf
+ * The PDF.
+ * @param si
+ * The string.
+ * @param placeholder
+ * The placeholder the string should be filled with.
+ */
+ public static void restorePlaceholder(final byte[] pdf, StringInfo si, final byte placeholder)
+ {
+ byte[] ph = new byte[si.string_length];
+ for (int i = 0; i < ph.length; i++)
+ {
+ ph[i] = placeholder;
+ }
+ System.arraycopy(ph, 0, pdf, si.string_start, ph.length);
+ }
+
+ /**
+ * Reconstructs the replaces from the PDF and forms suitable value strings.
+ *
+ * @param pdf
+ * The PDF.
+ * @param brevs
+ * The brevs.
+ * @param sis
+ * The StringInfo objects of the strings.
+ * @return Returns the List of ReplaceInfo objects containing the restored
+ * values.
+ * @throws PDFDocumentException
+ */
+ public static List reconstructReplaces(final byte[] pdf, byte[][] brevs, StringInfo[] sis, byte[][] encodings) throws PDFDocumentException
+ {
+ try
+ {
+ List replaces = new ArrayList();
+
+ ReplaceInfo cur_ri = null;
+
+ for (int cur = 0; cur < brevs.length; cur++)
+ {
+ if (ByteArrayUtils.compareByteArrays(brevs[cur], 0, BREV_NIL))
+ {
+ continue;
+ }
+
+ if (cur_ri == null || !ByteArrayUtils.compareByteArrays(cur_ri.brev, 0, brevs[cur]))
+ {
+ if (cur >= encodings.length) {
+ throw new PDFDocumentException(ErrorCode.INVALID_SIGNATURE_DICTIONARY, "Invalid EGIZ signature dictionary.");
+ }
+ cur_ri = new ReplaceInfo();
+
+ cur_ri.replaces = new ArrayList();
+
+ cur_ri.brev = brevs[cur];
+ cur_ri.enc = encodings[cur];
+
+ replaces.add(cur_ri);
+ }
+
+ cur_ri.replaces.add(sis[cur]);
+ }
+
+ // restore value Strings
+ Iterator rit = replaces.iterator();
+ while (rit.hasNext())
+ {
+ ReplaceInfo ri = (ReplaceInfo) rit.next();
+ ri.value = Placeholder.reconstructStringFromPartition(pdf, ri.replaces, ri.enc);
+
+ // System.out.println(new String(ri.brev, "US-ASCII") + ": " +
+ // ri.value);
+ }
+
+ return replaces;
+ }
+ catch (IOException e)
+ {
+ throw new PDFDocumentException(310, e);
+ }
+
+ }
+
+ /**
+ * Reads an unsigned integer number.
+ *
+ * @param pdf
+ * The PDF.
+ * @param start_index
+ * The start index of the number.
+ * @param num_digits
+ * The number of digits.
+ * @return Returns the read number.
+ */
+ public static int readNumber(final byte[] pdf, final int start_index, final int num_digits)
+ {
+ try
+ {
+ byte[] n_bytes = new byte[num_digits];
+ System.arraycopy(pdf, start_index, n_bytes, 0, num_digits);
+ String n_string = new String(n_bytes, "US-ASCII");
+
+ int n = Integer.parseInt(n_string);
+ return n;
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ logger.error(e.getMessage(), e);
+ return -1;
+ }
+ }
+
+ /**
+ * Replaces a number by the new value.
+ *
+ * @param pdf
+ * The PDF.
+ * @param start_index
+ * The start index of the number.
+ * @param number
+ * The new number.
+ * @param num_digits
+ * The number of digits.
+ */
+ public static void replaceNumber(final byte[] pdf, final int start_index, final int number, final int num_digits)
+ {
+ try
+ {
+ if (number < 0)
+ {
+ throw new IllegalArgumentException("The given number " + number + " must not be negative.");
+ }
+ String number_string = Integer.toString(number);
+ if (number_string.length() > num_digits)
+ {
+ throw new IllegalArgumentException("The given number " + number + " has more than " + num_digits + " digits.");
+ }
+
+ int leading_zeros = num_digits - number_string.length();
+ String zeros_string = "";
+ for (int i = 0; i < leading_zeros; i++)
+ {
+ zeros_string += "0";
+ }
+
+ String total_string = zeros_string + number_string;
+ byte[] total_bytes = total_string.getBytes("US-ASCII");
+ System.arraycopy(total_bytes, 0, pdf, start_index, num_digits);
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ logger.error(e.getMessage(), e);
+ }
+ }
+
+
+ // TODO old code - remove
+ // /**
+ // * For debugging purposes.
+ // *
+ // * @param args
+ // * @throws IOException
+ // */
+ // public static void main(String[] args) throws IOException
+ // {
+ // File signed_doc = new File("C:/wprinz/temp.pdf");
+ //
+ // PdfReader reader = new PdfReader(new FileInputStream(signed_doc));
+ // PdfDictionary egiz_dict = getEgizDictFromReader(reader);
+ // if (egiz_dict == null)
+ // {
+ // System.out.println("NO Egiz Dict");
+ // return;
+ // }
+ //
+ // String sig_text = extractSignatureTextOnly(egiz_dict);
+ // System.out.println("Sig Text:");
+ // System.out.println(sig_text);
+ //
+ // int ods = getOriginalDocumentSizeFromEgizDict(egiz_dict);
+ // System.out.println("Original Document Size = " + ods);
+ // }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/BinarySignatureHolder.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/BinarySignatureHolder.java
new file mode 100644
index 0000000..7dc49ef
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/BinarySignatureHolder.java
@@ -0,0 +1,185 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: BinarySignatureHolder.java,v 1.1 2006/10/11 07:58:28 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.pdf;
+
+import java.io.Serializable;
+
+import at.gv.egiz.pdfas.impl.input.ByteArrayPdfDataSourceImpl;
+import at.gv.egiz.pdfas.framework.input.DataSource;
+import at.gv.egiz.pdfas.framework.input.PdfDataSource;
+
+import at.knowcenter.wag.egov.egiz.sig.SignatureObject;
+
+/**
+ * Data structure that holds the information of one binary signature block,
+ * which is the signed/signable pdf and the corresponding SignatureObject.
+ *
+ * <p>
+ * The actual signed text is computed by Base64 encoding the binary data when
+ * first requested.
+ * </p>
+ * <p>
+ * The corresponding getters can be used to retrieve the signed document (e.g.
+ * for displaying a preview).
+ * </p>
+ *
+ * @author wprinz
+ */
+public class BinarySignatureHolder implements Serializable, SignatureHolder
+{
+
+ /**
+ * SVUID.
+ */
+ private static final long serialVersionUID = -7208103904479272760L;
+
+// /**
+// * The whole pdf this holder was extracted from.
+// */
+// private byte[] signed_pdf = null;
+
+ private PdfDataSource pdfDataSource = null;
+
+// /**
+// * The number of bytes that give the signed document.
+// */
+// private int signed_pdf_length = -1;
+
+// /**
+// * The signed text of this object.
+// *
+// * <p>
+// * This is the value that will be signed by the Connector.
+// * </p>
+// */
+// private String signed_text = null;
+
+ /**
+ * The signature object.
+ */
+ private SignatureObject signature_object = null;
+
+// /**
+// * Constructor that takes the pdf and the SignatureObject as parameters.
+// *
+// * @param pdf
+// * The pdf data.
+// * @param length
+// * The length (number of bytes) of the pdf data to be used for being
+// * converted into "signed text".
+// * @param so
+// * The signed signature object.
+// */
+// public BinarySignatureHolder(final byte[] pdf, final int length, SignatureObject so)
+// {
+//// this.signed_pdf = pdf;
+// this.pdfDataSource = new ByteArrayPdfDataSourceImpl(pdf);
+// // streaming byte array
+// this.signed_pdf_length = length;
+// this.signature_object = so;
+//
+//// this.signed_text = null;
+// }
+
+ public BinarySignatureHolder(PdfDataSource pdf, SignatureObject so)
+ {
+ this.pdfDataSource = pdf;
+ this.signature_object = so;
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.pdf.SignatureHolder#getSignedText()
+ */
+ public String getSignedText()
+ {
+ throw new RuntimeException("BinarySignatureHolder must not return text.");
+// if (this.signed_text == null)
+// {
+// computeSignedText();
+// }
+// return this.signed_text;
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.pdf.SignatureHolder#getSignatureObject()
+ */
+ public SignatureObject getSignatureObject()
+ {
+ return this.signature_object;
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.pdf.SignatureHolder#getDataSource()
+ */
+ public DataSource getDataSource()
+ {
+ return getSignedPdf();
+ }
+
+
+
+ // TODO obsolete funtction - remove;
+// /**
+// * Computes or recomputes the signed text from the underlying binary data.
+// *
+// * <p>
+// * This usually encodes the binary data of given length in Base64.
+// * </p>
+// *
+// * <p>
+// * This is usually called automatically when the signed text is first
+// * requested.
+// * </p>
+// */
+// protected void computeSignedText()
+// {
+// this.signed_text = BinarySignature.retrieveSignableTextFromData(this.signed_pdf, this.signed_pdf_length);
+// }
+
+// /**
+// * Returns the signed_pdf.
+// * @return Returns the signed_pdf.
+// */
+// public byte[] getSignedPdf()
+// {
+// return this.signed_pdf;
+// }
+
+ public PdfDataSource getSignedPdf ()
+ {
+ return this.pdfDataSource;
+ }
+
+// /**
+// * Returns the signed_pdf_length.
+// * @return Returns the signed_pdf_length.
+// */
+// public int getSignedPdfLength()
+// {
+// return this.signed_pdf_length;
+// }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/EGIZDate.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/EGIZDate.java
new file mode 100644
index 0000000..d2b29b6
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/EGIZDate.java
@@ -0,0 +1,284 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: EGIZDate.java,v 1.1 2006/10/31 08:08:33 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.pdf;
+
+import java.text.ParseException;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+
+import org.apache.commons.lang.time.DateUtils;
+import org.apache.log4j.Logger;
+
+/**
+ * Represents a signature date and the signing time as can be found in the
+ * SIG_DATE field.
+ *
+ * <p>
+ * This is used to compare date values of signatures.
+ * </p>
+ *
+ * @author wprinz
+ */
+public class EGIZDate {
+
+ private static final Logger LOG = Logger.getLogger(EGIZDate.class);
+
+ protected Date date = null;
+
+ // TODO remove deprecated old code
+// /**
+// * The year.
+// */
+// protected int year;
+//
+// /**
+// * The month.
+// */
+// protected int month;
+//
+// /**
+// * The day.
+// */
+// protected int day;
+//
+// /**
+// * The hour.
+// */
+// protected int hour;
+//
+// /**
+// * The minute.
+// */
+// protected int minute;
+//
+// /**
+// * The second.
+// */
+// protected int second;
+//
+// /**
+// * Constructor that fills the date with values.
+// *
+// * @param year
+// * The year.
+// * @param month
+// * The month.
+// * @param day
+// * The day.
+// * @param hour
+// * The hour.
+// * @param minute
+// * The minute.
+// * @param second
+// * The second.
+// */
+// public EGIZDate(int year, int month, int day, int hour, int minute,
+// int second) {
+// this.year = year;
+// this.month = month;
+// this.day = day;
+// this.hour = hour;
+// this.minute = minute;
+// this.second = second;
+// }
+
+
+ /**
+ * @param date
+ */
+ protected EGIZDate(Date date)
+ {
+ this.date = date;
+ }
+
+ /**
+ * Parses the date information from a given date value.
+ *
+ * <p>
+ * Usually the date value is one extracted from the value of the SIG_DATE
+ * field.
+ * </p>
+ *
+ * @param date_value
+ * The date value String.
+ * @return Returns the parsed EGIZDate. An IllegalArgumentException is
+ * thrown if the date String has an illegal format.
+ */
+ public static EGIZDate parseFromString(String date_value) {
+ Date date = parseDateFromString(date_value);
+// Calendar calendar = new GregorianCalendar();
+// calendar.setTime(date);
+
+ LOG.debug("Parsing date string \"" + date_value + "\" returns: " + date);
+
+// return new EGIZDate(calendar.get(Calendar.YEAR), calendar
+// .get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH),
+// calendar.get(Calendar.HOUR), calendar.get(Calendar.MINUTE),
+// calendar.get(Calendar.SECOND));
+ return new EGIZDate(date);
+
+ }
+
+ public static Date parseDateFromString (String date_value)
+ {
+ // find the according RFC standard and cite it
+
+ /*
+ * Pattern date_pattern =
+ * Pattern.compile("^\\d\\d\\d\\d-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\d(Z|((\\+|\\-)\\d\\d:\\d\\d))?$");
+ * Matcher date_matcher = date_pattern.matcher(date_value); if
+ * (!date_matcher.matches()) { throw new IllegalArgumentException("The
+ * date_value (" + date_value + ") has an illegal format."); } // for
+ * some strange reasons capture groups don't work
+ *
+ * int year = Integer.parseInt(date_value.substring(0, 4)); int month =
+ * Integer.parseInt(date_value.substring(5, 7)); int day =
+ * Integer.parseInt(date_value.substring(8, 10)); int hour =
+ * Integer.parseInt(date_value.substring(11, 13)); int minute =
+ * Integer.parseInt(date_value.substring(14, 16)); int second =
+ * Integer.parseInt(date_value.substring(17, 19)); return new
+ * EGIZDate(year, month, day, hour, minute, second);
+ */
+
+ String[] parsePatterns = { "yyyy-MM-dd'T'HH:mm:ss",
+ "yyyy-MM-dd'T'HH:mm:ssZ", "yyyy-MM-dd'T'HH:mm:ssZZ" };
+ if (date_value.length() > 19) {
+ int li = date_value.lastIndexOf(":");
+ if (li >= 19) {
+ date_value = new StringBuffer(date_value).deleteCharAt(li).toString();
+ }
+ // FIXME: @iaik: wenn man bei UTC+"Z" die letzten -2 Zeichen durch "UTC" ersetzt verliert die Zeit ihre Sekunden-Einerstelle!!!!!!!
+ // alter code:
+// if (date_value.endsWith("Z")) {
+// date_value = date_value.substring(0, date_value.length()-2) + "UTC";
+// }
+ // neuer code:
+ if (date_value.endsWith("ZZ")) {
+ date_value = date_value.substring(0, date_value.length()-2) + "UTC";
+ }
+ if (date_value.endsWith("Z")) {
+ date_value = date_value.substring(0, date_value.length()-1) + "UTC";
+ }
+
+ } else {
+ date_value += "UTC";
+ }
+
+ Date date;
+ try {
+ date = DateUtils.parseDate(date_value, parsePatterns);
+ } catch (ParseException e) {
+ throw new IllegalArgumentException("The date_value (" + date_value
+ + ") has an illegal format.");
+ }
+
+
+// return new EGIZDate(calendar.get(Calendar.YEAR), calendar
+// .get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH),
+// calendar.get(Calendar.HOUR), calendar.get(Calendar.MINUTE),
+// calendar.get(Calendar.SECOND));
+
+ // fixed by tknall: really bad bug: Calendar.HOUR means hour in 12-hour-mode instead f 24-hour. !!!!
+ // this leads to false comparison of two dates where one date is prior noon and one after noon.
+// return new EGIZDate(calendar.get(Calendar.YEAR), calendar
+// .get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH),
+// calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE),
+// calendar.get(Calendar.SECOND));
+ return date;
+
+ }
+
+ /**
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object obj) {
+ if (!(obj instanceof EGIZDate)) {
+ return false;
+ }
+
+ EGIZDate other = (EGIZDate)obj;
+ return this.date.equals(other.date);
+ }
+
+ /**
+ * @see java.lang.Object#hashCode()
+ */
+ public int hashCode() {
+ return this.date.hashCode();
+ }
+
+ /**
+ * @see java.lang.Object#toString()
+ */
+ public String toString()
+ {
+ return this.date.toString();
+ }
+
+
+// /**
+// * Converts the date to a long integer.
+// *
+// * <p>
+// * An earlier date is lower than a later date.
+// * </p>
+// * <p>
+// * E.g. a date in 1999 will get a smaller number than a date in 2006.
+// * </p>
+// *
+// * @return Returns the compareable long.
+// */
+// protected long toCompareableLong() {
+// return +this.year * 12 * 31 * 24 * 60 * 60 + this.month * 31 * 24 * 60
+// * 60 + this.day * 24 * 60 * 60 + this.hour * 60 * 60
+// + this.minute * 60 + this.second;
+// }
+
+ /**
+ * Compares this EGIZDate to another EXIZDate.
+ *
+ * @param other
+ * The other EGIZDate.
+ * @return Returns negative if this date is earlier (lower) than the other
+ * date. Returns 0 if both dates are equal. Returns positive if this
+ * date is later (higher) than the other date.
+ */
+ public int compareTo(EGIZDate other) {
+ return this.date.compareTo(other.date);
+// long diff = toCompareableLong() - other.toCompareableLong();
+// return (int) diff;
+ }
+
+ /**
+ * @return the date
+ */
+ public Date getDate()
+ {
+ return this.date;
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/IncrementalUpdateInformation.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/IncrementalUpdateInformation.java
new file mode 100644
index 0000000..3714684
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/IncrementalUpdateInformation.java
@@ -0,0 +1,252 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: IncrementalUpdateInformation.java,v 1.2 2006/10/31 08:09:33 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.pdf;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import at.gv.egiz.pdfas.api.analyze.NonTextObjectInfo;
+import at.gv.egiz.pdfas.api.timestamp.TimeStamper;
+import at.gv.egiz.pdfas.framework.input.PdfDataSource;
+import at.gv.egiz.pdfas.utils.PdfAUtil;
+import at.knowcenter.wag.egov.egiz.sig.SignatureData;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject;
+
+import com.lowagie.text.pdf.PdfReader;
+
+/**
+ * This parameter object contains all useful inforamtion the binary incremental
+ * update methods need to create and replace a binary singature block.
+ *
+ * <p>
+ * This class is basically used to transport information about the document from
+ * the prepareSign to the finishSign of the Signator. In future, this could be
+ * extended and encapsulated to task proprietary IUI instances. E.g. a
+ * BinarySignatorIUI, a TextualSignatorIUI, both implementing the core IUI
+ * interface, but encapsulating Binary or Textual specialities.
+ * </p>
+ *
+ * @author wprinz
+ */
+public class IncrementalUpdateInformation implements Serializable
+{
+ public static final Logger log = Logger.getLogger(IncrementalUpdateInformation.class);
+
+ /**
+ * SVUID.
+ */
+ private static final long serialVersionUID = -5904526956127108035L;
+
+ /**
+ * The original PDF document.
+ */
+ //public byte[] original_document = null;
+ public PdfDataSource original_document = null;
+
+ /**
+ * The Singature type to be created.
+ */
+ public String signature_type = null;
+
+ /**
+ * The signed pdf document.
+ *
+ * <p>
+ * This is the original document plus the incremental update block.
+ * </p>
+ */
+ public byte[] signed_pdf = null;
+ // this is only valid during prepare
+
+ // holds the variable iui data for bin sigs.
+ public byte [] sign_iui_block = null;
+
+ /**
+ * The start index of this incremental update block.
+ */
+ int start_index = -1;
+
+ /**
+ * The indirect reference of the egiz dict.
+ */
+ // PdfIndirectReference egiz_dict_ir = null;
+ public int egiz_dict_ir_number;
+
+ public int egiz_dict_ir_generation;
+
+ /**
+ * The List of ReplaceInfo objects specifying the byte ranges where the
+ * variable data has to be fille in.
+ */
+ public List replaces = null;
+
+ /**
+ * The List of StringInfo objects specifying the byte ranges that should
+ * be/were signed.
+ */
+ public List byte_ranges = null;
+
+ /**
+ * The indirect reference of the signature x-object.
+ */
+ // public PdfIndirectReference temp_ir;
+ public int temp_ir_number;
+
+ public int temp_ir_generation;
+
+ /**
+ * The start index of the content stream of the signature x-object.
+ */
+ public int content_stream_start = -1;
+
+ /**
+ * The length of the content stream of the signature x-object.
+ */
+ public int content_stream_length = -1;
+
+// /**
+// * The document text for signing.
+// */
+// public String document_text;
+ /**
+ * The data to be signed or verified.
+ *
+ * <p>
+ * For text signature this is the document text.
+ * For binary signature this is the PDF document.
+ * </p>
+ */
+ public SignatureData signature_data = null;
+
+ /**
+ * The SignatureObject containing the variable values after the document text
+ * has been signed.
+ * <p>
+ * These values have to be filled in.
+ * </p>
+ */
+ public SignSignatureObject signed_signature_object;
+
+ /**
+ * The start of the /encodings array.
+ */
+ public int enc_start = -1;
+
+ /**
+ * The length of the /encodings array.
+ */
+ public int enc_length = -1;
+
+ /**
+ * The start of the first /Cert
+ */
+ public int cert_start = -1;
+
+ /**
+ * The length of the /cert placeholder.
+ */
+ public int cert_length = -1;
+
+ /**
+ * The length of the /TimeStamp placeholder.
+ */
+ public int timestamp_length = -1;
+
+ /**
+ * The start of the first /Timestamp
+ */
+ public int timestamp_start = -1;
+
+ /**
+ * The list of strings of the KZ.
+ */
+ public List kz_list;
+
+ /**
+ * The table position.
+ */
+ public TablePos pos;
+
+ /**
+ * For signing: the profile.
+ */
+ public String signProfile;
+
+ /**
+ * The actual position where the table was written.
+ */
+ public ActualTablePos actualTablePos;
+
+ /**
+ * The field definitions of invisible fields, which data should be stored in /Data.
+ */
+ public List invisible_field_definitions;
+
+ /**
+ * The invisible KZ String, if KZ is invisible.
+ */
+ public String invisibleKZString = null;
+
+ /**
+ * List {@link NonTextObjectInfo} of non text objects if available (text signature only).
+ *
+ */
+ public List nonTextObjectInfos;
+
+
+ /**
+ * The timestamper if any
+ */
+ public TimeStamper timeStamper;
+
+ // dferbas
+
+ public String getPdfVersion() {
+ byte[] pdf_data = this.original_document.getAsByteArray();
+ PdfReader reader;
+ String pdfVersion = null;
+ try {
+ reader = new PdfReader(pdf_data);
+ // is.close();
+
+ byte[] metaData = reader.getMetadata();
+ if (metaData != null) {
+ pdfVersion = PdfAUtil.findPdfAVersion(new String(metaData));
+ }
+ if (pdfVersion == null) {
+ pdfVersion = "PDF 1." + reader.getPdfVersion();
+ }
+
+ reader.close();
+ } catch (IOException e) {
+ log.error(e.getMessage(), e);
+ }
+ return pdfVersion;
+ }
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/NoSignatureHolder.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/NoSignatureHolder.java
new file mode 100644
index 0000000..97a6111
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/NoSignatureHolder.java
@@ -0,0 +1,84 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.pdf;
+
+import java.io.Serializable;
+
+import at.gv.egiz.pdfas.framework.input.DataSource;
+import at.knowcenter.wag.egov.egiz.sig.SignatureObject;
+
+public class NoSignatureHolder implements Serializable, SignatureHolder {
+
+ private static final long serialVersionUID = 1L;
+
+ // # sigs before modification
+ private int position;
+
+ public NoSignatureHolder(int pos) {
+ this.position = pos;
+ }
+
+ public DataSource getDataSource() {
+ return null;
+ }
+
+ public SignatureObject getSignatureObject() {
+ return null;
+ }
+
+ public int getPosition() {
+ return this.position;
+ }
+
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + this.position;
+ return result;
+ }
+
+ public boolean equals(Object obj) {
+
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj == null) {
+ return false;
+ }
+
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+
+ final NoSignatureHolder other = (NoSignatureHolder) obj;
+
+ if (this.position != other.position) {
+ return false;
+ }
+
+ return true;
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/ObjectExtractor.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/ObjectExtractor.java
new file mode 100644
index 0000000..eb7377a
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/ObjectExtractor.java
@@ -0,0 +1,233 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.pdf;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDPage;
+import org.apache.pdfbox.pdmodel.PDResources;
+import org.apache.pdfbox.pdmodel.graphics.xobject.PDXObjectImage;
+import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation;
+
+import at.gv.egiz.pdfas.api.analyze.NonTextObjectInfo;
+import at.gv.egiz.pdfas.framework.input.PdfDataSource;
+
+/**
+ * Method for object extraction from pdf documents.
+ * This uses pdf-box 0.8.0, not 0.7.2. Packages org.apache.pdfbox instead org.pdfbox!
+ * @author dferbas
+ *
+ */
+public class ObjectExtractor {
+ private static Logger log = Logger.getLogger(ObjectExtractor.class);
+
+ /*
+ * If set <code>true</code> signature annotations are not extracted otherwise
+ * all signatures except PDF-AS signatures are extracted.
+ */
+ private final static boolean SKIP_NON_PDFAS_SIGNATURES = false;
+
+ /**
+ * Find annotation objects in pdf documents
+ * @param objectInfos
+ * @param pageNr
+ * @param page
+ */
+ private static void doExtractAnnotations(List objectInfos, int pageNr, PDPage page) {
+ List annotations;
+ try {
+ annotations = page.getAnnotations();
+ } catch (IOException e) {
+ log.error("Error extracting annotations from pdf. No NonTextObjectInfo-annotations available.", e);
+ return;
+ }
+ for (Iterator it = annotations.iterator(); it.hasNext();) {
+ try {
+ PDAnnotation anno = (PDAnnotation) it.next();
+ log.debug("found annotation: " +anno);
+ if (log.isTraceEnabled()) {
+ log.trace("annotation def: " + dictToString(anno.getDictionary()));
+ }
+ String ft = anno.getDictionary().getNameAsString("FT");
+ if (ft != null && ft.equals("Sig")) { // skip signature widgets
+ if (SKIP_NON_PDFAS_SIGNATURES) {
+ log.debug("found signature widged, skip extraction");
+ continue;
+ } else {
+ COSDictionary sigDict = (COSDictionary) anno.getDictionary().getDictionaryObject("V");
+ if (sigDict != null && AdobeSignatureHelper.ADOBE_SIG_FILTER.equals(sigDict.getNameAsString("Filter"))) {
+ log.debug("found PDF-AS signature widged, skip extraction");
+ continue;
+ }
+ }
+ }
+
+ NonTextObjectInfo objInfo = new NonTextObjectInfo();
+ objInfo.setName(anno.getDictionary().getString( "NM" ));
+ objInfo.setObjectType(NonTextObjectInfo.TYPE_ANNOTATION);
+
+ String subtype = anno.getDictionary().getNameAsString("Subtype");
+ String subj = anno.getDictionary().getString("Subj");
+ if (subj != null) {
+ subtype+= "/" + subj;
+ }
+ objInfo.setSubType(subtype);
+
+ objInfo.setPageNr(pageNr);
+ objInfo.setHeight(anno.getRectangle().getHeight());
+ objInfo.setWidth(anno.getRectangle().getWidth());
+ objectInfos.add(objInfo);
+ } catch (Exception ex) {
+ log.info("error reading non text object info key " + ex);
+ }
+ }
+ }
+
+ /**
+ * Create string representation from COSDictionary
+ * @param dict
+ * @return
+ */
+ public static String dictToString(COSDictionary dict)
+ {
+ try {
+ String retVal = "COSDictionary{";
+ for (int i = 0; i<dict.size(); i++)
+ {
+ COSName key = (COSName)dict.keyList().get(i);
+ retVal = retVal + "(" + key + ":" + dict.getItem(key) + ") ";
+ }
+ retVal = retVal + "}";
+ return retVal;
+ } catch (Exception e) {
+ return "no detail available";
+ }
+ }
+
+ /**
+ * Find resources (images) in pdf documents
+ * @param objectInfos
+ * @param pageNr
+ * @param page
+ */
+ private static void doExtractFromResources(List objectInfos, int pageNr, PDPage page) {
+ PDResources resources = page.getResources();
+
+ Map images;
+ try {
+ images = resources.getImages();
+ } catch (IOException e) {
+ log.error("Error extracting images from pdf. No NonTextObjectInfo-Images available.", e);
+ return;
+ }
+ if (images != null) {
+ Iterator imageIter = images.keySet().iterator();
+ while (imageIter.hasNext()) {
+ NonTextObjectInfo objInfo = new NonTextObjectInfo();
+ String key = (String) imageIter.next();
+ PDXObjectImage image = (PDXObjectImage) images.get(key);
+
+ objInfo.setHeight(image.getHeight());
+ objInfo.setWidth(image.getWidth());
+ objInfo.setName(key + image.getSuffix());
+ objInfo.setObjectType(NonTextObjectInfo.TYPE_IMAGE);
+ objInfo.setPageNr(pageNr);
+ objectInfos.add(objInfo);
+ objInfo.setSubType(image.getSuffix());
+
+ if (log.isDebugEnabled()) {
+ log.debug("Found non text object: " + objInfo.toString());
+ }
+ }
+ }
+ }
+
+ /**
+ * Extract non textual data from pdf.
+ *
+ * @see org.pdfbox.ExtractImages
+ *
+ * @param document
+ * @return List of {@link NonTextObjectInfo}
+ */
+ public static List extractNonTextInfo(PDDocument document) {
+ // extraction does not work with the normalized pdf from extractTextTextual
+ log.debug("going to extract non text objects");
+ List objectInfos = new ArrayList();
+ List pages = document.getDocumentCatalog().getAllPages();
+ Iterator iter = pages.iterator();
+ int pageNr = 0;
+ while (iter.hasNext()) {
+ pageNr++;
+ PDPage page = (PDPage) iter.next();
+ doExtractFromResources(objectInfos, pageNr, page);
+ doExtractAnnotations(objectInfos, pageNr, page); // does not work with pdf-box 0.7.2 -> 0.8.0 needed
+ }
+ if (log.isDebugEnabled()) {
+ log.debug("extracted non textual objects count: " + objectInfos.size());
+ }
+ return objectInfos;
+
+ }
+
+ /**
+ * Extract non textual data from pdf.
+ * @param pdfDataSource
+ *
+ * @see org.pdfbox.ExtractImages
+ *
+ * @return List of {@link NonTextObjectInfo}
+ */
+ public static List extractNonTextInfo(PdfDataSource pdfDataSource) {
+
+ PDDocument doc = null;
+ try {
+ doc = PDDocument.load(pdfDataSource.createInputStream());
+ List res = extractNonTextInfo(doc);
+ doc.close();
+ return res;
+ } catch (IOException e) {
+ log.error("Error extracting images from pdf. No NonTextObjectInfo available.", e);
+ return new ArrayList();
+ } finally {
+ if (doc != null) {
+ try {
+ doc.close();
+ } catch (IOException e) {
+ log.error("error closing pddocument", e);
+ }
+ }
+ }
+
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFPage.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFPage.java
new file mode 100644
index 0000000..a0311da
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFPage.java
@@ -0,0 +1,377 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: PDFPage.java,v 1.5 2006/10/31 08:09:33 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.pdf;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+import org.pdfbox.cos.COSName;
+import org.pdfbox.cos.COSStream;
+import org.pdfbox.pdmodel.PDPage;
+import org.pdfbox.pdmodel.PDResources;
+import org.pdfbox.pdmodel.common.PDStream;
+import org.pdfbox.pdmodel.graphics.xobject.PDXObject;
+import org.pdfbox.pdmodel.graphics.xobject.PDXObjectForm;
+import org.pdfbox.util.Matrix;
+import org.pdfbox.util.PDFOperator;
+import org.pdfbox.util.PDFTextStripper;
+import org.pdfbox.util.TextPosition;
+import org.pdfbox.util.operator.OperatorProcessor;
+
+import at.knowcenter.wag.egov.egiz.cfg.ConfigLogger;
+
+/**
+ * PDFPage is an inner class that is used to calculate the page length of a PDF
+ * Document page. It extends the PDFTextStripper class and implement one
+ * interested method: {@link PDFPage#showCharacter(TextPosition)}<br>
+ * This method is called when processing the FileStream. By calling the method
+ * {@link org.pdfbox.util.PDFStreamEngine#processStream(org.pdfbox.pdmodel.PDPage, org.pdfbox.pdmodel.PDResources, org.pdfbox.cos.COSStream)}
+ * the implemented method showCharacter is called.
+ *
+ * @author wlackner
+ * @see PDFTextStripper
+ */
+public class PDFPage extends PDFTextStripper
+{
+ /**
+ * The logger definition.
+ */
+ private static final Logger logger_ = ConfigLogger.getLogger(PDFPage.class);
+
+ /**
+ * The maximum (lowest) y position of a character.
+ */
+ protected float max_character_ypos = Float.NEGATIVE_INFINITY;
+
+ /**
+ * The maximum (lowest y position of an image.
+ */
+ protected float max_image_ypos = Float.NEGATIVE_INFINITY;
+
+ /**
+ * The y coordinate of the footer line. PDF elements below this footer line will not be regarded.
+ */
+ protected float footer_line = 0.0f;
+
+ /**
+ * Constructor.
+ *
+ * @param footer_line The y coordinate of the footer line. PDF elements below this footer line will not be regarded.
+ *
+ * @throws IOException
+ */
+ public PDFPage(float footer_line) throws IOException
+ {
+ super();
+
+ this.footer_line = footer_line;
+
+ OperatorProcessor newInvoke = new MyInvoke();
+ newInvoke.setContext(this);
+ operators.put("Do", newInvoke);
+ }
+
+
+ protected void processOperator(PDFOperator operator, List arguments) throws IOException
+ {
+ //logger_.debug("operator = " + operator);
+
+ super.processOperator(operator, arguments);
+ }
+
+ // exthex
+ /**
+ * A method provided as an event interface to allow a subclass to perform some
+ * specific functionality when a character needs to be displayed. This method
+ * is used to calculate the latest position of a text in the page. Sorry for
+ * this missinterpretation of the method, but it is the only way to do this
+ * (provided by PDFBox)!!!
+ *
+ * @param text
+ * the character to be displayed -> calculate there y position.
+ */
+ protected void showCharacter(TextPosition text)
+ {
+ float current_y = text.getY();
+ final String character = text.getCharacter();
+
+ int pageRotation = page.findRotation();
+ //logger_.debug("PageRotation = " + pageRotation);
+ if (pageRotation == 0)
+ {
+ current_y = text.getY();
+ }
+ if (pageRotation == 90)
+ {
+ current_y = text.getX();
+ }
+ if (pageRotation == 180)
+ {
+ float page_height = page.findMediaBox().getHeight();
+ current_y = page_height - text.getY();
+ }
+ if (pageRotation == 270)
+ {
+ float page_height = page.findMediaBox().getHeight();
+ current_y = page_height - text.getX();
+ }
+
+
+ if (current_y > this.footer_line)
+ {
+ //logger_.debug("character is below footer_line. footer_line = " + this.footer_line + ", text.character=" + character + ", y=" + current_y);
+ return;
+ }
+
+ // store ypos of the char if it is not empty
+ if (!character.equals(" ") && current_y > this.max_character_ypos)
+ {
+ this.max_character_ypos = current_y;
+ //logger_.debug("text.character=" + character + ", y=" + current_y);
+ // System.err.println(character + "|" + current_y);
+ }
+
+ //logger_.error("text.character=" + character + ", y=" + current_y + " max_c=" + this.max_character_ypos);
+ // System.err.println(character + "|" + current_y);
+ }
+
+ // use this funtion getting an unsorted text output
+ // public void showString(byte[] string) {
+ // logger_.debug(new String(string));
+ // }
+
+ /**
+ * Returns the calculated page length.
+ *
+ * @return the max page length value
+ */
+ public float getMaxPageLength()
+ {
+ float max_ypos = Float.NEGATIVE_INFINITY;
+
+ if (this.max_character_ypos > this.max_image_ypos)
+ {
+ max_ypos = this.max_character_ypos;
+ }
+ else
+ {
+ max_ypos = this.max_image_ypos;
+ }
+ //logger_.error("max len=" + max_ypos);
+ return max_ypos;
+ }
+
+ public class MyInvoke extends OperatorProcessor
+ {
+
+ public void process(PDFOperator operator, List arguments) throws IOException
+ {
+ COSName name = (COSName) arguments.get(0);
+ //logger_.error("<Do name=\"" + name.getName() + "\">");
+
+ // PDResources res = context.getResources();
+
+ Map xobjects = context.getXObjects();
+ PDXObject xobject = (PDXObject) xobjects.get(name.getName());
+
+ PDStream stream = xobject.getPDStream();
+ COSStream cos_stream = stream.getStream();
+
+ COSName subtype = (COSName) cos_stream.getDictionaryObject(COSName.SUBTYPE);
+ //logger_.error("<Do subtype name=\"" + subtype.getName() + "\">");
+ if (subtype.equals(COSName.IMAGE))
+ {
+ //logger_.error("XObject Image");
+
+ Matrix ctm = context.getGraphicsState().getCurrentTransformationMatrix();
+ //logger_.debug("ctm = " + ctm);
+
+ Pos [] coordinates = new Pos [] {
+ new Pos(0, 0, 1),
+ new Pos(1, 0, 1),
+ new Pos(0, 1, 1),
+ new Pos(1, 1, 1) };
+
+ Pos [] transformed_coordinates = transtormCoordinates(coordinates, ctm);
+
+ /**********************************************************
+ * pdf-as fix:
+ * calculating min and max point of an image to look where
+ * the signature should be placed
+ * fix solves problems with footer and images and
+ * placement of the signature in an image only pdf document
+ **********************************************************/
+
+ float actual_lowest_point = Float.NaN;
+ float actual_starting_point = Float.NaN;
+
+ int pageRotation = page.findRotation();
+ logger_.debug("PageRotation = " + pageRotation);
+ if (pageRotation == 0)
+ {
+ float min_y = findMinY(transformed_coordinates);
+ logger_.debug("min_y = " + min_y);
+ float page_height = page.findMediaBox().getHeight();
+ logger_.debug("page_height = " + page_height);
+
+ actual_lowest_point = page_height - min_y;
+ actual_starting_point = page_height - findMaxY(transformed_coordinates);
+ }
+ if (pageRotation == 90)
+ {
+ float max_x = findMaxX(transformed_coordinates);
+ logger_.debug("max_x = " + max_x);
+ float page_width = page.findMediaBox().getWidth();
+ logger_.debug("page_width = " + page_width);
+
+ actual_lowest_point = max_x;
+ actual_starting_point = findMinX(transformed_coordinates);
+ }
+ if (pageRotation == 180)
+ {
+ float min_y = findMinY(transformed_coordinates);
+ logger_.debug("min_y = " + min_y);
+ float page_height = page.findMediaBox().getHeight();
+ actual_lowest_point = page_height - findMaxY(transformed_coordinates);
+ actual_starting_point = page_height - min_y;
+ }
+ if (pageRotation == 270)
+ {
+ float min_x = findMinX(transformed_coordinates);
+ logger_.debug("min_x = " + min_x);
+
+ float page_width = page.findMediaBox().getWidth();
+ logger_.debug("page_width = " + page_width);
+
+ actual_lowest_point = page_width - min_x;
+ actual_starting_point = page_width - findMaxX(transformed_coordinates);
+ }
+
+
+ logger_.debug("actual_lowest_point = " + actual_lowest_point);
+
+ if (actual_lowest_point > PDFPage.this.footer_line && actual_starting_point > PDFPage.this.footer_line)
+ {
+ logger_.debug("image is below footer_line. footer_line = " + PDFPage.this.footer_line);
+ return;
+ }
+
+ if (actual_lowest_point > PDFPage.this.max_image_ypos)
+ {
+ PDFPage.this.max_image_ypos = actual_lowest_point;
+ }
+
+ return;
+ }
+
+ if (xobject instanceof PDXObjectForm)
+ {
+ PDXObjectForm form = (PDXObjectForm) xobject;
+ COSStream invoke = (COSStream) form.getCOSObject();
+ PDResources pdResources = form.getResources();
+ PDPage page = context.getCurrentPage();
+ if (pdResources == null)
+ {
+ pdResources = page.findResources();
+ }
+
+ getContext().processSubStream(page, pdResources, invoke);
+ }
+ }
+ }
+
+ public static Pos [] transtormCoordinates (Pos [] coordinates, Matrix m)
+ {
+ Pos [] transformed = new Pos [coordinates.length];
+ for (int i = 0; i < coordinates.length; i++)
+ {
+ transformed[i] = transtormCoordinate(coordinates[i], m);
+ }
+ return transformed;
+ }
+
+ public static Pos transtormCoordinate (Pos pos, Matrix m)
+ {
+ Pos transformed = new Pos();
+ transformed.x = pos.x * m.getValue(0, 0) + pos.y * m.getValue(1, 0) + pos.z * m.getValue(2, 0);
+ transformed.y = pos.x * m.getValue(0, 1) + pos.y * m.getValue(1, 1) + pos.z * m.getValue(2, 1);
+ transformed.z = pos.x * m.getValue(0, 2) + pos.y * m.getValue(1, 2) + pos.z * m.getValue(2, 2);
+
+ logger_.debug(" transformed " + pos + " --> " + transformed);
+ return transformed;
+ }
+
+ public static float findMinY (Pos [] coordinates)
+ {
+ float min = Float.POSITIVE_INFINITY;
+ for (int i = 0; i < coordinates.length; i++)
+ {
+ if (coordinates[i].y < min)
+ {
+ min = coordinates[i].y;
+ }
+ }
+ return min;
+ }
+
+ public static float findMaxY(Pos[] coordinates) {
+ float max = 0;
+ for (int i = 0; i < coordinates.length; i++) {
+ if (coordinates[i].y > max) {
+ max = coordinates[i].y;
+ }
+ }
+ return max;
+ }
+
+ public static float findMaxX (Pos [] coordinates)
+ {
+ float max = Float.NEGATIVE_INFINITY;
+ for (int i = 0; i < coordinates.length; i++)
+ {
+ if (coordinates[i].x > max)
+ {
+ max = coordinates[i].x;
+ }
+ }
+ return max;
+ }
+ public static float findMinX (Pos [] coordinates)
+ {
+ float min = Float.POSITIVE_INFINITY;
+ for (int i = 0; i < coordinates.length; i++)
+ {
+ if (coordinates[i].x < min)
+ {
+ min = coordinates[i].x;
+ }
+ }
+ return min;
+ }
+
+} \ No newline at end of file
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFSignatureCreation.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFSignatureCreation.java
new file mode 100644
index 0000000..d6e6966
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFSignatureCreation.java
@@ -0,0 +1,176 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: PDFSignatureCreation.java,v 1.6 2006/10/31 08:09:33 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.pdf;
+
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+
+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.SettingsException;
+import at.knowcenter.wag.egov.egiz.sig.SignatureObject;
+
+/**
+ * This class provides wrapper methods to get an access to abstract PDF documents (PDFSignator).
+ * There exists many open source libraries and commercial libraries that can implement the abstract
+ * interface. <br>
+ * This class is to load the corresponding implementation of an abstract PDFSignator class. Therefor
+ * it seams to be a factory. The factory settings are read from the configuration file calling the
+ * SettingsReader.
+ *
+ * @author wlackner
+ * @see at.knowcenter.wag.egov.egiz.cfg.SettingsReader
+ */
+public class PDFSignatureCreation {
+ /**
+ * The abstract signature object
+ */
+ private SignatureObject sigObject_ = null;
+ /**
+ * The abstract pdf siganture object
+ */
+ private PDFSignatureObject pdfSigObject_ = null;
+ /**
+ * The SettingsReader instance
+ */
+ private SettingsReader settings_ = null;
+ /**
+ * The factory class prefix
+ */
+ private final static String CLASS_PREFIX = ".PDFSignatureObject";
+ /**
+ * The factory class prefix of the default library
+ */
+ protected final static String DEFAULT_LIBRARY = "IText";
+ /**
+ * The settings key defined in the settings file
+ *
+ * @see SettingsReader
+ */
+ protected final static String SETTINGS_KEY = "pdf.signature.library";
+ /**
+ * The logger definition.
+ */
+ private static final Logger logger_ = ConfigLogger.getLogger(PDFSignatureCreation.class);
+
+ /**
+ * Load the configuration settings. Load the corresponding class implementation for the abstract
+ * PDFSignature class. Init with a signature object.
+ *
+ * @param sigObject the native signature object
+ * @throws PDFDocumentException ErrorCode:101
+ */
+ public PDFSignatureCreation(SignatureObject sigObject) throws PDFDocumentException {
+// try {
+ loadSettings();
+// } catch (PDFDocumentException e) {
+// e.setErrorCode(101);
+// throw e;
+// }
+ sigObject_ = sigObject;
+ }
+
+ /**
+ * Load the factory implementation. This method trys to load the configured PDF library.
+ *
+ * @throws PDFDocumentException
+ */
+ private PDFSignatureObject createPDFSignatureObject() throws PDFDocumentException {
+ PDFSignatureObject pdf_sig_object = null;
+ String class_name = this.getClass().getPackage().getName() + getClassName();
+ Class pdf_sig_obj_class = null;
+ try {
+ pdf_sig_obj_class = Class.forName(class_name);
+ } catch (ClassNotFoundException e) {
+ if (logger_.isEnabledFor(Level.FATAL)) {
+ logger_.fatal("Class not found:" + class_name);
+ }
+ throw new PDFDocumentException(203, "Can not load pdf signator library", e);
+ }
+ try {
+ pdf_sig_object = (PDFSignatureObject) pdf_sig_obj_class.newInstance();
+ } catch (InstantiationException e) {
+ if (logger_.isEnabledFor(Level.FATAL)) {
+ logger_.fatal("Can not instantiate:" + class_name);
+ }
+ throw new PDFDocumentException(203, "Can not load pdf signator library", e);
+ } catch (IllegalAccessException e) {
+ if (logger_.isEnabledFor(Level.FATAL)) {
+ logger_.fatal("Can not access:" + class_name);
+ }
+ throw new PDFDocumentException(203, "Can not load pdf signator library", e);
+ }
+ return pdf_sig_object;
+ }
+
+ /**
+ * load the class settings
+ *
+ * @throws PDFDocumentException
+ * @see SettingsReader
+ */
+ private void loadSettings() throws PDFDocumentException {
+ if (settings_ == null) {
+ try {
+ settings_ = SettingsReader.getInstance();
+ } catch (SettingsException e) {
+ String log_message = "Can not load pdf signature settings. Cause:\n" + e.getMessage();
+ logger_.error(log_message);
+ throw new PDFDocumentException(101, log_message, e);
+ }
+ }
+ }
+
+ /**
+ * Read the class postfix from the configuration file
+ *
+ * @return the full qualified class name
+ */
+ private String getClassName() {
+ String extract_class = settings_.getSetting(SETTINGS_KEY, DEFAULT_LIBRARY);
+ return CLASS_PREFIX + extract_class;
+ }
+
+ /**
+ * Creates a new pdf signature object using the configured pdf library.
+ *
+ * @return a new pdf signature object
+ * @throws PDFDocumentException ErrorCode:203
+ */
+ public PDFSignatureObject getPDFSignatureObject() throws PDFDocumentException {
+ if (pdfSigObject_ == null) {
+// try {
+ pdfSigObject_ = createPDFSignatureObject();
+// } catch (PDFDocumentException e) {
+// e.setErrorCode(203);
+// throw e;
+// }
+ pdfSigObject_.setSignatorObject(sigObject_);
+ }
+ return pdfSigObject_;
+ }
+} \ No newline at end of file
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFSignatureObject.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFSignatureObject.java
new file mode 100644
index 0000000..bd5b6a3
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFSignatureObject.java
@@ -0,0 +1,56 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: PDFSignatureObject.java,v 1.3 2006/10/31 08:09:33 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.pdf;
+
+import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException;
+import at.knowcenter.wag.egov.egiz.sig.SignatureObject;
+
+/**
+ * Defines an interface to get access to PDF documents. There exists many open source libraries and
+ * commercial libraries.
+ *
+ * @author wlackner
+ */
+public interface PDFSignatureObject {
+ public void setSignatorObject(SignatureObject signatorObject);
+
+ /**
+ * Converts the current abstract signature object in a pdf signature object implementation
+ *
+ * @return the converted pdf signature object
+ * @throws PDFDocumentException
+ */
+ public Object getSignatureObject() throws PDFDocumentException;
+
+ /**
+ * Converts a abstract signature object in a pdf signature object implementation
+ *
+ * @param signatorObject the abstract signatorObject to convert
+ * @return the converted pdf signature object
+ * @throws PDFDocumentException
+ */
+ public Object getSignatureObject(SignatureObject signatorObject) throws PDFDocumentException;
+} \ No newline at end of file
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFSignatureObjectIText.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFSignatureObjectIText.java
new file mode 100644
index 0000000..1145619
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFSignatureObjectIText.java
@@ -0,0 +1,618 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: PDFSignatureObjectIText.java,v 1.5 2006/10/31 08:09:33 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.pdf;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+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.SettingsException;
+import at.knowcenter.wag.egov.egiz.sig.SignatureObject;
+import at.knowcenter.wag.egov.egiz.table.Entry;
+import at.knowcenter.wag.egov.egiz.table.Style;
+import at.knowcenter.wag.egov.egiz.table.Table;
+
+import com.lowagie.text.BadElementException;
+import com.lowagie.text.DocumentException;
+import com.lowagie.text.Element;
+import com.lowagie.text.Font;
+import com.lowagie.text.Image;
+import com.lowagie.text.Phrase;
+import com.lowagie.text.pdf.BaseFont;
+import com.lowagie.text.pdf.PdfPCell;
+import com.lowagie.text.pdf.PdfPTable;
+import com.lowagie.text.pdf.SubsetLocal;
+
+/**
+ * This class is the IText implementation of the PDFSignatureObject interface.
+ * The class takes an abstract definition of a signature object and convert them
+ * into a pdf table that is used to sign a pdf document.
+ *
+ * @author wlackner
+ * @see at.knowcenter.wag.egov.egiz.sig.SignatureObject
+ * @see at.knowcenter.wag.egov.egiz.table.Table
+ * @see at.knowcenter.wag.egov.egiz.table.Entry
+ * @see at.knowcenter.wag.egov.egiz.table.Style
+ * @see com.lowagie.text.pdf.PdfPTable
+ * @see at.knowcenter.wag.egov.egiz.cfg.SettingsReader
+ */
+public class PDFSignatureObjectIText implements PDFSignatureObject
+{
+
+// 03.11.2010 changed by exthex to allow setting separate hAlign and vAlign for value and non-value cells.
+// If no value for valuevalign or valuehalign is set the values from valign and halign are taken.
+// Also fixed a minor bug which prevented proper style inheritment (Bug Nr. #534).
+// 04.11.2010 changed by exthex - allow setting separate hAlign and vAlign for image cells analog to value cells.
+
+ private static final String SIG_PDFA1_B_VALID = "SIG_PDFA1B_VALID";
+
+/**
+ * The default font definition
+ */
+ private static Font DEFAULT_FONT = new Font(Font.HELVETICA, 8, Font.NORMAL);
+
+ /**
+ * The abstract signature object
+ */
+ private SignatureObject sigObject_ = null;
+
+ /**
+ * The IText pdf table object
+ */
+ private PdfPTable pdfSigObject_ = null;
+
+ /**
+ * The SettingsReader instance
+ */
+ private SettingsReader settings_ = null;
+
+ /**
+ * The logger definition.
+ */
+ private static final Logger logger_ = ConfigLogger.getLogger(PDFSignatureObjectIText.class);
+
+ /**
+ * Map the style align definitions to IText's align statements
+ */
+ private static HashMap alignMap_ = new HashMap();
+
+ /**
+ * Map the font definitions to IText's font statements
+ */
+ private static HashMap fontMap_ = new HashMap();
+
+ /**
+ * The empty constructor. It loads the ui definitions from signature tables
+ * and init the align map.
+ *
+ * @throws PDFDocumentException
+ */
+ public PDFSignatureObjectIText() throws PDFDocumentException
+ {
+ loadSettings();
+ initStyleMaps();
+ }
+
+ /**
+ * load the class settings
+ *
+ * @throws PDFDocumentException
+ * @see SettingsReader
+ */
+ private void loadSettings() throws PDFDocumentException
+ {
+ if (settings_ == null)
+ {
+ try
+ {
+ settings_ = SettingsReader.getInstance();
+ }
+ catch (SettingsException e)
+ {
+ String log_message = "Can not load pdf signature settings. Cause:\n" + e.getMessage();
+ logger_.error(log_message);
+ throw new PDFDocumentException(101, log_message, e);
+ }
+ }
+ }
+
+ /**
+ * This method initialize the style maps. It maps the style style definitions
+ * to IText styles.
+ */
+ private void initStyleMaps()
+ {
+ alignMap_.put(Style.TOP, new Integer(Element.ALIGN_TOP));
+ alignMap_.put(Style.MIDDLE, new Integer(Element.ALIGN_MIDDLE));
+ alignMap_.put(Style.BOTTOM, new Integer(Element.ALIGN_BOTTOM));
+ alignMap_.put(Style.LEFT, new Integer(Element.ALIGN_LEFT));
+ alignMap_.put(Style.CENTER, new Integer(Element.ALIGN_CENTER));
+ alignMap_.put(Style.RIGHT, new Integer(Element.ALIGN_RIGHT));
+
+ fontMap_.put(Style.HELVETICA, new Integer(Font.HELVETICA));
+ fontMap_.put(Style.TIMES_ROMAN, new Integer(Font.TIMES_ROMAN));
+ fontMap_.put(Style.COURIER, new Integer(Font.COURIER));
+ fontMap_.put(Style.NORMAL, new Integer(Font.NORMAL));
+ fontMap_.put(Style.BOLD, new Integer(Font.BOLD));
+ fontMap_.put(Style.ITALIC, new Integer(Font.ITALIC));
+ fontMap_.put(Style.BOLDITALIC, new Integer(Font.BOLDITALIC));
+ fontMap_.put(Style.UNDERLINE, new Integer(Font.UNDERLINE));
+ fontMap_.put(Style.STRIKETHRU, new Integer(Font.STRIKETHRU));
+ }
+
+ /**
+ * Set the abstract signature definition.
+ *
+ * @param signatorObject
+ * the abstract signator object
+ * @see at.knowcenter.wag.egov.egiz.pdf.PDFSignatureObject#setSignatorObject(at.knowcenter.wag.egov.egiz.sig.SignatureObject)
+ */
+ public void setSignatorObject(SignatureObject signatorObject)
+ {
+ sigObject_ = signatorObject;
+ }
+
+ /**
+ * This method maps the table cell definitions to the pdfCell element.
+ *
+ * @param pdfCell
+ * the pdf cell to be styled
+ * @param cellStyle
+ * the abstract style definition
+ * @param type
+ * type of the cell to render - the appropriate style will be set
+ * @see com.lowagie.text.pdf.PdfPCell
+ * @see at.knowcenter.wag.egov.egiz.table.Style
+ */
+ private void setCellStyle(PdfPCell pdfCell, Style cellStyle, int type)
+ {
+ if (cellStyle != null)
+ {
+ if (cellStyle.getBgColor() != null)
+ {
+ pdfCell.setBackgroundColor(cellStyle.getBgColor());
+ }
+ pdfCell.setPadding(cellStyle.getPadding());
+ //exthex - fix for not exactly vertically centered text
+ pdfCell.setUseAscender(true);
+
+ if (cellStyle.getBorder() > 0)
+ {
+ pdfCell.setBorderWidth(cellStyle.getBorder());
+ }
+ else
+ {
+ pdfCell.setBorder(0);
+ }
+ int align = -1;
+ if (type == Entry.TYPE_VALUE && cellStyle.getValueVAlign() != null)
+ align = ((Integer) alignMap_.get(cellStyle.getValueVAlign())).intValue();
+ //Note: to change the default valign of images to those of values, change the if construct below
+ else if (type == Entry.TYPE_IMAGE && cellStyle.getImageVAlign() != null)
+ align = ((Integer) alignMap_.get(cellStyle.getImageVAlign())).intValue();
+ else if (cellStyle.getVAlign() != null)
+ align = ((Integer) alignMap_.get(cellStyle.getVAlign())).intValue();
+ if (align != -1)
+ pdfCell.setVerticalAlignment(align);
+
+ align = -1;
+ if (type == Entry.TYPE_VALUE && cellStyle.getValueHAlign() != null)
+ align = ((Integer) alignMap_.get(cellStyle.getValueHAlign())).intValue();
+ //Note: to change the default halign of images to those of values, change the if construct below
+ else if (type == Entry.TYPE_IMAGE && cellStyle.getImageHAlign() != null)
+ align = ((Integer) alignMap_.get(cellStyle.getImageHAlign())).intValue();
+ else if (cellStyle.getHAlign() != null)
+ align = ((Integer) alignMap_.get(cellStyle.getHAlign())).intValue();
+ if (align != -1)
+ pdfCell.setHorizontalAlignment(align);
+ }
+ }
+
+ /**
+ * This method maps the cell font definition to the iText Font Object
+ *
+ * @param fontString
+ * @return the corresponding iText Font Object
+ * @see com.lowagie.text.Font
+ */
+ private Font getCellFont(String fontString)
+ {
+ Font font = DEFAULT_FONT;
+ if (fontString == null)
+ {
+ return font;
+ }
+ Object cache_font = fontMap_.get(fontString);
+ if (cache_font != null)
+ {
+ return (Font) cache_font;
+ }
+ String[] font_arr = fontString.split(",");
+ if (font_arr.length != 3)
+ {
+ return font;
+ }
+ Object font_face = fontMap_.get(font_arr[0]);
+ if (font_face == null)
+ {
+ return font;
+ }
+ Object font_weight = fontMap_.get(font_arr[2]);
+ if (font_weight == null)
+ {
+ return font;
+ }
+ int face = ((Integer) font_face).intValue();
+ float height = Float.parseFloat(font_arr[1]);
+ int weight = ((Integer) font_weight).intValue();
+
+ font = new Font(face, height, weight);
+ fontMap_.put(fontString, font);
+ return font;
+ }
+
+ /**
+ * Creates a custom
+ * @param fontString
+ * @return
+ * @throws PDFDocumentException
+ */
+ private Font getCellTrueTypeFont(String fontString) throws PDFDocumentException {
+ float fontSize=8;
+ String fontName = fontString.replaceFirst("TTF:", "");
+ String[] split = fontName.split(",");
+ if(split.length>1)
+ {
+ fontName = split[0].trim();
+ try
+ {
+ fontSize = Float.parseFloat(split[1].trim());
+ }catch (NumberFormatException e)
+ {
+ logger_.error("Unable to parse fontsize:"+fontString);
+ }
+ }
+ logger_.debug("TrueType Font detected:"+fontName +" ("+fontSize+")");
+
+ try {
+ Font font = (Font) fontMap_.get(fontString);
+
+ if (font == null) {
+ logger_.debug("Font \"" + fontString + "\" not in cache. Instantiating font.");
+ String fontPath = SettingsReader.RESOURCES_PATH + "fonts" + File.separator + fontName;
+ logger_.debug("Instantiating \"" + fontPath + "\".");
+
+ font = new Font(BaseFont.createFont(fontPath, BaseFont.WINANSI, true), fontSize);
+ fontMap_.put(fontString, font);
+ }
+ return font;
+ } catch (DocumentException e) {
+ throw new PDFDocumentException(ErrorCode.FONT_NOT_FOUND, e.getMessage());
+ } catch (IOException e) {
+ throw new PDFDocumentException(ErrorCode.FONT_NOT_FOUND, e.getMessage());
+ }
+ }
+
+ /**
+ * This method visualize an abstract table cell into a corresponding pdf table
+ * cell. The new pdf table cell is redered and get the style information from
+ * the abstract cell. Following types can be rendered:
+ * <ul>
+ * <li>text statements</li>
+ * <li>images</li>
+ * <li>tables</li>
+ * </ul>
+ *
+ * @param abstractCell
+ * the abstract cell definition
+ * @return the new redererd pdf table cell
+ * @throws PDFDocumentException
+ * ErrorCode:220, 221, 222
+ * @see com.lowagie.text.pdf.PdfPCell
+ * @see at.knowcenter.wag.egov.egiz.table.Entry
+ */
+ private PdfPCell renderCell(Entry abstractCell) throws PDFDocumentException
+ {
+ boolean pdfaValid =false;
+ try
+ {
+ String profileid = sigObject_.getSignatureTypeDefinition().getType();
+ String pdfa = SettingsReader.getInstance().getSetting("sig_obj." +profileid+".key."+SIG_PDFA1_B_VALID, "default."+SIG_PDFA1_B_VALID, "false");
+ pdfaValid= "true".equalsIgnoreCase(pdfa);
+
+// exthex test
+ //SubsetLocal.set(!pdfaValid);
+
+// boolean forceSubset = true; // get this from config, default to false
+ //String
+
+ //SubsetLocal.set(true); // exthex
+
+ logger_.trace("Sign PDF/A compliant:"+pdfa);
+ } catch (SettingsException e1)
+ {
+ logger_.error(e1);
+ }
+
+ PdfPCell pdf_cell = null;
+ Style cell_style = abstractCell.getStyle();
+ boolean isValue = true;
+ switch (abstractCell.getType())
+ {
+ case Entry.TYPE_CAPTION:
+ isValue = false;
+ case Entry.TYPE_VALUE:
+ String text = (String) abstractCell.getValue();
+ if (text == null)
+ {
+ text = "";
+ }
+ String font_string = cell_style.getFont();
+ if (abstractCell.getType() == Entry.TYPE_VALUE && cell_style.getValueFont() != null)
+ {
+ font_string = cell_style.getValueFont();
+ }
+
+ logger_.trace("using cell font: "+font_string);
+
+ Font cell_font;
+ if(font_string.startsWith("TTF:"))
+ {
+ cell_font = getCellTrueTypeFont(font_string);
+ }
+ else
+ {
+ if (pdfaValid) {
+ throw new PDFDocumentException(ErrorCode.NO_EMBEDABLE_TTF_CONFIGURED_FOR_PDFA, "PDF/A modus requires an embedable true type font");
+ }
+ cell_font = getCellFont(font_string);
+
+ }
+ // exthex
+ if (pdfaValid && abstractCell.getType() == Entry.TYPE_VALUE) {
+ SubsetLocal.addNonSubsetFont(cell_font.getBaseFont());
+ }
+ Phrase text_phrase = new Phrase(text, cell_font);
+ pdf_cell = new PdfPCell(text_phrase);
+ setCellStyle(pdf_cell, cell_style, (isValue?Entry.TYPE_VALUE:Entry.TYPE_CAPTION));
+ break;
+ case Entry.TYPE_IMAGE:
+ try
+ {
+ String img_ref = (String) abstractCell.getValue();
+ // fixed by tknall start
+ File img_file = new File(img_ref);
+ if (!img_file.isAbsolute()) {
+ logger_.debug("Image file declaration is relative. Prepending path of resources directory.");
+ img_file = new File(SettingsReader.relocateFile(img_ref));
+ } else {
+ logger_.debug("Image file declaration is absolute. Skipping file relocation.");
+ }
+// String img_location = SettingsReader.relocateFile(img_ref);
+// File img_file = new File (img_location);
+ if (!img_file.exists())
+ {
+ logger_.debug("Image file \"" + img_file.getCanonicalPath() + "\" doesn't exist.");
+ throw new PDFDocumentException(220, "Image file \"" + img_file.getCanonicalPath() + "\" doesn't exist.");
+ }
+ Image image = Image.getInstance(img_file.getCanonicalPath());
+ logger_.debug("Using image file \"" + img_file.getCanonicalPath() + "\".");
+
+ image.scaleToFit(80.0f, 80.0f);
+ boolean fit = true;
+ Style.ImageScaleToFit istf = cell_style.getImageScaleToFit();
+ if (istf != null)
+ {
+ image.scaleToFit(istf.getWidth(), istf.getHeight());
+ fit = false;
+ }
+ pdf_cell = new PdfPCell(image, fit);
+ setCellStyle(pdf_cell, cell_style, Entry.TYPE_IMAGE);
+ }
+ catch (BadElementException e)
+ {
+ if (logger_.isEnabledFor(Level.ERROR))
+ {
+ logger_.error("BadElementException:" + e.getMessage());
+ }
+ PDFDocumentException pde = new PDFDocumentException(220, "PDF table can not created");
+ throw pde;
+ }
+ catch (MalformedURLException e)
+ {
+ if (logger_.isEnabledFor(Level.ERROR))
+ {
+ logger_.error("MalformedURLException:" + e.getMessage());
+ }
+ PDFDocumentException pde = new PDFDocumentException(221, "PDF table can not created");
+ throw pde;
+ }
+ catch (IOException e)
+ {
+ if (logger_.isEnabledFor(Level.ERROR))
+ {
+ logger_.error("Error Code: 222, IOException:" + e.getMessage());
+ }
+ PDFDocumentException pde = new PDFDocumentException(222, "PDF table can not created: Image can not loaded");
+ throw pde;
+ }
+ break;
+ case Entry.TYPE_TABLE:
+ Table table = (Table) abstractCell.getValue();
+ // inherit the style from the parent table
+ Style inherit_style = Style.doInherit(table.getStyle(), cell_style);
+ table.setStyle(inherit_style);
+ PdfPTable pdf_table = renderTable(table);
+ pdf_cell = new PdfPCell(pdf_table);
+ // The default new PdfPCell has a default border of 15.
+ // For blocks without border and subtables this results
+ // in a border to be drawn around the cell.
+ // ==> no border on default
+ pdf_cell.setBorder(0);
+ break;
+ }
+ return pdf_cell;
+ }
+
+ /**
+ * This method visualize an abstract table into a corresponding pdf table. The
+ * new pdf table is redered and get the style information from the abstract
+ * cell.
+ *
+ * @param abstractTable
+ * the abstract table definition
+ * @return the new redererd pdf table cell
+ * @throws PDFDocumentException
+ * ErrorCode:220, 221, 222, 223
+ * @see com.lowagie.text.pdf.PdfPTable
+ * @see at.knowcenter.wag.egov.egiz.table.Table
+ */
+ private PdfPTable renderTable(Table abstractTable) throws PDFDocumentException
+ {
+ if (abstractTable == null)
+ {
+ PDFDocumentException pde = new PDFDocumentException(223, "Table is not defined.");
+ throw pde;
+ }
+ PdfPTable pdf_table = null;
+ float[] cols = abstractTable.getColsRelativeWith();
+ int max_cols = abstractTable.getMaxCols();
+ if (cols == null)
+ {
+ cols = new float[max_cols];
+ // set the column ratio for all columns to 1
+ for (int cols_idx = 0; cols_idx < cols.length; cols_idx++)
+ {
+ cols[cols_idx] = 1;
+ }
+ }
+ pdf_table = new PdfPTable(cols);
+ pdf_table.setWidthPercentage(abstractTable.getWidth());
+ Style table_style = abstractTable.getStyle();
+ setCellStyle(pdf_table.getDefaultCell(), table_style, Entry.TYPE_TABLE);
+
+ ArrayList rows = abstractTable.getRows();
+ for (int row_idx = 0; row_idx < rows.size(); row_idx++)
+ {
+ ArrayList row = (ArrayList) rows.get(row_idx);
+ // logger_.debug("## Row:" + row_idx + " ## of table:" +
+ // abstractTable.getName());
+ for (int entry_idx = 0; entry_idx < row.size(); entry_idx++)
+ {
+ Entry cell = (Entry) row.get(entry_idx);
+ // 03.11.2010 changed by exthex - swapped the two params, was probably a bug
+ Style inherit_style = Style.doInherit(table_style, cell.getStyle());
+ cell.setStyle(inherit_style);
+ // logger_.debug(cell.toString());
+ PdfPCell pdf_cell = renderCell(cell);
+ if (cell.getColSpan() > 1)
+ {
+ pdf_cell.setColspan(cell.getColSpan());
+ }
+ if (cell.isNoWrap())
+ {
+ pdf_cell.setNoWrap(true);
+ }
+ // System.err.println("valign:" + pdf_cell.getVerticalAlignment() + "
+ // halign:" +
+ // pdf_cell.getHorizontalAlignment());
+ pdf_table.addCell(pdf_cell);
+ }
+ }
+ // logger_.debug("render table:" + abstractTable.getName());
+ return pdf_table;
+ }
+
+ /**
+ * This method creates the pdf table object. It takes the abstract table
+ * definition from the signature object and render the abstract table.
+ *
+ * @param sigObject
+ * the signature object, the base for the abstract table definition
+ * @return R
+ * @throws PDFDocumentException
+ * ErrorCode:220, 221, 222, 223
+ */
+ private PdfPTable createPDFSignatureObject(SignatureObject sigObject) throws PDFDocumentException
+ {
+ SubsetLocal.clear();
+ Table table = sigObject.getAbstractTable();
+ PdfPTable pdf_table = renderTable(table);
+ return pdf_table;
+ }
+
+ /*
+ * This method search for the table definitions in the settings file an init
+ * @param sigObject
+ */
+ /*
+ * private void initTableSettings(SignatureObject sigObject) { String sig_type =
+ * sigObject.getSignationType(); String table_key = SignatureObject.SIG_OBJ +
+ * sig_type + ".table."; ArrayList main_rows = settings_.getKeys(table_key +
+ * "main"); }
+ */
+
+ /**
+ * Converts the current abstract signature object in a pdf signature object
+ * implementation
+ *
+ * @return the converted pdf signature object
+ * @see at.knowcenter.wag.egov.egiz.pdf.PDFSignatureObject#getSignatureObject()
+ */
+ public Object getSignatureObject() throws PDFDocumentException
+ {
+ if (pdfSigObject_ == null)
+ {
+ pdfSigObject_ = (PdfPTable) getSignatureObject(sigObject_);
+ }
+ return pdfSigObject_;
+ }
+
+ /**
+ * Converts a abstract signature object in a pdf signature object
+ * implementation
+ *
+ * @param sigObject
+ * the abstract signatorObject to convert
+ * @return the converted pdf signature object
+ * @throws PDFDocumentException
+ * @see at.knowcenter.wag.egov.egiz.pdf.PDFSignatureObject#getSignatureObject(at.knowcenter.wag.egov.egiz.sig.SignatureObject)
+ */
+ public Object getSignatureObject(SignatureObject sigObject) throws PDFDocumentException
+ {
+ // initTableSettings(sigObject);
+ return createPDFSignatureObject(sigObject);
+ }
+} \ No newline at end of file
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFUtilities.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFUtilities.java
new file mode 100644
index 0000000..e2a3d06
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFUtilities.java
@@ -0,0 +1,148 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: PDFUtilities.java,v 1.3 2006/10/31 08:09:33 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.pdf;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+import at.gv.egiz.pdfas.framework.input.PdfDataSource;
+import at.gv.egiz.pdfas.impl.input.ByteArrayPdfDataSourceImpl;
+
+import org.pdfbox.pdfparser.PDFParser;
+import org.pdfbox.pdmodel.PDDocument;
+import org.pdfbox.pdmodel.PDPage;
+
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException;
+
+import com.lowagie.text.DocumentException;
+
+/**
+ * Contains useful helpers for accessing PDF documents.
+ *
+ * @author wprinz
+ * @author mruhmer
+ */
+public abstract class PDFUtilities
+{
+ public static float calculatePageLength(final PdfDataSource pdfDataSource,int page ,float footer_line, int pagerotation) throws PDFDocumentException
+ {
+ try
+ {
+ //ByteArrayInputStream original_bais = new ByteArrayInputStream(pdf);
+ //byte [] normalized_pdf = TextualSignature.normalizePDF(original_bais);
+ byte [] normalized_pdf = TextualSignature.normalizePDF(pdfDataSource);
+
+ // PERF: The whole PDF normalization process is costy
+ ByteArrayInputStream bais = new ByteArrayInputStream(normalized_pdf);
+
+ PDFParser parser = new PDFParser(bais);
+ File temporary_dir = SettingsReader.getTemporaryDirectory();
+ parser.setTempDirectory(temporary_dir);
+ parser.parse();
+
+ PDDocument pdfDocument_ = parser.getPDDocument();
+ float page_length = calculatePageLength(pdfDocument_,page , footer_line, pagerotation);
+ pdfDocument_.close();
+ return page_length;
+ }
+ catch (IOException e)
+ {
+ throw new PDFDocumentException(201, e);
+ }
+ catch (DocumentException e)
+ {
+ throw new PDFDocumentException(201, e);
+ }
+ }
+ public static float calculatePageLength(PDDocument document,int page ,float footer_line, int pagerotation) throws IOException
+ {
+ //int last_page_id = document.getNumberOfPages();
+ List allPages = document.getDocumentCatalog().getAllPages();
+ PDPage pdpage = (PDPage) allPages.get(page);
+ pdpage.setRotation(pagerotation);
+ return calculatePageLength(pdpage, footer_line);
+ }
+
+ /**
+ * @deprecated
+ * @param pdf
+ * @param footer_line
+ * @return
+ * @throws PDFDocumentException
+ */
+ public static float calculateLastPageLength(final byte[] pdf, float footer_line) throws PDFDocumentException
+ {
+ try
+ {
+ //ByteArrayInputStream original_bais = new ByteArrayInputStream(pdf);
+ PdfDataSource dataSource = new ByteArrayPdfDataSourceImpl(pdf);
+ byte [] normalized_pdf = TextualSignature.normalizePDF(dataSource);
+
+ ByteArrayInputStream bais = new ByteArrayInputStream(normalized_pdf);
+
+ PDFParser parser = new PDFParser(bais);
+ File temporary_dir = SettingsReader.getTemporaryDirectory();
+ parser.setTempDirectory(temporary_dir);
+ parser.parse();
+
+ PDDocument pdfDocument_ = parser.getPDDocument();
+ float last_page_length = calculateLastPageLength(pdfDocument_, footer_line);
+ pdfDocument_.close();
+
+ return last_page_length;
+ }
+ catch (IOException e)
+ {
+ throw new PDFDocumentException(201, e);
+ }
+ catch (DocumentException e)
+ {
+ throw new PDFDocumentException(201, e);
+ }
+ }
+
+ public static float calculateLastPageLength(PDDocument document, float footer_line) throws IOException
+ {
+ int last_page_id = document.getNumberOfPages();
+ List allPages = document.getDocumentCatalog().getAllPages();
+ PDPage last_page = (PDPage) allPages.get(last_page_id - 1);
+
+ return calculatePageLength(last_page, footer_line);
+ }
+
+ public static float calculatePageLength(PDPage page, float footer_line) throws IOException
+ {
+ // logger_.debug("Last Page id:" + last_page_id);
+ // PDPage last_page = (PDPage) allPages.get(0);
+ PDFPage my_page = new PDFPage(footer_line);
+ my_page.processStream(page, page.findResources(), page.getContents().getStream());
+ return my_page.getMaxPageLength();
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/Placeholder.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/Placeholder.java
new file mode 100644
index 0000000..9249985
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/Placeholder.java
@@ -0,0 +1,572 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: Placeholder.java,v 1.5 2006/10/31 08:17:50 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.pdf;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.sound.midi.SysexMessage;
+
+import org.apache.commons.codec.net.URLCodec;
+import org.apache.log4j.Logger;
+
+import at.knowcenter.wag.egov.egiz.cfg.ConfigLogger;
+import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException;
+import at.knowcenter.wag.egov.egiz.exceptions.PlaceholderException;
+import at.knowcenter.wag.exactparser.ByteArrayUtils;
+
+/**
+ * Helper class that provides functionality for dealing with placeholders and
+ * replacements in pdf.
+ *
+ * @author wprinz
+ */
+public abstract class Placeholder
+{
+ /**
+ * The logger definition.
+ */
+ private static final Logger logger_ = ConfigLogger.getLogger(Placeholder.class);
+
+ /**
+ * Escapes the String to be a suitable Literal String..
+ *
+ * @param data
+ * The String to be escaped.
+ * @return Returns the escaped PDF String.
+ */
+ public static byte[] escapePDFString(byte[] data)
+ {
+ try
+ {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ for (int i = 0; i < data.length; i++)
+ {
+ byte[] escaped_bytes = escapeByte(data[i]);
+ baos.write(escaped_bytes);
+ }
+ return baos.toByteArray();
+ }
+ catch (IOException e)
+ {
+ logger_.error(e.getMessage(), e);
+ return null;
+ }
+ }
+
+ /**
+ * Unescapes the PDF String.
+ *
+ * @param data
+ * The escaped String.
+ * @return Returns the unescaped String.
+ */
+ public static byte[] unescapePDFString(byte[] data)
+ {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ for (int i = 0; i < data.length; i++)
+ {
+ if (data[i] == '\\' && data[i + 1] == '\\')
+ {
+ baos.write('\\');
+ i++;
+ continue;
+ }
+ if (data[i] == '\\' && data[i + 1] == '(')
+
+ {
+ baos.write('(');
+ i++;
+ continue;
+ }
+ if (data[i] == '\\' && data[i + 1] == ')')
+ {
+ baos.write(')');
+ i++;
+ continue;
+ }
+ baos.write(data[i]);
+ }
+ return baos.toByteArray();
+ }
+
+ /**
+ * Reconstructs the string from a partition of placeholders.
+ *
+ * @param pdf
+ * The PDF to read the string from.
+ * @param sis
+ * The list of StringInfo objects that specify the bytes of the
+ * string in the pdf.
+ * @return Returns the extracted and reconverted string.
+ * @throws IOException
+ * Forwarded exception.
+ */
+ public static String reconstructStringFromPartition(byte[] pdf, List sis,
+ byte[] enc) throws IOException
+ {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ Iterator it = sis.iterator();
+ while (it.hasNext())
+ {
+ StringInfo si = (StringInfo) it.next();
+
+ for (int i = si.string_start; i < si.string_start + si.string_length; i++)
+ {
+ if (pdf[i] != 0)
+ {
+ baos.write(pdf[i]);
+ }
+ }
+ }
+
+ baos.close();
+ byte[] bytes = baos.toByteArray();
+
+ byte[] unescaped_bytes = unescapePDFString(bytes);
+
+ if (!ByteArrayUtils.compareByteArrays(enc, 0, BinarySignature.ENCODING_WIN) && !ByteArrayUtils.compareByteArrays(enc, 0, BinarySignature.ENCODING_URL))
+ {
+ String enc_str = new String(enc, "US-ASCII");
+ logger_.warn("The encoding " + enc_str + " is not known by this application - trying to proceed anyways.");
+ }
+
+ String text = new String(unescaped_bytes, "windows-1252");
+
+ String str = text;
+ if (ByteArrayUtils.compareByteArrays(enc, 0, BinarySignature.ENCODING_URL))
+ {
+ str = unapplyURLEncoding(str);
+ }
+
+ return str;
+ }
+
+ /**
+ * Prepares the given String to a byte array that can be substituted into the
+ * placeholder.
+ *
+ * @param text
+ * The text to be prepared for substitution.
+ * @return Returns the prepared byte array.
+ */
+ public static byte[] applyWinAnsiEncoding(String text)
+ {
+ // text = text.replace("\\", "\\\\");
+ // text = text.replace("(", "\\(");
+ // text = text.replace(")", "\\)");
+
+ byte[] replace_bytes;
+ try
+ {
+ replace_bytes = text.getBytes("windows-1252");// CP1252 = WinAnsiEncoding
+
+ // test the opposite way:
+ // String restored_string = new String (replace_bytes, "windows-1252");
+ // if (!restored_string.equals(text))
+ // {
+ // String url_encoded = URLEncoder.encode(text);
+ // replace_bytes = url_encoded.getBytes("windows-1252");
+ // }
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ logger_.error(e.getMessage(), e);
+ return null;
+ }
+ return replace_bytes;
+ }
+
+ /**
+ * Unapplies the WinAnsi encoding.
+ *
+ * @param replace_bytes
+ * The bytes.
+ * @return Returns the decoded String.
+ */
+ public static String unapplyWinAnsiEncoding(byte[] replace_bytes)
+ {
+ try
+ {
+ String text = new String(replace_bytes, "windows-1252");
+
+ return text;
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ logger_.error(e.getMessage(), e);
+ return null;
+ }
+
+ }
+
+ /**
+ * Applies the URL encoding to the text.
+ *
+ * @param text
+ * The text
+ * @return Returns the URL and WinAnsi encoded text.
+ */
+ public static byte[] applyURLEncoding(String text)
+ {
+ URLCodec utf8_url_codec = new URLCodec("UTF-8");
+ String url_encoded = null;
+ try
+ {
+ url_encoded = utf8_url_codec.encode(text, "UTF-8");
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ throw new RuntimeException("Couldn't url encode : " + text, e);
+ }
+ // String url_encoded = URLEncoder.encode(text);
+ return applyWinAnsiEncoding(url_encoded);
+ }
+
+ /**
+ * Unapplies the WinAnsi and URL encoding.
+ *
+ * @param winansi_str
+ * The Winansi and URL text.
+ * @return Returns the decoded text.
+ */
+ public static String unapplyURLEncoding(String winansi_str)
+ {
+ URLCodec utf8_url_codec = new URLCodec("UTF-8");
+ String url_decoded = null;
+ try
+ {
+ url_decoded = utf8_url_codec.decode(winansi_str, "UTF-8");
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException("Couldn't url decode : " + winansi_str, e);
+ }
+ // String url_decoded = URLDecoder.decode(winansi_str);
+ return url_decoded;
+ }
+
+ /**
+ * Restores the String from a previously prepared byte array.
+ *
+ * @param pdf_string
+ * The byte array.
+ * @return Returns the unprepared String.
+ */
+ public static String unprepareAndUnescapeString(byte[] pdf_string)
+ {
+ try
+ {
+ String text = new String(pdf_string, "windows-1252");
+
+ // This makes problems when "+" appears.
+ // if (isURLEncoded(text))
+ // {
+ // text = URLDecoder.decode(text);
+ // }
+
+// text = text.replace("\\)", ")");
+// text = text.replace("\\(", "(");
+// text = text.replace("\\\\", "\\");
+
+ // TODO: replace jdk1.5-code with jdf1.4-code (should be tested)
+ /* */
+ text = text.replaceAll("\\\\\\)", ")");
+ text = text.replaceAll("\\\\\\(", "(");
+ text = text.replaceAll("\\\\\\\\", "\\\\");
+
+
+ return text;
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ logger_.error(e.getMessage(), e);
+ return null;
+ }
+ }
+
+ /**
+ * Checks the presence of typical URL encoded characters to tell if the string
+ * is URL encoded.
+ *
+ * <p>
+ * This heuristic checks if there are any non URL encoded characters in the
+ * String, like ASCII control characters, which aren't allowed in the
+ * URLEncoding characterset.
+ * </p>
+ *
+ * @param text
+ * The text under suspicion.
+ * @return Returns true if the String is URL encoded, false otherwise.
+ */
+ protected static boolean isURLEncoded(String text)
+ {
+ if (text.indexOf(' ') >= 0)
+ {
+ return false;
+ }
+ for (int i = 0; i < text.length(); i++)
+ {
+ char c = text.charAt(i);
+ if (0x00 <= c && c <= 0x1f)
+ {
+ return false;
+ }
+ if (c == 0x7F)
+ {
+ return false;
+ }
+ if (0x80 <= c)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Tells, if a break can occur behind the given character.
+ *
+ * @param character
+ * The character.
+ * @return Returns true, if a break may occur behind the character, false
+ * otherwise.
+ */
+ protected static boolean canBreakAfter(byte character)
+ {
+ return (character == ' ' || character == '.' || character == ',' || character == ';' || character == '-' || character == '\n') ;
+ }
+
+ /**
+ * Scans the given PDF content stream for literal PDF strings.
+ *
+ * @param pdf
+ * The PDF.
+ * @param stream_start
+ * The start of the content stream to be scanned.
+ * @param stream_next
+ * The end of the content stream.
+ * @return Returns a list of StringInfo objects specifying the strings that
+ * could be found.
+ */
+ public static List parseStrings(byte[] pdf, int stream_start, int stream_next)
+ {
+ List strings = new ArrayList();
+ StringInfo cur_string = null;
+ for (int i = stream_start; i < stream_next; i++)
+ {
+ byte cur_byte = pdf[i];
+
+ if (cur_byte == '(' && pdf[i - 1] != '\\')
+ {
+ cur_string = new StringInfo();
+ cur_string.pdf = pdf;
+ cur_string.string_start = i + 1;
+ cur_string.string_length = -1;
+ // logger_.debug("String start = " + cur_string.string_start);
+ continue;
+ }
+ if (cur_byte == ')' && pdf[i - 1] != '\\')
+ {
+ cur_string.string_length = i - cur_string.string_start;
+ // logger_.debug("String length = " + cur_string.string_length);
+ strings.add(cur_string);
+
+ cur_string = null;
+ continue;
+ }
+ }
+
+ return strings;
+ }
+
+ /**
+ * Escapes the data byte if necessary.
+ *
+ * <p>
+ * Before bytes can be written into the pdf Strings, they have to be escaped.
+ * Special care has to be taken that escaped sequences are not split due to
+ * line breaks. This could have fatal consequences and usually renders the
+ * whole document invalid.
+ * </p>
+ *
+ * @param data
+ * The data byte to be escaped.
+ * @return Returns a new byte array escaping the data byte. If the byte needs
+ * not to be escaped, this new array will contain only the original
+ * data byte.
+ */
+ public static byte[] escapeByte(byte data)
+ {
+ if (data == '\\')
+ {
+ return new byte[] { '\\', '\\' };
+ }
+ if (data == '(')
+ {
+ return new byte[] { '\\', '(' };
+ }
+ if (data == ')')
+ {
+ return new byte[] { '\\', ')' };
+ }
+ return new byte[] { data };
+ }
+
+ /**
+ * Replaces the placeholder with the given String breaking lines with a given
+ * tolerance.
+ *
+ * @param pdf
+ * The PDF.
+ * @param sis
+ * The list of StringInfo objects describing the positions where the
+ * String should be filled in.
+ * @param replace_bytes
+ * The unescaped bytes to be filled in. Escaping is performed by this
+ * method.
+ * @param tolerance
+ * The tolerance for line wrapping. The tolerance counts from the end
+ * of a StringInfo backwards to its start. If a word that starts
+ * within the tolerance doesn't fit, it is wrapped into the next
+ * line.
+ * @throws PDFDocumentException
+ * Forwarded exception.
+ */
+ public static void replacePlaceholderWithTolerance(byte[] pdf, List sis,
+ byte[] replace_bytes, int tolerance) throws PDFDocumentException
+ {
+ try
+ {
+ // String rep_str = new String(replace_bytes);
+
+ SplitStrings ss = new SplitStrings(pdf, sis);
+
+ int read_index = 0;
+ while (read_index < replace_bytes.length)
+ {
+ if (!ss.isValidLine())
+ {
+ break;
+ }
+
+ byte[] token = readToken(replace_bytes, read_index);
+ // String token_str = new String(token);
+ byte[] escaped_token = escapeToken(token);
+
+ if (ss.fits(escaped_token))
+ {
+ ss.write(escaped_token);
+ read_index += token.length;
+ continue;
+ }
+ else
+ {
+ if (ss.getAvailable() < tolerance)
+ {
+ ss.newline();
+ continue;
+ }
+ else
+ {
+ // break the token
+ for (; read_index < replace_bytes.length; read_index++)
+ {
+ byte data = replace_bytes[read_index];
+
+ byte[] escaped_data = escapeByte(data);
+
+ if (ss.fits(escaped_data))
+ {
+ ss.write(escaped_data);
+ }
+ else
+ {
+ ss.newline();
+ break;
+ }
+ }
+ continue;
+
+ }
+ }
+ }
+ ss.fillRest();
+
+ if (read_index < replace_bytes.length)
+ {
+ logger_.error("The replace string was longer than the reserved placeholder.");
+ throw new PlaceholderException(null, replace_bytes.length - read_index);
+ }
+
+ }
+ catch (IOException e)
+ {
+ throw new PDFDocumentException(201, e);
+ }
+
+ }
+
+ protected static byte[] readToken(byte[] bytes, int index)
+ {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ for (; index < bytes.length; index++)
+ {
+ byte data = bytes[index];
+
+
+ // byte [] escaped_data = escapeByte(data);
+ baos.write(data);
+
+ if (canBreakAfter(data))
+ {
+ break;
+ }
+ }
+
+ return baos.toByteArray();
+ }
+
+
+
+protected static byte[] escapeToken(byte[] token) throws IOException
+ {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ for (int i = 0; i < token.length; i++)
+ {
+ byte[] escaped_data = escapeByte(token[i]);
+ baos.write(escaped_data);
+ }
+
+ return baos.toByteArray();
+ }
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/Pos.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/Pos.java
new file mode 100644
index 0000000..c0b3ecd
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/Pos.java
@@ -0,0 +1,70 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: Pos.java,v 1.1 2006/08/25 17:10:08 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.pdf;
+
+/**
+ * Encapsulation of a position on a PDF page.
+ *
+ * @author wprinz
+ */
+public class Pos
+{
+
+ public float x;
+
+ public float y;
+
+ public float z;
+
+ /**
+ * Default constructor.
+ */
+ public Pos()
+ {
+ }
+
+ /**
+ * Constructor that sets the coordinates.
+ * @param xx
+ * @param yy
+ * @param zz
+ */
+ public Pos(float xx, float yy, float zz)
+ {
+ this.x = xx;
+ this.y = yy;
+ this.z = zz;
+ }
+
+ /**
+ * @see java.lang.Object#toString()
+ */
+ public String toString()
+ {
+ return "(" + this.x + "," + this.y + "," + this.z + ")";
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PositioningInstruction.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PositioningInstruction.java
new file mode 100644
index 0000000..7af4ce7
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PositioningInstruction.java
@@ -0,0 +1,139 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: $
+ */
+package at.knowcenter.wag.egov.egiz.pdf;
+
+/**
+ * The positioning instruction holds information of where to place the signature
+ * block.
+ *
+ * <p>
+ * This instruction is given to the PDF writer in order to place the signature.
+ * </p>
+ *
+ * @author wprinz
+ */
+public class PositioningInstruction
+{
+
+ /**
+ * Tells, if a new plain page should be appended.
+ *
+ * <p>
+ * This command is executed before the signature block is positioned according
+ * to page, x and y.
+ * </p>
+ */
+ protected boolean make_new_page = false;
+
+ /**
+ * The number of the page on which the signature block is to be placed. If
+ * specified to make a new page, the number of this newly created page can be
+ * used here as well.
+ */
+ protected int page = 0;
+
+ /**
+ * The x coordinate where the upper left corner of the signature block should
+ * be placed.
+ */
+ protected float x = 0.0f;
+
+ /**
+ * The y coordinate where the upper left corner of the signature block should
+ * be placed.
+ */
+ protected float y = 0.0f;
+
+ /**
+ *
+ * @param make_new_page
+ * Tells, if a new plain page should be appended. This command is
+ * executed before the signature block is positioned according to
+ * page, x and y.
+ * @param page
+ * The number of the page on which the signature block is to be
+ * placed. If specified to make a new page, the number of this newly
+ * created page can be used here as well.
+ * @param x
+ * The x coordinate where the upper left corner of the signature
+ * block should be placed.
+ * @param y
+ * The y coordinate where the upper left corner of the signature
+ * block should be placed.
+ */
+ public PositioningInstruction(boolean make_new_page, int page, float x, float y)
+ {
+ this.make_new_page = make_new_page;
+ this.page = page;
+ this.x = x;
+ this.y = y;
+ }
+
+ /**
+ * Tells, if a new plain page should be appended to the document.
+ *
+ * @return Returns true, if a new plain page should be appended.
+ */
+ public boolean isMakeNewPage()
+ {
+ return this.make_new_page;
+ }
+
+ /**
+ * Returns the page on which the signature is to be printed.
+ *
+ * @return Returns the page on which the signature is to be printed.
+ */
+ public int getPage()
+ {
+ return this.page;
+ }
+
+ /**
+ * Returns the x coordinate where the upper left corner of the signature block
+ * should be placed.
+ *
+ * @return Returns the x coordinate where the upper left corner of the
+ * signature block should be placed.
+ */
+ public float getX()
+ {
+ return this.x;
+ }
+
+ /**
+ * Returns the y coordinate where the upper left corner of the signature block
+ * should be placed.
+ *
+ * @return Returns the y coordinate where the upper left corner of the
+ * signature block should be placed.
+ */
+ public float getY()
+ {
+ return this.y;
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/ReplaceInfo.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/ReplaceInfo.java
new file mode 100644
index 0000000..520d987
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/ReplaceInfo.java
@@ -0,0 +1,93 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: ReplaceInfo.java,v 1.1 2006/08/25 17:10:08 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.pdf;
+
+import java.io.Serializable;
+import java.util.List;
+
+import at.knowcenter.wag.egov.egiz.sig.SignatureFieldDefinition;
+
+/**
+ * Holds the information requeired to replace a certain value in the document
+ * completely.
+ *
+ * @author wprinz
+ */
+public class ReplaceInfo implements Serializable
+{
+
+ /**
+ * SVUID.
+ */
+ private static final long serialVersionUID = 7307210282876750431L;
+
+ /**
+ * The field definition of this value.
+ */
+ public SignatureFieldDefinition sfd = null;
+
+ /**
+ * The value itself.
+ */
+ public String value = null;
+
+ /**
+ * The list of Strings this value must be splitted to.
+ */
+ public List replaces = null;
+
+ /**
+ * The brev of this value.
+ */
+ public byte[] brev = null;
+
+ /**
+ * The encoding of this value.
+ */
+ public byte[] enc = null;
+
+ public String toString() {
+ return "ReplaceInfo [brev=" + (brev != null ? arrayToString(brev, brev.length) : null)
+ + ", enc=" + (enc != null ? arrayToString(enc, enc.length) : null) + ", sfd=" + sfd
+ + ", value=" + value + "]";
+ }
+
+ private String arrayToString(Object array, int len) {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("[");
+ for (int i = 0; i < len; i++) {
+ if (i > 0)
+ buffer.append(", ");
+ if (array instanceof byte[])
+ buffer.append(((byte[]) array)[i]);
+ }
+ buffer.append("]");
+ return buffer.toString();
+ }
+
+
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/SignatureHolder.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/SignatureHolder.java
new file mode 100644
index 0000000..54cac64
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/SignatureHolder.java
@@ -0,0 +1,76 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: SignatureHolder.java,v 1.3 2006/10/11 07:57:58 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.pdf;
+
+import at.gv.egiz.pdfas.framework.input.DataSource;
+import at.knowcenter.wag.egov.egiz.sig.SignatureObject;
+
+/**
+ * Data structure that holds the information of one signature block, which is
+ * the signed/signable text and the corresponding SignatureObject.
+ *
+ * <p>
+ * Signators and Verifiactors should implement own classes for this interface
+ * that generate the text to be signed from the underlying data. For example a
+ * binary signature holder could generate the text to be signed by Base64
+ * encoding the binary data. Furthermore this allows to cache the text to be
+ * signed.
+ * </p>
+ *
+ * @author wprinz
+ */
+public interface SignatureHolder
+{
+
+// /**
+// * Returns the signed text (verification) or the to-be-signed signable text
+// * (signation).
+// *
+// * <p>
+// * Note that this text must be the one that was actually signed. This text is
+// * directly passed to the connector for signation/verification. No
+// * normalization or modification will be / must be done to this text between
+// * reading out from the signature holder and passing the text to the
+// * connector.
+// * </p>
+// *
+// * @return Returns the signed text or the to-be-signed signable text.
+// */
+// public String getSignedText();
+
+ /**
+ *
+ * @return Returns the SignatureObject containing the issuer, serial number,
+ * etc.
+ */
+ public SignatureObject getSignatureObject();
+
+ /**
+ * Returns the DataSource providing the data.
+ * @return
+ */
+ public DataSource getDataSource();
+} \ No newline at end of file
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/SplitStrings.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/SplitStrings.java
new file mode 100644
index 0000000..be2b2b4
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/SplitStrings.java
@@ -0,0 +1,177 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: SplitStrings.java,v 1.1 2006/08/30 14:02:35 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.pdf;
+
+import java.util.List;
+
+import org.apache.commons.lang.ArrayUtils;
+
+
+/**
+ * Class that helps filling out the placeholders.
+ *
+ * <p>
+ * This class treats a sequence of placeholder StringInfos like a continuous
+ * data area that can be filled out regarding the boundaries.
+ * </p>
+ *
+ * @author wprinz
+ */
+public class SplitStrings
+{
+ /**
+ * The byte used to fill unused bytes in the placeholders.
+ */
+
+ public static final byte FILL_BYTE = ' ';
+
+ /**
+ * The underlying PDF.
+ */
+ protected byte[] pdf = null;
+
+ /**
+ * The strings to be filled out.
+ */
+ protected StringInfo[] strings = null;
+
+ /**
+ * The current string which is written to.
+ */
+ protected int cur_string = 0;
+
+ /**
+ * The current write position within the current string.
+ */
+ protected int cur_pos = 0;
+
+ /**
+ * Constructor.
+ *
+ * @param pdf
+ * The underlying PDF.
+ * @param strings
+ * The strings to be filled out.
+ */
+ public SplitStrings(byte[] pdf, List strings)
+ {
+ this.pdf = pdf;
+ this.strings = new StringInfo[strings.size()];
+ for (int i = 0; i < strings.size(); i++)
+ {
+ StringInfo si = (StringInfo) strings.get(i);
+ this.strings[i] = si;
+ }
+ }
+
+ /**
+ * Returns how many bytes are still available in the current string.
+ *
+ * @return Returns the number of bytes that are still available. (positive
+ * integer, or zero if none are available)
+ */
+ public int getAvailable()
+ {
+ return this.strings[this.cur_string].string_length - this.cur_pos;
+ }
+
+ /**
+ * Tells, if the whole data would fit into the current string.
+ *
+ * @param data
+ * The data to be matched for fitting
+ * @return Returns true, if the whole data fits, false otherwise.
+ */
+ public boolean fits(byte[] data)
+ {
+ return getAvailable() >= data.length;
+ }
+
+ /**
+ * Writes the data into the current string.
+ *
+ * <p>
+ * Note that the data must fit in.
+ * </p>
+ * @param data The data to be written.
+ */
+ public void write(byte[] data)
+ {
+ if (!fits(data))
+ {
+ throw new IllegalArgumentException("The data doesn't fit in.");
+ }
+
+ System.arraycopy(data, 0, this.pdf, this.strings[this.cur_string].string_start + this.cur_pos, data.length);
+ this.cur_pos += data.length;
+
+ if (data[data.length-1] == '\n') {
+ this.cur_pos -= 1; // remove \n from output
+ newline();
+ }
+ }
+
+ /**
+ * Fills the current string with the fill character and moves on to the next
+ * string.
+ *
+ */
+ public void newline()
+ {
+ int end = this.strings[this.cur_string].string_start + this.strings[this.cur_string].string_length;
+ for (int i = this.strings[this.cur_string].string_start + this.cur_pos; i < end; i++)
+ {
+ pdf[i] = FILL_BYTE;
+ }
+
+ this.cur_string++;
+ this.cur_pos = 0;
+ }
+
+ /**
+ * Fills all rest bytes with the fill character.
+ *
+ * <p>
+ * This should be called when everything is finished to fill all strings properly.
+ * </p>
+ */
+ public void fillRest()
+ {
+ while (this.cur_string < this.strings.length)
+ {
+ newline();
+ }
+ }
+
+ /**
+ * Tells, if the current line is valid.
+ * @return Returns true, if this is a line that can be written to.
+ */
+ public boolean isValidLine ()
+ {
+ return this.cur_string < this.strings.length;
+ }
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/StringInfo.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/StringInfo.java
new file mode 100644
index 0000000..1982077
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/StringInfo.java
@@ -0,0 +1,106 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: StringInfo.java,v 1.2 2006/10/11 07:57:58 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.pdf;
+
+import java.io.Serializable;
+import java.io.UnsupportedEncodingException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Specifies a certain data area within the pdf.
+ *
+ * <p>
+ * Actually this is a byte range, which is used to hold the placeholder ranges
+ * for later replacement.
+ * </p>
+ *
+ * @author wprinz
+ */
+public class StringInfo implements Serializable
+{
+ /**
+ * SVUID.
+ */
+ private static final long serialVersionUID = 5834801907046737048L;
+
+ protected static Log logger = LogFactory.getLog(StringInfo.class);
+
+ /**
+ * The PDF document this range belongs to.
+ */
+ public byte[] pdf = null;
+
+ /**
+ * The start offset of the range.
+ */
+ public int string_start = -1;
+
+ /**
+ * The length of the range.
+ */
+ public int string_length = -1;
+
+ /**
+ * Copies the bytes of this range to a new byte array.
+ *
+ * @return Returns the new byte array.
+ */
+ public byte[] copyStringBytes()
+ {
+ byte[] bytes = new byte[this.string_length];
+ System.arraycopy(this.pdf, this.string_start, bytes, 0, this.string_length);
+ return bytes;
+ }
+
+ /**
+ * Converts the range into a String.
+ *
+ * @return Returns the String.
+ * @throws UnsupportedEncodingException
+ * Forwarded exception.
+ */
+ public String getString(String encoding) throws UnsupportedEncodingException
+ {
+ byte[] bytes = copyStringBytes();
+ return new String(bytes, encoding);
+ }
+
+ public String toString()
+ {
+ try
+ {
+ return "(" + this.string_start + "," + this.string_length + ")" + getString("ISO-8859-1");
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ logger.error(e.getMessage(), e);
+ return "(" + this.string_start + "," + this.string_length + ")";
+ }
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/StructContentHelper.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/StructContentHelper.java
new file mode 100644
index 0000000..7ca5a0a
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/StructContentHelper.java
@@ -0,0 +1,716 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.pdf;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.knowcenter.wag.egov.egiz.exceptions.PresentableException;
+import at.knowcenter.wag.egov.egiz.sig.SignatureObject;
+
+import com.lowagie.text.Rectangle;
+import com.lowagie.text.pdf.PdfArray;
+import com.lowagie.text.pdf.PdfContentByte;
+import com.lowagie.text.pdf.PdfDictionary;
+import com.lowagie.text.pdf.PdfFormField;
+import com.lowagie.text.pdf.PdfIndirectReference;
+import com.lowagie.text.pdf.PdfName;
+import com.lowagie.text.pdf.PdfNumber;
+import com.lowagie.text.pdf.PdfObject;
+import com.lowagie.text.pdf.PdfStamper;
+import com.lowagie.text.pdf.PdfStamperImp;
+import com.lowagie.text.pdf.PdfString;
+import com.lowagie.text.pdf.PdfTemplate;
+import com.lowagie.text.pdfas.StructContentWriter;
+import com.lowagie.text.pdfas.StructContentWriterHolder;
+import com.lowagie.text.pdfas.UrlInTextFinder;
+
+/**
+ * Helper class for writing the structure hierarchy of the signature elements.
+ * Everything is written with the PdfObject low level API because there is no better support.
+ * The structured content is only written for structured (==tagged) input documents. The methods have to be called in the
+ * defined order. The object cannot be reused for several signatures.<br>
+ * See pdf spec "Logical Structure" for details.<br>
+ * The struct writing could be a little more abstracted, but this would include quite some itext extension work. And like this it
+ * fits better to PDF-AS / wprinz coding style :-(
+ * @author exthex
+ *
+ */
+public class StructContentHelper implements StructContentWriter {
+ private static final Logger logger = Logger.getLogger(StructContentHelper.class);
+
+ private static final String SIGBLOCK_STRUCT_TYPE = "P";
+ private static final PdfName PARENTTREENEXTKEY = new PdfName("ParentTreeNextKey");
+ private static final String ALT_TEXT_DEFAULT = "Signaturbildmarke";
+ private final static String ALT_TEXT_CONF_KEY = "sigLogoAltText";
+
+
+ private int nextMcid = 0;
+ /**
+ * MCID value used for the sigblock marked contend identifier
+ */
+ private int sigBlockMcid =-1;
+ /**
+ * MCID value for "Bildmarke" marked content sequence
+ */
+ private int figureMcid = -1;
+ /**
+ * MCID value for verify link marked content sequence
+ */
+ private int linkMcid = -1;
+ private String linkUrlString = null;
+ private boolean isTagged = false;
+ private Map linkPosMap = new HashMap();
+ private Map tmpMap = new HashMap();
+
+ private PdfStamper stamper;
+ private PdfStamperImp stamperImp;
+ private PdfContentByte content;
+ private PdfDictionary page;
+ private PdfNumber parentTreeNextKey = null;
+ private PdfNumber annotationParentTreeKey = null;
+
+ /**
+ * Temporary save a pos
+ */
+ private Rectangle tempMarkedPos = null;
+ /**
+ * Cell position of the signature verify link overlay
+ */
+ private Rectangle verifyLinkCellPos = null;
+
+ /**
+ * Kids array (K) of the <code>StructTreeRoot</code>
+ */
+ private PdfArray structTreeRootKids = null;
+
+ /**
+ * Entry in the ParentTree.Nums array used for sigtable structs
+ */
+ private PdfArray mainParentTreeNumEntry;
+
+ /**
+ * Create new helper for one signature, and bind it to {@link StructContentWriterHolder}
+ * for thread local access from itext.
+ *
+ * @param stamper
+ * @param content
+ * @param pageNr
+ */
+ StructContentHelper(PdfStamper stamper, PdfContentByte content, int pageNr) {
+ this.stamper = stamper;
+ this.content = content;
+ stamperImp = ((PdfStamperImp) stamper.getWriter());
+ page = stamper.getReader().getPageN(pageNr);
+ StructContentWriterHolder.setThreadLocalWriter(this);
+ }
+
+ /**
+ * Remove thread local helper
+ */
+ public void removeCurrent() {
+ StructContentWriterHolder.removeThreadLocalWriter();
+ }
+
+ /**
+ * Prepare structured content for signature block. This method initializes the whole StructTreeRoot stuff.
+ * @param sigBlockObj
+ * @throws PresentableException
+ */
+ void prepareStructData(PdfTemplate sigBlockObj) throws PresentableException {
+
+ try {
+ checkTagging();
+ if (!isTagged) {
+ return;
+ }
+
+ doAnnoTabOrder();
+
+ PdfDictionary structTreeRoot = getStructTreeRoot();
+ stamperImp.markUsed(structTreeRoot);
+
+ PdfArray parentTreeNums = getParentTreeNums();
+
+ PdfNumber structParentsNr = page.getAsNumber(PdfName.STRUCTPARENTS); // read StructParents entry from current page
+
+ mainParentTreeNumEntry = obtainParentTreeEntry(structTreeRoot, parentTreeNums, structParentsNr, sigBlockObj);
+
+ nextMcid = mainParentTreeNumEntry.size();
+ sigBlockMcid = nextMcid;
+ nextMcid++;
+
+ this.structTreeRootKids = obtainStructTreeRootKids(structTreeRoot);
+
+ if(this.structTreeRootKids == null)
+ {
+ this.structTreeRootKids = this.createStructTreeRootKids(structTreeRoot);
+ }
+
+ } catch (Exception ex) {
+ logger.error("error", ex);
+ throw new PresentableException(ErrorCode.CANNOT_WRITE_PDF,
+ "error writing structured signature content", ex);
+ }
+ }
+
+ PdfArray createStructTreeRootKids(PdfDictionary structTreeRoot) {
+ PdfArray tmp = new PdfArray();
+ structTreeRoot.put(PdfName.K, tmp);
+ return tmp;
+ }
+
+ /**
+ * Create struct data for main signature block
+ * @throws PresentableException
+ */
+ void buildSigBlockStructData() throws PresentableException {
+ if (!isTagged) return;
+ try {
+ PdfIndirectReference newStructRef = createStructElem(SIGBLOCK_STRUCT_TYPE, new PdfNumber(
+ sigBlockMcid), getStructTreeRoot().getIndRef());
+
+ // ADD everything at the end because nothing can be written afterwards
+ structTreeRootKids.add(newStructRef);
+ mainParentTreeNumEntry.add(newStructRef);
+
+ stamperImp.markUsed(mainParentTreeNumEntry);
+
+ } catch (Exception ex) {
+ logger.error("error", ex);
+ throw new PresentableException(ErrorCode.CANNOT_WRITE_PDF,
+ "error writing structured signature content", ex);
+ }
+ }
+
+
+ /**
+ * Finish struct data for signblock and it's elements (NOT for the external link and annot!)
+ * @throws PresentableException
+ */
+ void finishMainStructData() throws PresentableException {
+ try {
+ if (isTagged && mainParentTreeNumEntry.getIndRef() == null) {
+ getParentTreeNums().add(
+ stamper.getWriter().addToBody(mainParentTreeNumEntry).getIndirectReference());
+ stamperImp.markUsed(getParentTreeNums());
+ stamperImp.markUsed(getStructTreeRoot().getAsDict(PdfName.PARENTTREE));
+ }
+ } catch (Exception ex) {
+ logger.error("error", ex);
+ throw new PresentableException(ErrorCode.CANNOT_WRITE_PDF,
+ "error writing structured signature content", ex);
+ }
+ }
+
+ /**
+ * Build the structured content for the signature logo (bildmarke). {@link #beginFigureContent(PdfContentByte)} and
+ * {@link #endFigureContent(PdfContentByte)} have to be called before this method to mark the logo in the stream. This
+ * is done implicitly in the modified itext source (see {@link StructContentWriterHolder}).
+ * @param so
+ * @param sigBlockObj
+ * @throws PresentableException
+ */
+ void buildFigureStructData(SignatureObject so, PdfTemplate sigBlockObj) throws PresentableException {
+ try {
+ if (isTagged && isFigureMarked()) {
+
+ PdfDictionary structTreeRoot = getStructTreeRoot();
+ PdfIndirectReference mcrRef = createMcrStructElem(this.figureMcid, sigBlockObj.getIndirectReference());
+ PdfIndirectReference figureRef = createStructElem("Figure", mcrRef,
+ getAltText(so.getSignatureTypeDefinition().getType()), structTreeRoot.getIndRef());
+
+ structTreeRootKids.add(figureRef);
+ mainParentTreeNumEntry.add(figureRef);
+
+ stamperImp.markUsed(structTreeRootKids);
+ stamperImp.markUsed(structTreeRoot);
+ stamperImp.markUsed(mainParentTreeNumEntry);
+
+ }
+
+ } catch (Exception ex) {
+ logger.error("error", ex);
+ throw new PresentableException(ErrorCode.CANNOT_WRITE_PDF,
+ "error writing structured signature content", ex);
+ }
+
+ }
+
+ /**
+ * Build the link annotation for the signature verification link and the structured content accordingly.<br>
+ * The tagging does NOT work if the link is placed in a binary signature replace cell (phlengh for this cell)!!
+ * @param sigBlockObj
+ * @param atp
+ * @throws PresentableException
+ */
+ void buildVerifyLinkStructData(PdfTemplate sigBlockObj, ActualTablePos atp) throws PresentableException {
+ if (!this.isTagged || !this.isLinkMarked() || !isLinkFound()) return;
+
+ try {
+ PdfNumber parentTreeKey = getNewParentTreeKey();
+
+ PdfArray annots = obrainAnnotsFromPage();
+
+ PdfIndirectReference linkAnnotRef = createLinkAnnot(parentTreeKey, atp);
+ annots.add(linkAnnotRef);
+
+ PdfIndirectReference objr = createObjrStructElem(linkAnnotRef);
+ PdfIndirectReference mcr = createMcrStructElem(this.linkMcid, sigBlockObj.getIndirectReference());
+
+ PdfDictionary structTreeRoot = getStructTreeRoot();
+
+ PdfArray linkKids = new PdfArray();
+ PdfIndirectReference linkKidsRef = stamper.getWriter().getPdfIndirectReference();
+
+ PdfIndirectReference linkRef = createStructElem("Link", linkKidsRef, structTreeRoot.getIndRef());
+ linkKids.add(objr);
+
+ PdfIndirectReference span = createStructElem("Span", mcr, linkRef);
+ linkKids.add(span);
+
+ stamper.getWriter().addToBody(linkKids, linkKidsRef);
+ structTreeRootKids.add(linkRef);
+
+ // create new entry in ParentTree
+ PdfArray parentTreeNums = getParentTreeNums();
+ parentTreeNums.add(parentTreeKey);
+ parentTreeNums.add(linkRef);
+
+ stamperImp.markUsed(parentTreeNums);
+ stamperImp.markUsed(structTreeRoot.getAsDict(PdfName.PARENTTREE));
+ stamperImp.markUsed(structTreeRootKids);
+ stamperImp.markUsed(linkKids);
+
+ stamperImp.markUsed(structTreeRoot);
+
+ } catch (IOException e) {
+ logger.error("error", e);
+ throw new PresentableException(ErrorCode.CANNOT_WRITE_PDF,
+ "error writing structured signature content", e);
+ }
+ }
+
+ private boolean isLinkFound() {
+ return this.linkUrlString != null && this.verifyLinkCellPos != null && this.linkPosMap.size() > 0 && this.linkMcid >= 0;
+ }
+
+ /**
+ * Build new StructParent entry for signature annotation.
+ * @return
+ */
+ PdfNumber buildAdobeSigStructParent() {
+ if (this.isTagged) {
+ this.annotationParentTreeKey = getNewParentTreeKey();
+ return annotationParentTreeKey;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Build and write structured content for adobe signature annotation
+ *
+ * @param sigFormField
+ * @param title
+ * @throws PresentableException
+ */
+ void buildAdobeSigStruct(PdfFormField sigFormField, String title) throws PresentableException {
+ if (!isTagged)
+ return;
+ try {
+
+ PdfDictionary root = getStructTreeRoot();
+
+ PdfIndirectReference objrRef = createObjrStructElem(sigFormField.getIndirectReference());
+
+ PdfIndirectReference adobeSigStructRef = createStructElem("Link", objrRef, root.getIndRef());
+
+ PdfArray parentTreeNums = getParentTreeNums();
+ // create new entry in ParentTree
+ parentTreeNums.add(annotationParentTreeKey);
+ parentTreeNums.add(adobeSigStructRef);
+
+ structTreeRootKids.add(adobeSigStructRef);
+ stamperImp.markUsed(structTreeRootKids);
+
+ stamperImp.markUsed(parentTreeNums);
+ stamperImp.markUsed(root.getAsDict(PdfName.PARENTTREE));
+
+ } catch (Exception ex) {
+ logger.error("error", ex);
+ throw new PresentableException(ErrorCode.CANNOT_WRITE_PDF,
+ "error writing structured signature content", ex);
+ }
+
+ }
+
+ /**
+ * Start tag for signature block content stream. Place this before the signature block is written to a content stream.
+ * Call {@link #endSigBlockContent()} afterwards
+ */
+ void beginSigBlockContent() {
+ if (isTagged) {
+ content.getInternalBuffer().append(new PdfName(SIGBLOCK_STRUCT_TYPE).getBytes()).append(" <</MCID ")
+ .append(sigBlockMcid).append(">> BDC").append('\n');
+ }
+ }
+
+ /**
+ * End tag for signature block content stream. Place this after the signature block is written to a content stream
+ */
+ void endSigBlockContent() {
+ if (isTagged) {
+ content.endMarkedContentSequence();
+ }
+ }
+
+ /**
+ * Writes start tag for signature logo marked content sequence.
+ */
+ public void beginFigureContent(PdfContentByte localContent) {
+ if (isTagged) {
+ if (!isFigureMarked()) {
+ this.figureMcid = this.nextMcid++;
+ localContent.getInternalBuffer().append("/Figure <</MCID ").append(this.figureMcid).append(">> BDC\n");
+ } else {
+ logger.warn("cannot tag multiple figures (bildmarken)");
+ }
+ }
+ }
+
+ /**
+ * Writes end tag for signature logo marked content sequence.
+ */
+ public void endFigureContent(PdfContentByte localContent) {
+ if (isTagged && isFigureMarked()) {
+ localContent.endMarkedContentSequence();
+ }
+ }
+
+ /**
+ * Writes start tag for verify link marked content sequence.
+ */
+ public void beginLinkContent(PdfContentByte localContent, String urlString) {
+ // it's called from here com.lowagie.text.pdf.PdfContentByte.showText(String)
+
+ if (isTagged) {
+ if (!isLinkMarked()) {
+ this.linkUrlString = urlString;
+ this.linkMcid = this.nextMcid++;
+ localContent.getInternalBuffer().append("/Span <</MCID ").append(this.linkMcid).append(">> BDC\n");
+ } else {
+ logger.warn("cannot tag multiple verify links");
+ }
+ }
+ }
+
+ /**
+ * Writes end tag for verify link marked content sequence.
+ */
+ public void endLinkContent(PdfContentByte localContent) {
+ if (isTagged && isLinkMarked()) {
+ localContent.endMarkedContentSequence();
+ }
+ }
+
+ /**
+ * Implements {@link StructContentWriter#markPos(Rectangle)}
+ */
+ public void markPos(Rectangle pos) {
+ this.tempMarkedPos = pos;
+ }
+
+ /**
+ * Implements {@link StructContentWriter#storeCurrentPosAsLink()}
+ */
+ public void storeCurrentPosAsLink() {
+ this.verifyLinkCellPos = new Rectangle(this.tempMarkedPos);
+ }
+
+ public void putVal(String key, Object val) {
+ tmpMap.put(key, val);
+ }
+
+ public void storeVals() {
+ linkPosMap = new HashMap(tmpMap);
+ }
+
+ /**
+ * set explicit annotation tab order if missing
+ */
+ private void doAnnoTabOrder() {
+ if (page.getAsName(new PdfName("Tabs")) == null) {
+ page.put(new PdfName("Tabs"), PdfName.S); // set explicit annotation TAB order
+ stamperImp.markUsed(page);
+ }
+ }
+
+ private void checkTagging() {
+ PdfDictionary markDict = stamper.getReader().getCatalog().getAsDict(PdfName.MARKINFO);
+ if (markDict != null) {
+ isTagged = markDict.getAsBoolean(PdfName.MARKED).booleanValue();
+ }
+ if (!isTagged) {
+ logger.debug("input document is not tagged. no structure/wai information is written");
+ }
+ logger.debug("Input is tagged. Writing structure/WAI data.");
+ }
+
+
+
+ private PdfIndirectReference createLinkAnnot(PdfNumber structParentNr, ActualTablePos atp) throws IOException {
+ PdfDictionary linkAnnot = new PdfDictionary();
+
+ PdfDictionary a = new PdfDictionary();
+ a.put(PdfName.S, new PdfName("URI"));
+ a.put(PdfName.TYPE, PdfName.ACTION);
+ a.put(PdfName.URI, new PdfString(this.linkUrlString));
+ linkAnnot.put(PdfName.A, a);
+
+ PdfDictionary bs = new PdfDictionary();
+ bs.put(PdfName.W, new PdfNumber(0));
+ linkAnnot.put(PdfName.BS, bs);
+ linkAnnot.put(PdfName.F, new PdfNumber(4));
+
+ // iText "converts" 0.0f to an integer, therefore we cannot use 0, not nice...
+ //linkAnnot.put(PdfName.RECT, new PdfArray(new float[] {0.01f, 0.01f, 0.01f, 0.01f}));
+ // take cell pos as link pos
+ linkAnnot.put(PdfName.RECT, new PdfArray(calcLinkPos(atp)));
+
+ linkAnnot.put(PdfName.STRUCTPARENT, structParentNr);
+ linkAnnot.put(PdfName.SUBTYPE, PdfName.LINK);
+
+ return stamper.getWriter().addToBody(linkAnnot).getIndirectReference();
+ }
+
+
+ private PdfArray calcLinkPos(ActualTablePos atp) {
+ PdfArray res = new PdfArray();
+
+ float downY = atp.y - atp.height;
+
+ float startX = atp.x + this.verifyLinkCellPos.getLeft();
+ float yLine = getPosMapVal("yLine");
+ float lineHigh = getPosMapVal("maxSize");
+ float lineWidth = getPosMapVal("lineWidth");
+ UrlInTextFinder finder = (UrlInTextFinder) this.linkPosMap.get("urlFinder");
+
+ // maybe one could calc the link pos even more exactly with char width counting
+ // but this should be close enough (see BidiLine.processLine and chunk.getcharwith)
+ float lineCorr = -2;
+ float xCorr = 5;
+ res.add(new PdfNumber(1 + startX + finder.calcLinkPosXStart(lineWidth)));
+ res.add(new PdfNumber(downY + yLine + lineHigh + lineCorr));
+ res.add(new PdfNumber(xCorr + startX + finder.calcLinkPosXEnd(lineWidth)));
+ res.add(new PdfNumber(downY + yLine + lineCorr));
+
+ return res;
+ }
+
+ private float getPosMapVal(String key) {
+ return ((Float) this.linkPosMap.get(key)).floatValue();
+ }
+
+ protected static PdfArray createPdfArrayFromTablePos(ActualTablePos pos) {
+ return new PdfArray( new float[] {pos.x, pos.y, pos.x + pos.width, pos.y - pos.height});
+ }
+
+ private PdfArray obrainAnnotsFromPage() throws IOException {
+ PdfArray annots = this.page.getAsArray(PdfName.ANNOTS);
+ if (annots == null) {
+ annots = new PdfArray();
+ page.put(PdfName.ANNOTS, annots);
+ stamperImp.markUsed(this.page);
+ stamper.getWriter().addToBody(annots);
+ }
+ return annots;
+ }
+
+ private PdfArray obtainStructTreeRootKids(PdfDictionary structTreeRoot) {
+ PdfArray rk = null;
+ PdfObject root_k = structTreeRoot.getDirectObject(PdfName.K);
+ stamperImp.markUsed(root_k);
+ if (root_k instanceof PdfDictionary) {
+ rk = new PdfArray();
+ stamperImp.markUsed(structTreeRootKids);
+ rk.add(root_k.getIndRef());
+ structTreeRoot.put(PdfName.K, structTreeRootKids);
+
+ } else if(root_k != null) { // has to be array
+ rk = (PdfArray) root_k;
+ }
+ return rk;
+ }
+
+ private PdfArray obtainParentTreeEntry(PdfDictionary structTreeRoot, PdfArray parentTreeNums,
+ PdfNumber structParentsNr, PdfTemplate sigBlockObj) {
+ int numsIdx = -1;
+ PdfArray parentTreeEntry = null;
+
+ if (structParentsNr == null) { // no StructParents entry yet, make new one and add new parenttree entry
+ PdfNumber parentTreeKey = null;
+ parentTreeNextKey = structTreeRoot.getAsNumber(PARENTTREENEXTKEY); // read next proposed key
+ if (parentTreeNextKey == null) { // this can be null if a non-perfect pdf creator was at work
+ // find the next key by counting
+ int nextI = ((int) parentTreeNums.size() / 2); // know the "Number Trees" data structure from pdf-ref
+ this.parentTreeNextKey = new PdfNumber(nextI);
+ structTreeRoot.put(PARENTTREENEXTKEY, this.parentTreeNextKey); // write ParentTreeNextKey entry
+ }
+
+ parentTreeKey = new PdfNumber(parentTreeNextKey.intValue());
+ parentTreeNextKey.increment();
+ page.put(PdfName.STRUCTPARENTS, parentTreeKey); // write /StructParents entry to page
+ structParentsNr = parentTreeKey;
+
+ stamperImp.markUsed(page);
+ // create new entry in ParentTree
+ parentTreeNums.add(parentTreeKey);
+ parentTreeEntry = new PdfArray();
+ numsIdx = parentTreeNums.size() - 1;
+
+ } else { // structparents entry already available, find parenttree entry
+ //parentTreeKey = structParentsNr;
+ parentTreeNextKey = structTreeRoot.getAsNumber(PARENTTREENEXTKEY); // read next proposed key
+ if (parentTreeNextKey == null) { // this can be null if a non-perfact pdf creator was at work
+ // find the next key by counting
+ int nextI = 0;
+ if (parentTreeNums != null) {
+ nextI = ((int) parentTreeNums.size() / 2);
+ }
+ this.parentTreeNextKey = new PdfNumber(nextI);
+ structTreeRoot.put(PARENTTREENEXTKEY, this.parentTreeNextKey);
+ }
+ }
+
+ // add Structparents entry to xobject content stream
+ sigBlockObj.addAttribute(PdfName.STRUCTPARENTS, structParentsNr);
+
+ // find my structParentEntry
+ if (numsIdx < 0) {
+ // it's a weird data structure: "number tree", see pdf reference if you really want to understand
+
+ // if the array has no gaps it is easy:
+ numsIdx = structParentsNr.intValue() * 2;
+ if (parentTreeNums.getAsNumber(numsIdx).intValue() != structParentsNr.intValue()) { // there seem to be gaps
+ for (numsIdx = 0; numsIdx < parentTreeNums.size(); numsIdx += 2) { // search manually
+ if (parentTreeNums.getAsNumber(numsIdx).intValue() == structParentsNr.intValue()) {
+ break;
+ }
+ }
+ }
+ numsIdx += 1;
+ }
+ if (parentTreeEntry == null) {
+ parentTreeEntry = parentTreeNums.getAsArray(numsIdx);
+ }
+ return parentTreeEntry;
+ }
+
+// private PdfIndirectReference createStructElem(String structType, PdfObject kid) throws IOException {
+// return createStructElem(structType, kid, null);
+// }
+
+ private PdfIndirectReference createStructElem(String structType, PdfObject kid, PdfIndirectReference parentRef) throws IOException {
+ return createStructElem(structType, kid, null, parentRef);
+ }
+
+ private PdfIndirectReference createStructElem(String structType, PdfObject kid, String altText,
+ PdfIndirectReference parentRef) throws IOException {
+
+ PdfDictionary newStruct = new PdfDictionary();
+ newStruct.put(PdfName.S, new PdfName(structType));
+ //newStruct.put(PdfName.T, new PdfString("PDF-AS Signaturblock"));// eher nicht
+ if (parentRef != null) {
+ newStruct.put(PdfName.P, parentRef);
+ }
+ newStruct.put(PdfName.TYPE, new PdfName("StructElem"));
+
+ newStruct.put(PdfName.PG, page.getIndRef());
+ if (altText != null) {
+ newStruct.put(PdfName.ALT, new PdfString(altText));
+ }
+ // newStruct.put(PdfName.ALT, new PdfString(getAltText(so.getSignatureTypeDefinition().getType())));
+ //newStruct.put(PdfName.K, new PdfNumber(nextMcid));
+ newStruct.put(PdfName.K, kid);
+
+ return stamper.getWriter().addToBody(newStruct).getIndirectReference();
+ }
+
+ private boolean isFigureMarked() {
+ return this.figureMcid > -1;
+ }
+
+ private boolean isLinkMarked() {
+ return this.linkMcid > -1;
+ }
+
+
+ private PdfNumber getNewParentTreeKey() {
+ // new parent tree entry
+ if (parentTreeNextKey == null) {
+ parentTreeNextKey = getStructTreeRoot().getAsNumber(PARENTTREENEXTKEY); // read next proposed key
+ }
+ PdfNumber res = new PdfNumber(parentTreeNextKey.intValue());
+ parentTreeNextKey.increment();
+ return res;
+ }
+
+
+ private PdfIndirectReference createObjrStructElem(PdfIndirectReference objRef) throws IOException {
+ PdfDictionary objr = new PdfDictionary();
+ objr.put(PdfName.TYPE, new PdfName("OBJR"));
+ objr.put(PdfName.PG, page.getIndRef());
+ objr.put(new PdfName("Obj"), objRef);
+
+ return stamper.getWriter().addToBody(objr).getIndirectReference();
+ }
+
+ private PdfIndirectReference createMcrStructElem(int mcid, PdfIndirectReference streamRef) throws IOException {
+ PdfDictionary objr = new PdfDictionary();
+ objr.put(PdfName.TYPE, new PdfName("MCR"));
+ objr.put(PdfName.PG, page.getIndRef());
+ objr.put(PdfName.MCID, new PdfNumber(mcid));
+ objr.put(new PdfName("Stm"), streamRef);
+
+ return stamper.getWriter().addToBody(objr).getIndirectReference();
+ }
+
+ private PdfArray getParentTreeNums() {
+ return getStructTreeRoot().getAsDict(PdfName.PARENTTREE).getAsArray(PdfName.NUMS);
+ }
+
+ private PdfDictionary getStructTreeRoot() {
+ return stamper.getReader().getCatalog().getAsDict(PdfName.STRUCTTREEROOT);
+ }
+
+ private static String getAltText(String sigProfile) {
+ return AdobeSignatureHelper.getDefaultableConfigProperty(sigProfile, ALT_TEXT_CONF_KEY, ALT_TEXT_DEFAULT);
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/TablePos.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/TablePos.java
new file mode 100644
index 0000000..53d6609
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/TablePos.java
@@ -0,0 +1,262 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: TablePos.java,v 1.1 2006/08/25 17:10:08 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.pdf;
+
+import java.io.Serializable;
+
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException;
+
+/**
+ * Class that holds the exact position where the table should be written to the
+ * document.
+ *
+ * @author wprinz
+ * @author mruhmer
+ */
+public class TablePos implements Serializable
+{
+
+ /**
+ * SVUID.
+ */
+ private static final long serialVersionUID = -5299027706623518059L;
+
+ /**
+ * The page on which the block should be displayed.
+ *
+ */
+ private int page = 0;
+
+ /**
+ * The x position.
+ */
+ private float pos_x = 0.0f;
+
+ /**
+ * The y position.
+ */
+ private float pos_y = 0.0f;
+
+ /**
+ * The width of the block.
+ */
+ private float width = 0.0f;
+ /**
+ * The top y position of the footer line.
+ */
+ public float footer_line = 0.0f;
+
+ /**
+ * The y position.
+ */
+ public String myposstring = "";
+
+ private boolean newpage = false;
+ private boolean autoX = true;
+ private boolean autoY = true;
+ private boolean autoW = true;
+ private boolean autoP = true;
+
+ public boolean isXauto()
+ {
+ return this.autoX;
+ }
+ public boolean isYauto()
+ {
+ return this.autoY;
+ }
+ public boolean isWauto()
+ {
+ return this.autoW;
+ }
+ public boolean isPauto()
+ {
+ return this.autoP;
+ }
+ public boolean isNewPage()
+ {
+ return this.newpage;
+ }
+ public int getPage()
+ {
+ return this.page;
+ }
+ public float getFooterLine()
+ {
+ //ignore if newpage and y is not auto
+ if (!this.autoY || this.newpage)
+ {
+ return 0.0f;
+ }
+ return this.footer_line;
+ }
+ public float getPosX()
+ {
+ return this.pos_x;
+ }
+ public float getPosY()
+ {
+ return this.pos_y;
+ }
+ public float getWidth()
+ {
+ return this.width;
+ }
+ public TablePos()
+ {
+ //nothing to do --> default
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param pos_string The pos instruction.
+ * format : [x:x_algo];[y:y_algo];[w:w_algo][p:p_algo];[f:f_algo]
+ * x_algo:='auto' ... automatic positioning x
+ * floatvalue ... absolute x
+ * y_algo:='auto' ... automatic positioning y
+ * floatvalue ... absolute y
+ * w_algo:='auto' ... automatic width
+ * floatvalue ... absolute width
+ * p_algo:='auto' ... automatic last page
+ * 'new' ... new page
+ * intvalue ... pagenumber
+ * f_algo floatvalue ... consider footerline (only if y_algo is auto and p_algo is not 'new')
+ * @throws PDFDocumentException
+ */
+ public TablePos(String pos_string) throws PDFDocumentException
+ {
+ //parse posstring and throw exception
+ //[x:x_algo];[y:y_algo];[w:w_algo][p:p_algo];[f:f_algo]
+
+ String[] strs = pos_string.split(";");
+ try
+ {
+ for (int cmds = 0;cmds<strs.length;cmds++)
+ {
+
+ String cmd_kvstring = strs[cmds];
+ String[] cmd_kv = cmd_kvstring.split(":");
+ if (cmd_kv.length != 2)
+ {
+ throw new PDFDocumentException(ErrorCode.INVALID_SIGNATURE_POSITION, "Pos string (=" + pos_string + ") is invalid.");
+ }
+ String cmdstr = cmd_kv[0];
+ if (cmdstr.length() != 1)
+ {
+ throw new PDFDocumentException(ErrorCode.INVALID_SIGNATURE_POSITION, "Pos string (=" + pos_string + ") is invalid.");
+ }
+ char command = cmdstr.charAt(0);
+ String commandval= cmd_kv[1];
+ switch (command)
+ {
+ case 'x': {
+ if (!commandval.equalsIgnoreCase("auto"))
+ {
+ float xval= Float.parseFloat(commandval);
+ if (xval<0)
+ {
+ throw new PDFDocumentException(228, "Pos string (x:" + xval + ") is invalid.");
+ }
+ this.pos_x = xval;
+ this.autoX = false;
+ }
+ break;
+ }
+ case 'y': {
+ if (!commandval.equalsIgnoreCase("auto"))
+ {
+ float yval= Float.parseFloat(commandval);
+ if (yval<0)
+ {
+ throw new PDFDocumentException(229, "Pos string (y:" + yval + ") is invalid.");
+ }
+ this.pos_y = yval;
+ this.autoY = false;
+ }
+ break;
+ }
+ case 'w': {
+ if (!commandval.equalsIgnoreCase("auto"))
+ {
+ float wval= Float.parseFloat(commandval);
+ if (wval<=0)
+ {
+ throw new PDFDocumentException(226, "pos.width (w:" + wval + ") must not be lower or equal 0.");
+ }
+ this.width = wval;
+ this.autoW = false;
+ }
+ break;
+ }
+ case 'p': {
+ if (!commandval.equalsIgnoreCase("auto"))
+ {
+ if (commandval.equalsIgnoreCase("new"))
+ {
+ this.newpage = true;
+ }
+ else
+ {
+ int pval = Integer.parseInt(commandval);
+ if (pval<1)
+ {
+ throw new PDFDocumentException(225, "Page (p:" + pval + ") must not be lower than 1.");
+ }
+ this.page = pval;
+ this.autoP = false;
+ }
+ }
+ break;
+ }
+ case 'f': {
+ float flval=Float.parseFloat(commandval);
+ if (flval<0)
+ {
+ throw new PDFDocumentException(ErrorCode.INVALID_SIGNATURE_POSITION, "Pos string (=" + pos_string + ") is invalid.");
+ }
+ this.footer_line = flval;
+ break;
+ }
+ default : {
+ throw new PDFDocumentException(ErrorCode.INVALID_SIGNATURE_POSITION, "Pos string (=" + pos_string + ") is invalid.");
+ }
+ }
+ }
+ this.myposstring=pos_string;
+ }
+ catch (NumberFormatException e)
+ {
+ throw new PDFDocumentException(ErrorCode.INVALID_SIGNATURE_POSITION, "Pos string (=" + pos_string + ") cannot be parsed.");
+ }
+ }
+ public String toString()
+ {
+ String thatsme = "cmd:"+this.myposstring+" pos_x:"+this.pos_x+" pos_y:"+this.pos_y+" page:"+this.page+" width:"+this.width+" footer:"+this.footer_line+"\n "+" autoX:"+this.autoX+" autoY:"+this.autoY+" autoW:"+this.autoW+" Newpage:"+this.newpage+" autoP:"+this.autoP;
+ return thatsme;
+ }
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/TextualSignature.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/TextualSignature.java
new file mode 100644
index 0000000..35a0768
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/TextualSignature.java
@@ -0,0 +1,282 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: TextualSignature.java,v 1.4 2006/10/31 08:12:45 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.pdf;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.log4j.Logger;
+import org.pdfbox.pdfparser.PDFParser;
+import org.pdfbox.pdmodel.PDDocument;
+import org.pdfbox.util.PDFTextStripper;
+
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.gv.egiz.pdfas.framework.input.PdfDataSource;
+import at.gv.egiz.pdfas.performance.PerformanceCounters;
+import at.gv.egiz.pdfas.utils.PDFASUtils;
+import at.knowcenter.wag.egov.egiz.cfg.ConfigLogger;
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException;
+
+import com.lowagie.text.Document;
+import com.lowagie.text.DocumentException;
+import com.lowagie.text.Rectangle;
+import com.lowagie.text.pdf.PdfContentByte;
+import com.lowagie.text.pdf.PdfImportedPage;
+import com.lowagie.text.pdf.PdfReader;
+import com.lowagie.text.pdf.PdfWriter;
+
+/**
+ * Contains helper function for textual signatures.
+ *
+ * @author wprinz
+ */
+public class TextualSignature
+{
+ /**
+ * The logger definition.
+ */
+ private static final Logger logger_ = ConfigLogger.getLogger(TextualSignature.class);
+
+ /**
+ * Extracts the document text from a given pdf.
+ *
+ * @param pdf_stream
+ * The pdf_input stream.
+ * @return Returns the extracted document text.
+ * @throws PDFDocumentException
+ * @throws TextExtractionException
+ * Forwarded exception.
+ */
+ public static String extractTextTextual(PdfDataSource pdfDataSource, String encoding) throws PDFDocumentException
+ {
+ PerformanceCounters.textExtractions.increment();
+
+ try
+ {
+ int first_page_rotation = 0;
+ // logger_.debug("====================================================");
+ // logger_.debug("extractText:");
+
+ // For text extraction, create a temporary object with iText just as the
+ // one
+ // created
+ // when being signed, but of course without adding content.
+
+
+ // byte[] bytes = normalizePDF(pdf_stream);
+ //iText
+
+ byte [] pdf_data = pdfDataSource.getAsByteArray();
+ PdfReader reader = new PdfReader(pdf_data);
+ PDFASUtils.checkReaderPermissions(reader);
+ //pdf_stream.close();
+
+ // PERF: PDF normalization needs byte array - this is costy
+ ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
+
+ // For some reason the Reader -> ImportPage -> Writer mechanism produces
+ // problems en mass.
+ // The text extractor may not be able to extract proper text from
+ // documents
+ // created with
+ // this method (although it works when a Table is appended)... very
+ // fragile.
+
+ Document document = new Document();
+
+ PdfWriter writer = PdfWriter.getInstance(document, baos);
+ document.open();
+
+ PdfContentByte cb = writer.getDirectContent();
+ for (int page_num = 1; page_num <= reader.getNumberOfPages(); page_num++)
+ {
+ //Rectangle new_size = reader.getPageSize(page_num);
+ //logger_.info("PageSize with no rotaion: Pagenr:"+page_num+" Size: "+new_size);
+ //document.setPageSize(new_size);
+ Rectangle new_size_withrot =reader.getPageSizeWithRotation(page_num);
+ if (page_num == 1)
+ {
+ //setFirstPageRotation(new_size_withrot.getRotation());
+ first_page_rotation = new_size_withrot.getRotation();
+ //logger_.info("iText first_page_rotation="+new_size_withrot.getRotation());
+ }
+ //logger_.info("iText set PageSize of page:"+page_num+" to: "+new_size_withrot);
+ //document.setPageSize(new_size);
+ document.setPageSize(new_size_withrot);
+ document.newPage();
+
+ PdfImportedPage page = writer.getImportedPage(reader, page_num);
+ // note that this will add an xobject form to the doc.
+ // the xobject form contains the content of the page.
+ cb.addTemplate(page, 0, 0);
+
+ // wprinz: debugging
+ // cb.beginText();
+ // cb.setFontAndSize(BaseFont.createFont(BaseFont.HELVETICA,
+ // BaseFont.CP1252, BaseFont.NOT_EMBEDDED), 14);
+ // cb.showText("page " + page_num);
+ // cb.endText();
+ // wprinz: end debugging
+ }
+
+ document.close();
+
+ // for (int i = 1; i <= reader.getNumberOfPages(); i++)
+ // {
+ // Rectangle rect = reader.getBoxSize(i, "bleed");
+ // logger_.debug("rect[" + i + "] = " + rect);
+ // }
+
+ baos.close();
+ byte[] normalizedPDF = baos.toByteArray();
+
+ ByteArrayInputStream bais = new ByteArrayInputStream(normalizedPDF);
+ //PDFBox-parser
+ PDFParser parser = new PDFParser(bais);
+ File temporary_dir = SettingsReader.getTemporaryDirectory();
+ //logger_.info("temporary_dir="+temporary_dir.getAbsolutePath());
+ parser.setTempDirectory(temporary_dir);
+ parser.parse();
+
+ PDDocument doc = parser.getPDDocument();
+ //System.out.println("pdfBox.getNumberOfPages()"+doc.getNumberOfPages());
+
+ PDFTextStripper stripper = new PDFTextStripper();
+ stripper.setSortByPosition(false);
+ stripper.setGetFirstPageRotationFromThis(true);
+ stripper.setFirstPageRotation(first_page_rotation);
+
+ // stripper.setStartPage(4);
+ // stripper.setEndPage(4);
+ logger_.debug("TextualSignator extractTextTextual: Begin stripping text");
+ String text;
+ try {
+ text = stripper.getText(doc, encoding);
+ } catch (Exception e) {
+ throw new PDFDocumentException(ErrorCode.TEXT_EXTRACTION_EXCEPTION, "Unable to extract textual content.", e);
+ }
+ logger_.debug("TextualSignator extractTextTextual: Stripping text ended");
+
+ doc.close();
+ //logger_.debug("TextualSignator extractTextTextual="+text);
+ return text;
+
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw new PDFDocumentException(ErrorCode.DOCUMENT_CANNOT_BE_READ, e);
+ }
+ catch (IOException e)
+ {
+ throw new PDFDocumentException(ErrorCode.DOCUMENT_CANNOT_BE_READ, e);
+ }
+ catch (DocumentException e)
+ {
+ throw new PDFDocumentException(ErrorCode.DOCUMENT_CANNOT_BE_READ, e);
+ }
+ }
+
+ /**
+ * Normalizes a given binary PDF to a version PDFbox can handle correctly.
+ *
+ * <p>
+ * PDFbox has serious problems with documents that use incremental updates or
+ * XObject forms. Therefor use this to remove incremental updates and create a
+ * streamlined document.
+ * </p>
+ *
+ * <p>
+ * Note that this has nothing to do with text normalization. It just unifies
+ * the PDF documents that are fed into PDFbox for text extraction and page
+ * length determination.
+ * </p>
+ *
+ * @param input_pdf
+ * The input pdf to be normalized.
+ * @return Returns the normalized pdf.
+ * @throws IOException
+ * @throws DocumentException
+ * @throws PDFDocumentException
+ */
+ public static byte[] normalizePDF(PdfDataSource pdfDataSource) throws IOException, DocumentException, PDFDocumentException
+ {
+ //iText
+ byte [] pdf_data = pdfDataSource.getAsByteArray();
+ PdfReader reader = new PdfReader(pdf_data);
+ PDFASUtils.checkReaderPermissions(reader);
+ //input_pdf.close();
+
+ // PERF: PDF Normalization needs byte array
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ // For some reason the Reader -> ImportPage -> Writer mechanism produces
+ // problems en mass.
+ // The text extractor may not be able to extract proper text from
+ // documents
+ // created with
+ // this method (although it works when a Table is appended)... very
+ // fragile.
+
+ Document document = new Document();
+
+ PdfWriter writer = PdfWriter.getInstance(document, baos);
+ document.open();
+
+ PdfContentByte cb = writer.getDirectContent();
+ for (int page_num = 1; page_num <= reader.getNumberOfPages(); page_num++)
+ {
+ Rectangle new_size_withrot =reader.getPageSizeWithRotation(page_num);
+ document.setPageSize(new_size_withrot);
+ document.newPage();
+ PdfImportedPage page = writer.getImportedPage(reader, page_num);
+ // note that this will add an xobject form to the doc.
+ // the xobject form contains the content of the page.
+ cb.addTemplate(page, 0, 0);
+
+ // wprinz: debugging
+ // cb.beginText();
+ // cb.setFontAndSize(BaseFont.createFont(BaseFont.HELVETICA,
+ // BaseFont.CP1252, BaseFont.NOT_EMBEDDED), 14);
+ // cb.showText("page " + page_num);
+ // cb.endText();
+ // wprinz: end debugging
+ }
+
+ document.close();
+
+ // for (int i = 1; i <= reader.getNumberOfPages(); i++)
+ // {
+ // Rectangle rect = reader.getBoxSize(i, "bleed");
+ // logger_.debug("rect[" + i + "] = " + rect);
+ // }
+
+ baos.close();
+ byte[] normalizedPDF = baos.toByteArray();
+ return normalizedPDF;
+ }
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/TextualSignatureHolder.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/TextualSignatureHolder.java
new file mode 100644
index 0000000..165de05
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/TextualSignatureHolder.java
@@ -0,0 +1,153 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: TextualSignatureHolder.java,v 1.1 2006/10/11 07:58:17 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.pdf;
+
+import java.io.Serializable;
+import java.util.Iterator;
+import java.util.List;
+
+import at.gv.egiz.pdfas.framework.input.DataSource;
+import at.gv.egiz.pdfas.framework.input.TextDataSource;
+import at.gv.egiz.pdfas.impl.input.TextDataSourceImpl;
+import at.knowcenter.wag.egov.egiz.sig.SignatureObject;
+
+/**
+ * Data structure that holds the information of one signature block, which is
+ * the signed/signable text and the corresponding SignatureObject.
+ *
+ * @author wprinz
+ */
+public class TextualSignatureHolder implements Serializable, SignatureHolder
+{
+
+ /**
+ * SVUID.
+ */
+ private static final long serialVersionUID = -7208103904479272760L;
+
+// /**
+// * The signed text of this object.
+// *
+// * <p>
+// * This is the value that will be signed by the Connector.
+// * </p>
+// */
+// private String signed_text = null;
+
+ /**
+ * The signature object.
+ */
+ private SignatureObject signature_object = null;
+
+ private TextDataSource textDataSource = null;
+
+ private int uiBlockEndPos = 0;
+
+ public TextualSignatureHolder(String text, SignatureObject so)
+ {
+ //this.signed_text = text;
+ this.signature_object = so;
+ this.textDataSource = new TextDataSourceImpl(text);
+ }
+
+ public TextualSignatureHolder(TextDataSource text, SignatureObject so)
+ {
+ //this.signed_text = text;
+ this.signature_object = so;
+ this.textDataSource = text;
+ }
+
+// /**
+// * @see at.knowcenter.wag.egov.egiz.pdf.SignatureHolder#getSignedText()
+// */
+// public String getSignedText()
+// {
+// return this.signed_text;
+// }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.pdf.SignatureHolder#getSignatureObject()
+ */
+ public SignatureObject getSignatureObject()
+ {
+ return this.signature_object;
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.pdf.SignatureHolder#getDataSource()
+ */
+ public DataSource getDataSource()
+ {
+ return this.textDataSource;
+ }
+
+ /**
+ * This is used to replace the DataSource.
+ *
+ * <p>
+ * After processing the text, data sources containing large texts are usually replaced by a FileBased ones to save memory.
+ * </p>
+ *
+ * @param tds
+ */
+ public void exchangeDataSource(TextDataSource tds)
+ {
+ this.textDataSource = tds;
+ }
+
+ /**
+ * This is just a shortcut to getDataSource().getText()
+ * @return Returns the text of this data source.
+ */
+ public String getSignedText()
+ {
+ return this.textDataSource.getText();
+ }
+
+ public int getUiBlockEndPos() {
+ return this.uiBlockEndPos;
+ }
+
+ public void setUiBlockEndPos(int uiBlockEndPos) {
+ this.uiBlockEndPos = uiBlockEndPos;
+ }
+
+ public static void mulitSetUiBlockEndPos(List signatureHolders, int uiBlockEndPos) {
+ for (Iterator it = signatureHolders.iterator(); it.hasNext();) {
+ SignatureHolder sh = (SignatureHolder) it.next();
+ trySetUiBlockEndPos(sh, uiBlockEndPos);
+ }
+ }
+
+ public static void trySetUiBlockEndPos(SignatureHolder sh, int uiBlockEndPos ) {
+ if (sh != null && sh instanceof TextualSignatureHolder) {
+ ((TextualSignatureHolder)sh).setUiBlockEndPos(uiBlockEndPos);
+ }
+ }
+
+
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/Utils.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/Utils.java
new file mode 100644
index 0000000..519d0b5
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/Utils.java
@@ -0,0 +1,124 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: Utils.java,v 1.3 2006/10/31 08:13:02 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.pdf;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+/**
+ * Abstract class that contains helpful utility functions used by the digital
+ * signatures.
+ *
+ * @author wprinz
+ */
+public abstract class Utils
+{
+
+ /**
+ * Extracts the pure content text from a given content stream.
+ *
+ * <p>
+ * The pure content text is just an assembly of all strings that occur within the content stream in
+ * stream order.
+ * Each of these strings will be set on a new line.
+ * </p>
+ *
+ * @param stream_bytes The content stream.
+ * @return Returns the extracted string.
+ * @throws IOException Forwarded exception.
+ */
+ public static String extractPureTextFromContentStream(
+ final byte[] stream_bytes) throws IOException
+ {
+
+ // logger_.debug("stream_bytes:");
+ // logger_.debug(new String(stream_bytes, "US-ASCII"));
+ // logger_.debug(":end of stream_bytes");
+
+ final byte OPEN = '(';
+ final byte CLOSE = ')';
+
+ StringWriter strwrtr = new StringWriter();
+ PrintWriter printer = new PrintWriter(strwrtr);
+ int open_index = -1;
+ int close_index = -1;
+ for (int i = 0; i < stream_bytes.length; i++)
+ {
+ if (stream_bytes[i] == OPEN)
+ {
+ open_index = i;
+ continue;
+ }
+ if (stream_bytes[i] == CLOSE)
+ {
+ close_index = i;
+
+ // logger_.debug("open = " + open_index + ", close = " +
+ // close_index);
+
+ int len = close_index - open_index - 1;
+ // logger_.debug("len = " + len);
+
+ byte[] bytes = new byte[len];
+ System.arraycopy(stream_bytes, open_index + 1, bytes, 0, len);
+
+ String str = new String(bytes, "ISO-8859-1");
+ // logger_.debug("string = " + str);
+
+ printer.println(str);
+
+ continue;
+ }
+ }
+ strwrtr.close();
+ String signature_text = new String(strwrtr.getBuffer());
+ // logger_.debug(signature_text);
+
+ return signature_text;
+ }
+
+ public static int max(int[] ints) {
+ int max = Integer.MIN_VALUE;
+ for (int i = 0; i < ints.length; i++) {
+ if (ints[i] > max) {
+ max = ints[i];
+ }
+ }
+ return max;
+ }
+
+ public static String resolveCanonical(String path) {
+ File file = new File(path);
+ try {
+ return file.getCanonicalPath();
+ } catch (IOException e) {
+ return file.getPath();
+ }
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/Connector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/Connector.java
new file mode 100644
index 0000000..f70f19c
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/Connector.java
@@ -0,0 +1,67 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: Connector.java,v 1.3 2006/10/11 07:54:03 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.sig;
+
+import at.knowcenter.wag.egov.egiz.exceptions.SignatureException;
+
+/**
+ * The basic interface for all connectors.
+ *
+ * @author wprinz
+ */
+public interface Connector
+{
+
+ /**
+ * Performs a sign.
+ *
+ * @param sig_type
+ * The signature type/profile.
+ * @param user_name
+ * The user name for user logging.
+ * @param text_to_sign
+ * The text to be signed.
+ * @return Returns the signed SignatureObject.
+ * @throws SignatureException
+ * F.e.
+ */
+ public SignatureObject doSign(String sig_type, String user_name,
+ String text_to_sign) throws SignatureException;
+
+ /**
+ * Performs a verify.
+ *
+ * @param signed_text
+ * The signed text to be verified.
+ * @param sig_obj
+ * The Signature object.
+ * @return Returns the SignatureResponse.
+ * @throws SignatureException
+ * F.e.
+ */
+ public SignatureResponse doVerify(String signed_text, SignatureObject sig_obj) throws SignatureException;
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/ConnectorFactory.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/ConnectorFactory.java
new file mode 100644
index 0000000..fa019b9
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/ConnectorFactory.java
@@ -0,0 +1,372 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: ConnectorFactory.java,v 1.4 2006/10/31 08:18:12 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.sig;
+
+import java.lang.reflect.Field;
+
+import org.apache.log4j.Logger;
+
+import at.gv.egiz.pdfas.api.commons.Constants;
+import at.knowcenter.wag.egov.egiz.cfg.ConfigLogger;
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorFactoryException;
+import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
+import at.knowcenter.wag.egov.egiz.sig.connectors.A1Connector;
+import at.knowcenter.wag.egov.egiz.sig.connectors.BKUConnector;
+import at.knowcenter.wag.egov.egiz.sig.connectors.ConnectorConfigurationKeys;
+import at.knowcenter.wag.egov.egiz.sig.connectors.MOAConnector;
+import at.knowcenter.wag.egov.egiz.sig.connectors.mocca.LocRefDetachedMOCCAConnector;
+
+/**
+ * This is a factory for creating the appropriate connector according to the
+ * connector identifier.
+ *
+ * @deprecated this code is far too complicated
+ *
+ * @see at.knowcenter.wag.egov.egiz.sig.ConnectorInformation
+ * @author wprinz
+ */
+public abstract class ConnectorFactory
+{
+ /**
+ * The name of the field that holds the Connector implementation's unique
+ * identifier.
+ *
+ * <p>
+ * This must be a public static final String on the Connector implementation
+ * class.
+ * </p>
+ */
+ protected static final String CONNECTOR_INFORMATION_FIELD_NAME = "CONNECTOR_INFORMATION";
+
+ /**
+ * The list of available Connector implementations.
+ *
+ * <p>
+ * Note that this could also be generated dynamically from a config file,
+ * preferably enveloped by a Singleton.
+ * </p>
+ */
+ protected static Class[] AVAILABLE_CONNECTORS = { MOAConnector.class,
+ BKUConnector.class, A1Connector.class };
+
+ /**
+ * The logger definition.
+ */
+ private static final Logger logger_ = ConfigLogger.getLogger(ConnectorFactory.class);
+
+
+
+ /**
+ * Retrieves the ConnectorInformation from the connector Class.
+ *
+ * @param connector_class
+ * The connector Class.
+ * @return Returns the ConnectorInformation.
+ * @throws IllegalArgumentException
+ * F.e.
+ * @throws IllegalAccessException
+ * F.e.
+ * @throws SecurityException
+ * F.e.
+ * @throws NoSuchFieldException
+ * F.e.
+ */
+ protected static ConnectorInformation getConnectorInformationFromClass(
+ Class connector_class) throws IllegalArgumentException, IllegalAccessException, SecurityException, NoSuchFieldException
+ {
+ Field type_field = connector_class.getField(CONNECTOR_INFORMATION_FIELD_NAME);
+ ConnectorInformation connector_information = (ConnectorInformation) type_field.get(null);
+ return connector_information;
+ }
+
+ /**
+ * Gathers the ConnectorInformation objects of all registered connectors.
+ *
+ * <p>
+ * This is used by the user interface to provide a list of all available
+ * connectors.
+ * </p>
+ *
+ * @return Returns the ConnectorInformation objects.
+ * @throws ConnectorFactoryException
+ * F.e.
+ */
+ public static ConnectorInformation[] getConnectorInformationArray() throws ConnectorFactoryException
+ {
+ ConnectorInformation[] coninf = new ConnectorInformation[AVAILABLE_CONNECTORS.length];
+
+ for (int i = 0; i < coninf.length; i++)
+ {
+ try
+ {
+ coninf[i] = getConnectorInformationFromClass(AVAILABLE_CONNECTORS[i]);
+ }
+ catch (Exception e)
+ {
+ throw new ConnectorFactoryException(e);
+ }
+ }
+
+ return coninf;
+ }
+
+ /**
+ * Retrieves the connector Class belonging to the connector id.
+ *
+ * @param connector_identifier
+ * The connector id.
+ * @return Returns the corresponding connector class.
+ * @throws ConnectorFactoryException
+ * Thrown, if the id is invalid.
+ */
+ protected static Class getConnectorClass(String connector_identifier) throws ConnectorFactoryException
+ {
+ ConnectorInformation[] conids = getConnectorInformationArray();
+ for (int i = 0; i < conids.length; i++)
+ {
+ String connector_id = conids[i].getIdentifier();
+
+ if (connector_id.equals(connector_identifier))
+ {
+ Class conn_class = AVAILABLE_CONNECTORS[i];
+
+ return conn_class;
+ }
+ }
+
+ throw new ConnectorFactoryException("The connector '" + connector_identifier + "' couldn't be found in the list of available connectors.");
+ }
+
+ /**
+ * Creates a new connector given by the connector_identifier.
+ *
+ * @param connector_identifier
+ * The connector identifier of the new connector.
+ * @return Returns the new connector.
+ * @throws ConnectorFactoryException
+ * F.e.
+ */
+ public static Connector createConnector(String connector_identifier) throws ConnectorFactoryException
+ {
+
+ Class conn_class = getConnectorClass(connector_identifier);
+
+ try
+ {
+ Connector connector_obj = (Connector) conn_class.newInstance();
+ return connector_obj;
+ }
+ catch (Exception e)
+ {
+ throw new ConnectorFactoryException(e);
+ }
+ }
+
+ /**
+ * Tells, if the given connector identifier is valid.
+ *
+ * @param connector_identifier
+ * The connector identifier.
+ * @return Returns true, if the identifier is valid, false otherwise.
+ * @throws ConnectorFactoryException
+ * F.e.
+ */
+ public static boolean isValidConnectorIdentifier(String connector_identifier) throws ConnectorFactoryException
+ {
+ ConnectorInformation[] conids = getConnectorInformationArray();
+ for (int i = 0; i < conids.length; i++)
+ {
+ if (conids[i].getIdentifier().equals(connector_identifier))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Retrieves the availability of the connector from the flags specified in the
+ * config file.
+ *
+ * @param connector_identifier
+ * The connector.
+ * @param availability_key
+ * The key of the availability flag to be retrieved.
+ * @param default_value
+ * The default value to be used if the flag is not set in the config
+ * file.
+ * @return Returns true, if the flag was set to true, false, if the flag was
+ * set otherwise, or the default_value if the flag wasn't set at all.
+ * @throws ConnectorFactoryException
+ * Thrown, if the connector is invalid.
+ */
+ protected static boolean getAvailabilityUsingDefault(String connector_identifier,
+ String availability_key, boolean default_value) throws ConnectorFactoryException
+ {
+ if (!isValidConnectorIdentifier(connector_identifier))
+ {
+ throw new ConnectorFactoryException("The connector '" + connector_identifier + "' couldn't be found in the list of available connectors.");
+ }
+
+ SettingsReader settings_ = null;
+ try
+ {
+ settings_ = SettingsReader.getInstance();
+ }
+ catch (SettingsException e)
+ {
+ String log_message = "Can not load signature settings. Cause:\n" + e.getMessage();
+ logger_.error(log_message);
+ throw new RuntimeException(e);
+ }
+
+ String value = settings_.getValueFromKey(connector_identifier + "." + availability_key);
+ if (value == null)
+ {
+ return default_value;
+ }
+ return value.equals("true");
+ }
+
+ /**
+ * Tells, if the connector is available for being used in the Commandline
+ * (synchron) environment.
+ *
+ * <p>
+ * A connector is available for commandline processing if it requires no
+ * active user interaction for being executed or if it handles the user
+ * interaction itself.
+ * </p>
+ * <p>
+ * A commandline connector is executed synchronously. The client waits until
+ * the Connector has finished.
+ * </p>
+ * <p>
+ * Usually a synchron connector can also be used in a web environment.
+ * </p>
+ * <p>
+ * Examples for commandline connectors are: MOA, BKU. A1 is not suitible for
+ * commandline because it requires HTTP/HTML interaction, log in, etc.
+ * </p>
+ *
+ * @return Returns true, if the Connector is available for Commandline
+ * processing.
+ */
+ public static boolean isAvailableForCommandline(String connector_identifier) throws ConnectorFactoryException
+ {
+ return getAvailabilityUsingDefault(connector_identifier, ConnectorConfigurationKeys.AVAILABLE_FOR_COMMANDLINE, false);
+ }
+
+ /**
+ * Tells, if the Connector is available for being used in a Web (asynchron,
+ * local) environment.
+ *
+ * <p>
+ * A connector is available for Web if it can be used in a web environment.
+ * Often a web connector is also a local connector.
+ * </p>
+ * <p>
+ * Typical examples are the local BKU and A1. The later requires HTML log in
+ * and session handling.
+ * </p>
+ *
+ * @return Returns true, if the Connector is available for the Web
+ * application.
+ */
+ public static boolean isAvailableForWeb(String connector_identifier) throws ConnectorFactoryException
+ {
+ return getAvailabilityUsingDefault(connector_identifier, ConnectorConfigurationKeys.AVAILABLE_FOR_WEB, false);
+ }
+
+ /**
+ * Tells, if the given connector is local.
+ *
+ * @param connector_identifier
+ * The connector.
+ * @return Returns true, if the given connector is local, false otherwise.
+ * @throws ConnectorFactoryException
+ * F.e.
+ */
+ public static boolean isConnectorLocal(String connector_identifier) throws ConnectorFactoryException
+ {
+ return connector_identifier.equals(Constants.SIGNATURE_DEVICE_BKU) || connector_identifier.equals(Constants.SIGNATURE_DEVICE_A1) || connector_identifier.equals(Constants.SIGNATURE_DEVICE_MOC);
+ }
+
+ /**
+ * Key value in property file
+ */
+ // dferbas: not used anymore with dynamic algorithm support.
+ // field has to be showed/embedded except for default algorithm suites
+ // use signature block layout to show/hide
+ //public static final String MOA_ID_VISIBLE_PROPERTY_KEY = "moa.id.field.visible";
+
+ // dferbas: not used anymore
+// /**
+// * Tells, if the given connector needs or produces SIG_IDs.
+// *
+// * <p>
+// * This method is used when pre formatted signature blocks have to be created
+// * that have to know if there will be a SIG_ID field or not.
+// * </p>
+// * <p>
+// * Connectors like BKU produce SIG_IDs when signing that are needed when
+// * verifying.
+// * </p>
+// *
+// * @param connector
+// * The connector.
+// * @return Returns true, if the given connector uses SIG_IDs, false otherwise.
+// */
+// public static boolean needsSIG_ID(String connector)
+// {
+// // all modernn detached signatures have the SIG_ID field.
+// if(connector.equals("moa"))
+// {
+// String is_id_field_visible = null;
+//
+// try
+// {
+// is_id_field_visible = SettingsReader.getInstance().getValueFromKey(MOA_ID_VISIBLE_PROPERTY_KEY);
+// } catch (SettingsException e)
+// {
+// logger_.error(e.getMessage(), e);
+// }
+//
+// // if not setted in config, show it
+// if(is_id_field_visible == null)
+// return true;
+// if(is_id_field_visible.equals("true"))
+// return true;
+// else
+// return false;
+// }
+//
+// return true;
+// //return !connector.equals("moa");
+// }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/ConnectorInformation.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/ConnectorInformation.java
new file mode 100644
index 0000000..efd6c53
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/ConnectorInformation.java
@@ -0,0 +1,97 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: ConnectorInformation.java,v 1.2 2006/08/25 17:09:41 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.sig;
+
+import java.io.Serializable;
+
+/**
+ * Holds the information of one connectior.
+ *
+ * <p>
+ * An implementation of the Connector interface must provide a public static
+ * final ConnectorInformation field named
+ * ConnectorFactory#CONNECTOR_INFORMATION_FIELD_NAME that provides the
+ * information about this connector to the system.
+ * </p>
+ *
+ * @see at.knowcenter.wag.egov.egiz.sig.ConnectorFactory
+ *
+ * @author wprinz
+ */
+public class ConnectorInformation implements Serializable
+{
+ /**
+ * SVUID.
+ */
+ private static final long serialVersionUID = 5692836392376853268L;
+
+ /**
+ * The short identifier of the connector (e.g. "bku").
+ */
+ protected String connector_identifiert = null;
+
+ /**
+ * The user suitable description of the connector (e.g.
+ * "B&uuml;rgerkartenumgebung").
+ */
+ protected String connector_description = null;
+
+ /**
+ * Constructor that initializes this object.
+ *
+ * @param identifier
+ * The short identifier of the connector (e.g. "bku").
+ * @param description
+ * The user suitable description of the connector (e.g.
+ * "B&uuml;rgerkartenumgebung").
+ */
+ public ConnectorInformation(String identifier, String description)
+ {
+ this.connector_identifiert = identifier;
+ this.connector_description = description;
+ }
+
+ /**
+ * Returns the identifier of this connector.
+ *
+ * @return Returns the identifier of this connector.
+ */
+ public String getIdentifier()
+ {
+ return this.connector_identifiert;
+ }
+
+ /**
+ * Returns the description if this connector.
+ *
+ * @return Returns the description if this connector.
+ */
+ public String getDescription()
+ {
+ return this.connector_description;
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/DummyLDAPAPI.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/DummyLDAPAPI.java
new file mode 100644
index 0000000..d15f1a9
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/DummyLDAPAPI.java
@@ -0,0 +1,100 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: DummyLDAPAPI.java,v 1.2 2006/08/25 17:09:41 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.sig;
+
+import java.io.File;
+import java.io.FileInputStream;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.ldap.api.LDAPAPIException;
+import at.knowcenter.wag.egov.egiz.ldap.client.LDAPIssuerNameFilter;
+
+/**
+ * This is just a dummy implementation until the real Egiz LDAP API is
+ * implemented.
+ *
+ * @author wprinz
+ * @author modified by <a href="mailto:thomas.knall@iaik.tugraz.at">Thomas Knall</a>
+ * @deprecated Use {@link at.knowcenter.wag.egov.egiz.ldap.api.LDAPAPIFactory#createLDAPAPI()} instead.
+ */
+public class DummyLDAPAPI implements LDAPAPI
+{
+ String url_ = null;
+
+ /**
+ * The Logger.
+ */
+ protected static Log logger = LogFactory.getLog(DummyLDAPAPI.class);
+
+ public DummyLDAPAPI(String url)
+ {
+ this.url_ = url;
+ }
+
+ /* (non-Javadoc)
+ * @see at.knowcenter.wag.egov.egiz.sig.LDAPAPI#getURL(String)
+ */
+ public String getURL(String issuer)
+ {
+ return this.url_;
+ }
+
+ /* (non-Javadoc)
+ * @see at.knowcenter.wag.egov.egiz.sig.LDAPAPI#loadCertificateFromLDAP(java.lang.String, java.lang.String)
+ */
+public byte[] loadBase64CertificateFromLDAP(String serial_number, String issuer)
+ {
+ //System.out.println("LDAP: serial_number = " + serial_number);
+ //System.out.println("LDAP: issuer = " + issuer);
+
+ byte[] data = null;
+ if (serial_number.equals("153868") && issuer.equals("CN=a-sign-TEST-Premium-Sig-01,OU=a-sign-TEST-Premium-Sig-01,O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH,C=AT"))
+ {
+ try
+ {
+ File test_file = new File(SettingsReader.CERT_PATH + File.separator + "ldap_test_cert.der");
+ data = new byte[(int) test_file.length()];
+ FileInputStream fis = new FileInputStream(test_file);
+ fis.read(data);
+ fis.close();
+ }
+ catch (Exception e)
+ {
+ logger.error(e.getMessage(), e);
+ data = null;
+ }
+ }
+
+ return data;
+ }
+
+ public void setIssuerNameFilter(LDAPIssuerNameFilter filter) throws LDAPAPIException {
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/LDAPAPI.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/LDAPAPI.java
new file mode 100644
index 0000000..4269e28
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/LDAPAPI.java
@@ -0,0 +1,50 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig;
+
+import at.knowcenter.wag.egov.egiz.ldap.api.LDAPAPIException;
+import at.knowcenter.wag.egov.egiz.ldap.client.LDAPIssuerNameFilter;
+
+/**
+ * @author <a href="mailto:thomas.knall@iaik.tugraz.at">Thomas Knall</a>
+ */
+public interface LDAPAPI {
+
+ public static final String SYS_PROP_IMPLEMENTATION = "pdfas.ldapapi.impl";
+
+ /**
+ * Retrieves an certificate from the ldap server identified by serial number and issuer name.
+ * @param serialNumber The serial number.
+ * @param issuer The issuer name.
+ * @return BASE64 encoded certificate
+ */
+ public byte[] loadBase64CertificateFromLDAP(String serialNumber, String issuer);
+
+ /**
+ * Sets the filter that has to be applied before trying to match the issuer name.
+ * @param filter The filter.
+ */
+ public void setIssuerNameFilter(LDAPIssuerNameFilter filter) throws LDAPAPIException;
+
+} \ No newline at end of file
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/LocalConnector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/LocalConnector.java
new file mode 100644
index 0000000..1c254e2
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/LocalConnector.java
@@ -0,0 +1,127 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: LocalConnector.java,v 1.2 2006/08/25 17:09:41 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.sig;
+
+import java.util.Properties;
+
+import at.knowcenter.wag.egov.egiz.exceptions.SignatureException;
+
+/**
+ * A local connector is a refinement of a "normal" Connector that allows to
+ * explicitely do the request on a local client.
+ *
+ * <p>
+ * Basically the sign and verify procedures of this connector are split into
+ * three groups:
+ * </p>
+ * <ol>
+ * <li>Prepare the request to the local service.</li>
+ * <li>Carry out the request on the local client.</li>
+ * <li>Analyze the response from the local client.</li>
+ * </ol>
+ * <p>
+ * Usually the preparation and the analyzation are carried out on the server,
+ * whereas the connection to the local service is made from the local client.
+ * </p>
+ *
+ * @deprecated use the new connectory instead
+ *
+ * @author wprinz
+ */
+public interface LocalConnector extends Connector
+{
+ /**
+ * Prepares the sign request string.
+ *
+ * @param user_name
+ * The user name.
+ * @param sign_text
+ * The text to be signed.
+ * @param signature_type
+ * The type of the signature.
+ * @return Returns the request string to be sent to the local service.
+ * @throws SignatureException
+ * F.e.
+ */
+ public String prepareSignRequest(String user_name, String sign_text,
+ String signature_type) throws SignatureException;
+
+ /**
+ * Prepares the verify request string.
+ *
+ * @param signed_text
+ * The signed text to be verified.
+ * @param signature_object
+ * The SignatureObject.
+ * @return Returns the request string.
+ * @throws SignatureException
+ * F.e.
+ */
+ public String prepareVerifyRequest(String signed_text,
+ SignatureObject signature_object) throws SignatureException;
+
+ /**
+ * Analyzes the sign response string.
+ *
+ * @param signature_type
+ * The type of the signature.
+ * @return Returns the SignatureObject of the sign request.
+ * @throws SignatureException
+ * F.e.
+ */
+ // TODO hotfix - already deprecated
+ public SignatureObject analyzeSignResponse(Properties response_properties,
+ String signature_type) throws SignatureException;
+
+ /**
+ * Analyzes the verify response string.
+ *
+ * @return Returns the SignatureResponse of the verify request.
+ * @throws SignatureException
+ * F.e.
+ */
+ // TODO hotfix - already deprecated
+ public SignatureResponse analyzeVerifyResponse(Properties response_properties) throws SignatureException;
+
+ /**
+ * Returns the sign URL of the local service.
+ *
+ * @param profile
+ * The signature type the URL should be retrieved from.
+ * @return Returns the sign URL of the local service.
+ */
+ public String getSignURL(String profile);
+
+ /**
+ * Returns the verify URL of the local service.
+ *
+ * @param profile
+ * The signature type the URL should be retrieved from.
+ * @return Returns the verify URL of the local service.
+ */
+ public String getVerifyURL(String profile);
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureBlock.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureBlock.java
new file mode 100644
index 0000000..c9e3b98
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureBlock.java
@@ -0,0 +1,316 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: SignatureBlock.java,v 1.4 2006/10/31 08:18:56 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.sig;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+
+import at.knowcenter.wag.egov.egiz.exceptions.SignatureException;
+import at.knowcenter.wag.egov.egiz.exceptions.SignatureTypesException;
+
+/**
+ * This method is to analyse a signature block string. It searches for
+ * configured signature types while compairing defined key words with the text.
+ *
+ * @deprecated Use AbsoluteTextSignature instead.
+ *
+ * @author wlackner
+ */
+public class SignatureBlock
+{
+
+ /**
+ * Start index of the signature block text.
+ */
+ private int startIndex_ = -1;
+
+ /**
+ * End index of the signature block text.
+ */
+ private int endIndex_ = -1;
+
+ /**
+ * The type of the signature block.
+ */
+ private String type_ = null;
+
+ /**
+ * The signature type definition object.
+ */
+ private SignatureTypeDefinition sigTypeDef_ = null;
+
+ /**
+ * The signature block string.
+ */
+ private String signatureString_ = null;
+
+ /**
+ * The signature object build by the signature string using the signture
+ * definition.
+ */
+ private SignatureObject signatureObject_ = null;
+
+ /**
+ * A list of configured signature types.
+ */
+ List signatureTypes_ = null;
+
+ /**
+ * A list of found keys in the signature block string.
+ */
+ Map foundKeys_ = new HashMap();
+
+ int maxSize_ = -1;
+
+ /**
+ * The default constructor to analyse a signature block string. It uses a
+ * predefined signature type list to assign the text block to signature type.
+ * The analyse method have to be call separately -->
+ * separateBlockFromRawText()
+ *
+ * @param signatureTypes
+ */
+ public SignatureBlock(List signatureTypes)
+ {
+ signatureTypes_ = signatureTypes;
+ }
+
+ /**
+ * This method checks if all required keys are found in the signature block
+ * string.
+ *
+ * @param foundKeys
+ * the keys that are found in the singnature block string
+ * @return true if all required keys are found, false otherwise
+ */
+ private boolean checkRequiredFields(Map foundKeys)
+ {
+ String[] req_keys = SignatureTypes.REQUIRED_SIG_KEYS;
+ for (int req_idx = 0; req_idx < req_keys.length; req_idx++)
+ {
+ String key = req_keys[req_idx];
+ // SIG_ID could be optional --> only set in BKU signed documents
+ if (key.equals(SignatureTypes.SIG_ID))
+ {
+ continue;
+ }
+ // logger.debug("check:" + key + "=" + foundKeys.get(key));
+ if (foundKeys.get(key) == null)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * This method is the base method to analyse a raw text separating a signature
+ * block string from the raw text. It searches for corresponding signature
+ * types from back to front in the raw text. Therefore a revert list of
+ * multiple signations can be extracted calling this method more than one
+ * times. The method extracts the start and end postition of a found signature
+ * block and extracts all keys used in that block. If all required fields are
+ * found a successful separation is done and can be access calling the method
+ * getStartIndex, getEndIndex, getType, getSignatureObject.
+ *
+ * @param rawText
+ * the raw text to separate a signature block from
+ * @return true if a separation has done successful false if no signature
+ * block can be found
+ */
+ public boolean separateBlockFromRawText(String rawText, boolean old_style)
+ {
+ endIndex_ = rawText.length();
+ boolean found_type = false;
+ for (int sig_type_idx = 0; sig_type_idx < signatureTypes_.size(); sig_type_idx++)
+ {
+ int last_index = endIndex_;
+ SignatureTypeDefinition sig_type_def = (SignatureTypeDefinition) signatureTypes_.get(sig_type_idx);
+ //logger.debug("Try sep type:" + sig_type_def.getType());
+
+ Vector keys = sig_type_def.getRevertSortedKeys();
+ Vector captions = sig_type_def.getRevertSortedCaptions();
+ Map found_keys = new HashMap();
+ for (int key_idx = 0; key_idx < keys.size(); key_idx++)
+ {
+ String key = (String) keys.get(key_idx);
+ if (old_style && key.equals(SignatureTypes.SIG_KZ))
+ {
+ // If separating the old style way - skip The "Kennzeichnung"
+ // key, because it wasn't present in old profiles.
+ continue;
+ }
+ String caption = (String) captions.get(key_idx);
+ int found_idx = rawText.lastIndexOf(caption);
+ //logger.debug("Try find:" + sig_type_def.getType() + "." + key + "." + caption + " at=" + found_idx);
+ if (found_idx >= 0 && found_idx < last_index)
+ {
+ if (key.equals(SignatureTypes.SIG_ID))
+ {
+ //logger.debug("store SIG_ID, but don't decrease last index:" + sig_type_def.getType() + "." + key + "." + caption + " at=" + found_idx);
+ found_keys.put(key, new Integer(found_idx));
+ // don't decrease last index as SIG_ID is not necessarily persistent
+ }
+ else
+ {
+ //logger.debug("store:" + sig_type_def.getType() + "." + key + "." + caption + " at=" + found_idx);
+ found_keys.put(key, new Integer(found_idx));
+ last_index = found_idx;
+ }
+ }
+ }
+ if (checkRequiredFields(found_keys) && found_keys.size() > maxSize_)
+ {
+ foundKeys_ = found_keys;
+ sigTypeDef_ = sig_type_def;
+ type_ = sig_type_def.getType();
+ startIndex_ = last_index;
+ signatureString_ = rawText.substring(startIndex_, endIndex_);
+ maxSize_ = found_keys.size();
+ found_type = true;
+ }
+ }
+ return found_type;
+ }
+
+ /**
+ * @return Returns the endIndex.
+ */
+ public int getEndIndex()
+ {
+ return endIndex_;
+ }
+
+ /**
+ * @return Returns the signatureObject of the separated signature block.
+ * @throws SignatureException
+ */
+ public SignatureObject getSignatureObject() throws SignatureException
+ {
+ if (signatureObject_ == null && foundKeys_ != null)
+ {
+ signatureObject_ = new SignatureObject();
+ try
+ {
+ signatureObject_.setSigType(type_);
+ signatureObject_.initByType();
+ }
+ catch (SignatureTypesException e)
+ {
+ SignatureException se = new SignatureException(101, "Can ot set signation type:" + type_, e);
+ throw se;
+ }
+ String sig_text = signatureString_;
+ Vector revert_keys = sigTypeDef_.getRevertSortedKeys();
+ Vector revert_captions = sigTypeDef_.getRevertSortedCaptions();
+ for (int key_idx = 0; key_idx < revert_keys.size(); key_idx++)
+ {
+ String key = (String) revert_keys.get(key_idx);
+ String caption = (String) revert_captions.get(key_idx);
+ int start_idx = sig_text.lastIndexOf(caption);
+ if (start_idx >= 0)
+ {
+ int sep_idx = start_idx + caption.length();
+ // logger.debug(sig_text);
+ // logger.debug("caption:" + caption + " start_idx:" + start_idx
+ // + " length:" +
+ // sig_text.length());
+ String value = sig_text.substring(sep_idx);
+ // logger.debug("key:" + key + " value:" + value);
+ signatureObject_.setSigValueCaption(key, value, caption);
+ sig_text = sig_text.substring(0, start_idx);
+ }
+ }
+ }
+ return signatureObject_;
+ }
+
+ /**
+ * @return Returns the startIndex.
+ */
+ public int getStartIndex()
+ {
+ return startIndex_;
+ }
+
+ /**
+ * @return Returns the type.
+ */
+ public String getType()
+ {
+ return type_;
+ }
+
+// /**
+// * @param endIndex
+// * The endIndex to set.
+// */
+// private void setEndIndex(int endIndex)
+// {
+// endIndex_ = endIndex;
+// }
+//
+// /**
+// * @param startIndex
+// * The startIndex to set.
+// */
+// private void setStartIndex(int startIndex)
+// {
+// startIndex_ = startIndex;
+// }
+//
+// /**
+// * @param type
+// * The type to set.
+// */
+// private void setType(String type)
+// {
+// type_ = type;
+// }
+
+ /**
+ * The standard toString method. Used for interal tests only.
+ */
+ public String toString()
+ {
+ String strg = "";
+ strg += "Type:" + type_ + "\n";
+ strg += "Start index:" + startIndex_ + "\n";
+ strg += "End index:" + endIndex_ + "\n";
+ strg += signatureString_ + "\n";
+ strg += sigTypeDef_ + "\n";
+ try
+ {
+ strg += getSignatureObject().toString();
+ }
+ catch (SignatureException e)
+ {
+ }
+ return strg;
+ }
+} \ No newline at end of file
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureData.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureData.java
new file mode 100644
index 0000000..18f4fe8
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureData.java
@@ -0,0 +1,82 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig;
+
+import at.gv.egiz.pdfas.framework.input.DataSource;
+
+/**
+ * This encapsuilates the content data to be signed or verified.
+ *
+ * <p>
+ * For a text signature this would be the text to be signed or verified. For a
+ * binary signature this would be the PDF to be signed or verified.
+ * </p>
+ *
+ * <p>
+ * This is an abstract reprsenation of data: the binary data, its mime type and
+ * (if appropriate according to the mime type) the charset the data is encoded.
+ * </p>
+ *
+ * @author wprinz
+ */
+public interface SignatureData
+{
+ /**
+ * Returns the DataSource that provides the data for this SignatureData.
+ *
+ * @return Returns the DataSource.
+ */
+ public DataSource getDataSource();
+
+ /**
+ * Returns the mime type of the data.
+ *
+ * <p>
+ * E.g. "text/plain" for text data or "application/pdf" for a PDF.
+ * </p>
+ *
+ * @return Returns the mime type of the data.
+ */
+ public String getMimeType();
+
+ /**
+ * Returns the character encoding (charset) of the data if appropriate.
+ *
+ * <p>
+ * This is only appropriate if the mime type suggests that the data contained
+ * in here is textually encoded. Usually text/plain or similar data types will
+ * have a character encoding present.
+ * </p>
+ * <p>
+ * If no character encoding is present, null is returned here.
+ * </p>
+ * <p>
+ * E.g. "UTF-8" is the most common encoding for textual data.
+ * </p>
+ *
+ * @return Returns the character encoding (charset) of the data if
+ * appropriate.
+ */
+ public String getCharacterEncoding();
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureDataImpl.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureDataImpl.java
new file mode 100644
index 0000000..cbd2408
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureDataImpl.java
@@ -0,0 +1,130 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig;
+
+import java.io.Serializable;
+
+import at.gv.egiz.pdfas.framework.input.DataSource;
+
+/**
+ * Generic implementation of the SignatureData interface for being used by
+ * signators and verificators.
+ *
+ * @author wprinz
+ */
+public class SignatureDataImpl implements SignatureData, Serializable
+{
+ /**
+ * SVUID.
+ */
+ private static final long serialVersionUID = -8652845539968684408L;
+
+ /**
+ * The signature data.
+ */
+ protected DataSource data = null;
+
+ /**
+ * The mime type of the data.
+ */
+ protected String mimeType = null;
+
+ /**
+ * The character encoding of the data if appropriate, or null if not.
+ */
+ protected String characterEncoding = null;
+
+ /**
+ * Constructor that fills the SignatureData.
+ *
+ * <p>
+ * The charactor encoding is set to null, so this constructor is primarily for
+ * signature data that has no character encoding (e.g. binary data).
+ * </p>
+ *
+ * @param data
+ * The signature data.
+ * @param mime_type
+ * The mime type of the data.
+ */
+ public SignatureDataImpl(DataSource data, String mime_type)
+ {
+ this.data = data;
+ this.mimeType = mime_type;
+ this.characterEncoding = null;
+ }
+
+// /**
+// * Constructor that fills the SignatureData.
+// *
+// * <p>
+// * Use this constructor for textual data as it allows to provide the character
+// * encoding.
+// * </p>
+// *
+// * @param data
+// * The signature data.
+// * @param mime_type
+// * The mime type of the data.
+// * @param character_encoding
+// * The character encoding of the data if appropriate, or null if not.
+// */
+// public SignatureDataImpl(byte[] data, String mime_type, String character_encoding)
+// {
+// this.data = data;
+// this.mimeType = mime_type;
+// this.characterEncoding = character_encoding;
+// }
+ public SignatureDataImpl(DataSource data, String mime_type, String character_encoding)
+ {
+ this.data = data;
+ this.mimeType = mime_type;
+ this.characterEncoding = character_encoding;
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.SignatureData#getDataSource()
+ */
+ public DataSource getDataSource()
+ {
+ return this.data;
+ }
+
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.SignatureData#getMimeType()
+ */
+ public String getMimeType()
+ {
+ return this.mimeType;
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.SignatureData#getCharacterEncoding()
+ */
+ public String getCharacterEncoding()
+ {
+ return this.characterEncoding;
+ }
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureEntry.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureEntry.java
new file mode 100644
index 0000000..078f80f
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureEntry.java
@@ -0,0 +1,163 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: SignatureEntry.java,v 1.3 2006/08/25 17:09:41 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.sig;
+
+import java.io.Serializable;
+
+/**
+ * This class is to store a signature entry. The signature entry is 3-tupel. A key that is defined
+ * or declarated in the settings file, an optional caption or a value. <br>
+ * An additional helper value is a marker for the start index of the key, if the key is found in an
+ * analysing process extracting captions and values from a raw signature text.
+ *
+ * @author wlackner
+ * @see at.knowcenter.wag.egov.egiz.sig.SignatureObject
+ */
+public class SignatureEntry implements Serializable {
+
+ /**
+ * SVUID.
+ */
+ private static final long serialVersionUID = 4640380069301731879L;
+
+ /**
+ * 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 starting index position of the key if it is found in the signature text.
+ */
+ private int startIndex_ = -1;
+
+ public boolean isPlaceholder = false;
+
+ /**
+ * The empty constructor.
+ */
+ public SignatureEntry() {
+ }
+
+ /**
+ * A new <code>SignatureEntry</code> 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 start position of the key that caption is found in the signature text.
+ *
+ * @return Returns the startIndex.
+ */
+ public int getStartIndex() {
+ return startIndex_;
+ }
+
+ /**
+ * Set the start position of the current key.
+ *
+ * @param startIndex The startIndex to set.
+ */
+ public void setStartIndex(int startIndex) {
+ startIndex_ = startIndex;
+ }
+
+ /**
+ * 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/knowcenter/wag/egov/egiz/sig/SignatureFieldDefinition.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureFieldDefinition.java
new file mode 100644
index 0000000..3c16599
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureFieldDefinition.java
@@ -0,0 +1,88 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: SignatureFieldDefinition.java,v 1.1 2006/08/25 17:09:41 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.sig;
+
+import java.io.Serializable;
+
+/**
+ * This class contains the information about one field in the signature block.
+ *
+ * <p>
+ * E.g. Field "Issuer" could have the caption "Aussteller", the value null and
+ * the placeholder length of 500.
+ * </p>
+ *
+ * @author wprinz
+ */
+public class SignatureFieldDefinition implements Serializable
+{
+
+ /**
+ * SVUID.
+ */
+ private static final long serialVersionUID = -46020173047777315L;
+
+ /**
+ * The key identifier of this field.
+ */
+ public String field_name = null;
+
+ /**
+ * The static caption of the field.
+ */
+ public String caption = null;
+
+ /**
+ * The static value of the field.
+ *
+ * <p>
+ * Null means that this field has no static value and must be filled out.
+ * </p>
+ */
+ public String value = null;
+
+ /**
+ * If the field is not static and has to be filled out, this gives the
+ * length of the placeholder that is reserved for filling out.
+ *
+ * <p>
+ * This has to be large enough so that it can hold the whole value to be
+ * filled out.
+ * </p>
+ */
+ public int placeholder_length = -1;
+
+ /**
+ * Stores the three byte abbreviation code of this field's field name.
+ */
+ //public byte [] brev = null;
+
+ public String toString()
+ {
+ return this.field_name + ": caption=" + this.caption + ", value=" + this.value + ", phlen=" + this.placeholder_length;
+ }
+
+} \ No newline at end of file
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureObject.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureObject.java
new file mode 100644
index 0000000..8855b86
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureObject.java
@@ -0,0 +1,2108 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: SignatureObject.java,v 1.7 2006/10/31 08:18:56 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.sig;
+
+import iaik.asn1.structures.Name;
+import iaik.asn1.structures.RDN;
+import iaik.utils.RFC2253NameParser;
+import iaik.utils.RFC2253NameParserException;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.Serializable;
+import java.io.UnsupportedEncodingException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.Logger;
+
+import at.knowcenter.wag.egov.egiz.PdfASID;
+import at.knowcenter.wag.egov.egiz.cfg.ConfigLogger;
+import at.knowcenter.wag.egov.egiz.cfg.OverridePropertyHolder;
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.exceptions.InvalidIDException;
+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.ldap.api.LDAPAPIException;
+import at.knowcenter.wag.egov.egiz.ldap.api.LDAPAPIFactory;
+import at.knowcenter.wag.egov.egiz.ldap.client.LDAPIssuerNameFilter;
+import at.knowcenter.wag.egov.egiz.sig.sigkz.SigKZIDHelper;
+import at.knowcenter.wag.egov.egiz.table.Entry;
+import at.knowcenter.wag.egov.egiz.table.Style;
+import at.knowcenter.wag.egov.egiz.table.Table;
+import at.knowcenter.wag.egov.egiz.tools.CodingHelper;
+import at.knowcenter.wag.egov.egiz.tools.FileHelper;
+import at.knowcenter.wag.egov.egiz.tools.Normalizer;
+
+/**
+ * This class represents the abstract signature object. It contains all methods
+ * reading the definitions from the settings file, analyse them and build the
+ * abstract signature table. <br>
+ * All values that build or used by the signation creation process, call the
+ * external services, can read or set separately. All other values are defined
+ * in the settings file.
+ *
+ * @author wlackner
+ * @author modified by <a href="mailto:thomas.knall@iaik.tugraz.at">Thomas Knall</a>
+ */
+public class SignatureObject implements Serializable
+{
+
+// 03.11.2010 changed by exthex - added default for defaultValueStyle_.hAlign since we had to remove the hardcoded default in Style
+// 04.11.2010 changed by exthex - setSigValue no longer removes multiple newlines from value
+
+ /**
+ * SVUID.
+ */
+ private static final long serialVersionUID = -3535189232362254713L;
+
+ /**
+ * The system file separator char
+ */
+ private static final String FILE_SEP = System.getProperty("file.separator");
+
+ /**
+ * The certificate extension
+ */
+ private static final String CERT_FILE_EXTENSION = ".der";
+
+ /**
+ * certificate import dir
+ */
+ private static final String CERT_ADD_DIR = "tobeadded";
+
+ /**
+ * The default style definition for images.
+ */
+ private Style defaultImageStyle_ = new Style();
+
+ /**
+ * The default style definition for captions.
+ */
+ private Style defaultCaptionStyle_ = new Style();
+
+ /**
+ * The default style definition for values.
+ */
+ private Style defaultValueStyle_ = new Style();
+
+ /**
+ * Standard key get/set the signature meta informations
+ */
+ public static final String SIG_META = "SIG_META";
+
+ /**
+ * Standard key get/set the certification value
+ */
+ public static final String SIG_CER = "SIG_CER";
+
+ /**
+ * Standard key get/set the certification digest value
+ */
+ public static final String SIG_CER_DIG = "SIG_CER_DIG";
+
+ private X509Cert x509Cert_ = null;
+
+ private String timeStamp = null;
+
+ // public static final String SIG_RES = "SIG_RES";
+ // dummy value for debugging only
+ private String sigResponse_ = null;
+
+ /**
+ * The logger definition.
+ */
+ private static final Logger logger_ = ConfigLogger.getLogger(SignatureObject.class);
+
+ /**
+ * The normalizer reference
+ */
+ private Normalizer normalizer_ = null;
+
+ /**
+ * The settings reader reference
+ */
+ private SettingsReader settings_ = null;
+
+ // /**
+ // * The reference to the settings property tree
+ // */
+ // private PropertyTree pTree_ = null;
+ /**
+ * The current signature type used reading and analysing the property tree
+ */
+ private String sigType_ = null;
+
+ /**
+ * Reference from signature key to there corresponding value
+ */
+ private Hashtable sigEntries_ = new Hashtable(8);
+
+ /**
+ * The abstract table representation
+ */
+ private Table sigTable_ = null;
+
+ // private HashMap sigIndexMap_ = new HashMap();
+
+ /**
+ * Path value storing and fetching the certificates
+ */
+ private String certPath_ = null;
+
+ /**
+ * the signature definition object
+ */
+ private SignatureTypeDefinition signatureDefinition_ = null;
+
+ /**
+ * The raw xml response from the connector that was used to set the values in
+ * this SignatureObject.
+ *
+ * <p>
+ * This is set by the Connector so that signing Applications can use the
+ * returned XML values.
+ * </p>
+ */
+ protected String raw_signature_response = null;
+
+ /**
+ * Filters the issuer name in order to find matches.
+ * @author tknall
+ * @see #normalizeIssuer
+ */
+ private LDAPIssuerNameFilter issuerNameFilter = new LDAPIssuerNameFilter() {
+ public Name applyFilter(Name name) {
+ RFC2253NameParser parser = new RFC2253NameParser(normalizeIssuer(name.getName()));
+ try {
+ name = parser.parse();
+ } catch (RFC2253NameParserException e) {
+ logger_.error(e.getMessage(), e);
+ }
+ return name;
+ }
+ };
+
+ /**
+ * The empty constructor. It initilize the normlizer, load the settings and
+ * set the default styles.
+ *
+ * @throws SignatureException
+ * ErrorCode:101, 400
+ */
+ public SignatureObject() throws SignatureException
+ {
+ initNormalizer();
+ loadSettings();
+ setDefaultStyles();
+ }
+
+ /**
+ * This method initialize the normalizer
+ *
+ * @throws SignatureException
+ * ErrorCode:400
+ */
+ private void initNormalizer() throws SignatureException
+ {
+ try
+ {
+ normalizer_ = new Normalizer();
+ }
+ catch (NormalizeException e)
+ {
+ SignatureException se = new SignatureException(400, "Normalizer can not be initialized", e);
+ throw se;
+ }
+ }
+
+ /**
+ * This method load the signature definitions
+ *
+ * @throws SignatureException
+ * ErrorCode:101
+ */
+ private void loadSettings() throws SignatureException
+ {
+ if (settings_ == null)
+ {
+ try
+ {
+ settings_ = SettingsReader.getInstance();
+ }
+ catch (SettingsException e)
+ {
+ String log_message = "Can not load pdf signature settings. Cause:\n" + e.getMessage();
+ logger_.error(log_message);
+ throw new SignatureException(101, log_message, e);
+ }
+ }
+ // pTree_ = settings_.getPTree();
+
+ certPath_ = SettingsReader.CERT_PATH;
+ }
+
+ /**
+ * This method set the default styles for images, captions and values.
+ */
+ private void setDefaultStyles()
+ {
+ defaultImageStyle_.setPadding(3);
+ defaultImageStyle_.setHAlign(Style.CENTER);
+ defaultImageStyle_.setVAlign(Style.MIDDLE);
+
+ defaultCaptionStyle_.setHAlign(Style.CENTER);
+ defaultCaptionStyle_.setVAlign(Style.MIDDLE);
+
+ defaultValueStyle_.setHAlign(Style.LEFT);
+ defaultValueStyle_.setVAlign(Style.MIDDLE);
+ }
+
+ /**
+ * Dummy getter Method for debugging only
+ *
+ * @return response string
+ */
+ public String getSigResponse()
+ {
+ return sigResponse_;
+ }
+
+ /**
+ * Dummy setter Method for debugging only
+ *
+ * @param sigRespone
+ * store the response string
+ */
+ public void setSigResponse(String sigRespone)
+ {
+ sigResponse_ = sigRespone;
+ }
+
+ /**
+ * This method set the signature type.
+ *
+ * @param sigType
+ * the signature type to be set
+ * @throws SignatureTypesException
+ */
+ public void setSigType(String sigType) throws SignatureTypesException
+ {
+ SignatureTypes sig_types = SignatureTypes.getInstance();
+ signatureDefinition_ = sig_types.getSignatureTypeDefinition(sigType_);
+ sigType_ = sigType;
+ }
+
+ /**
+ * Returns the default signation type
+ *
+ * @return the key for the default signature definition, if the key is not
+ * found it returns null
+ */
+ private String getDefaultSigType()
+ {
+ return settings_.getSetting(SignatureTypes.DEFAULT_TYPE, null);
+ }
+
+ /**
+ * This method checks if a given signature key is realy a defined signature
+ * key.
+ *
+ * @param sigKey
+ * the key to check
+ * @return true if the key is correct, false if the given key is not defined
+ */
+ public boolean isSigKey(String sigKey)
+ {
+ return signatureDefinition_.contains(sigKey);
+ }
+
+ /**
+ * This method adds an sig value to the entry cache. If a key is not in
+ * the cache a new signature entry is created. Therefore the method return
+ * true. <br>
+ * The value that has to be set would be normalized! <br>
+ * <b>If the key equals to <code>SIG_VALUE</code> all whitespaces are
+ * removed! </b> <br>
+ *
+ * @param key
+ * the key to be set
+ * @param value
+ * the value to be set
+ * @return <code>true</code> if a new signature value is created,
+ * <code>false</code> otherwise
+ */
+ public boolean setSigValue(String key, String value) {
+ return setSigValue(key, value, false);
+ }
+
+ public boolean setSigValue(String key, String value, boolean placeholder)
+ {
+ SignatureEntry sig_entry = null;
+ boolean is_new = false;
+ if (sigEntries_.containsKey(key))
+ {
+ sig_entry = (SignatureEntry) sigEntries_.get(key);
+ }
+ else
+ {
+ sig_entry = new SignatureEntry(key);
+ sigEntries_.put(key, sig_entry);
+ is_new = true;
+ }
+ value = normalizer_.normalize(value, true);
+ if (SignatureTypes.SIG_VALUE.equals(key) || SignatureTypes.SIG_ID.equals(key) || SignatureTypes.SIG_NUMBER.equals(key))
+ {
+ value = removeAllWhiteSpaces(value);
+ }
+ sig_entry.setValue(value);
+ sig_entry.isPlaceholder = placeholder;
+ return is_new;
+ }
+
+ public boolean setValueBruteForce(String key, String value)
+ {
+ SignatureEntry sig_entry = null;
+ boolean is_new = false;
+ if (sigEntries_.containsKey(key))
+ {
+ sig_entry = (SignatureEntry) sigEntries_.get(key);
+ }
+ else
+ {
+ sig_entry = new SignatureEntry(key);
+ sigEntries_.put(key, sig_entry);
+ is_new = true;
+ }
+ sig_entry.setValue(value);
+ return is_new;
+ }
+
+ /**
+ * Set the value and the caption to given key.
+ *
+ * @param key
+ * the key of the signature object
+ * @param value
+ * the value of the given key
+ * @param caption
+ * the caption of the given key
+ */
+ public void setSigValueCaption(String key, String value, String caption)
+ {
+ setSigValue(key, value);
+ SignatureEntry sig_entry = (SignatureEntry) sigEntries_.get(key);
+ sig_entry.setCaption(caption);
+ }
+
+ /**
+ * This method returns a value for a given signature key. If the key equals to
+ * <code>SIG_NORM</code> and the value is <code>null</code> the version
+ * string of the current normalizer is returned!
+ *
+ * @param key
+ * the key to get the value for
+ * @return a value for the given key
+ */
+ public String getSigValue(String key)
+ {
+
+ String value = null;
+ SignatureEntry sigEntry = null;
+ if (sigEntries_.containsKey(key))
+ {
+ sigEntry = (SignatureEntry) sigEntries_.get(key);
+ value = sigEntry.getValue();
+ }
+ if (value == null && SignatureTypes.SIG_NORM.equals(key))
+ {
+ value = normalizer_.getVersion();
+ }
+
+ String overrideVal = OverridePropertyHolder.getProperty(key);
+ if (value != null && sigEntry != null && !sigEntry.isPlaceholder && overrideVal != null) { // TODO this!! SignatureEntry.isPlaceholder
+ value = overrideVal;
+ if (logger_.isDebugEnabled()) {
+ logger_.debug("Using override property for key '" + key + "' = " + value);
+ }
+ }
+
+ return value;
+ }
+
+ /**
+ * Sets the "Kennzeichnung".
+ *
+ * @param kz
+ * The "Kennzeichnung" to be set.
+ */
+ public void setKZ(PdfASID kz)
+ {
+ setSigValue(SignatureTypes.SIG_KZ, kz.toString());
+ }
+
+ /**
+ * Returns the "Kennzeichnung" of this signature.
+ *
+ * @return Returns the "Kennzeichnung" of this signature. Returns null if
+ * there is no "Kennzeichnung" or it is not recognized by this
+ * application.
+ */
+ public PdfASID getKZ() throws InvalidIDException
+ {
+ String kz_string = getSigValue(SignatureTypes.SIG_KZ);
+ if (kz_string == null)
+ {
+ return null;
+ }
+ PdfASID kz = null;
+ try
+ {
+ kz = new PdfASID(kz_string);
+ }
+ catch (InvalidIDException e)
+ {
+ logger_.error(e.getMessage(), e);
+ }
+ return kz;
+ }
+
+ /**
+ * This method returns a caption for a given signature key. If the key exists
+ * and the coresponding value is <code>null</code> the key itself is
+ * returned as caption! If the key does not exist the method returns
+ * <code>null</code>.
+ *
+ * @param key
+ * the key to get the caption for
+ * @return a caption for the given key
+ */
+ private String getSigCaption(String key)
+ {
+
+ String caption = null;
+ if (sigEntries_.containsKey(key))
+ {
+ caption = ((SignatureEntry) sigEntries_.get(key)).getCaption();
+ if (caption == null)
+ {
+ caption = key;
+ }
+ }
+ return caption;
+ }
+
+ /**
+ * @return Returns the SignationType.
+ */
+ public String getSignationType()
+ {
+ if (sigType_ == null)
+ {
+ sigType_ = getDefaultSigType();
+ }
+ return sigType_;
+ }
+
+ /**
+ * @return Returns the SignationDate.
+ */
+ public String getSignationDate()
+ {
+ return getSigValue(SignatureTypes.SIG_DATE);
+ }
+
+ /**
+ * @param sigDate
+ * The SignationDate to set.
+ */
+ public void setSignationDate(String sigDate)
+ {
+ setSigValue(SignatureTypes.SIG_DATE, sigDate);
+ }
+
+ /**
+ * @return Returns the SignationName.
+ */
+ public String getSignationName()
+ {
+ return getSigValue(SignatureTypes.SIG_NAME);
+ }
+
+ /**
+ * @param sigName
+ * The SignationName to set.
+ */
+ public void setSignationName(String sigName)
+ {
+ setSigValue(SignatureTypes.SIG_NAME, sigName);
+ }
+
+ /**
+ * @return Returns the SignationNormVersion.
+ */
+ public String getSignationNormVersion()
+ {
+ return getSigValue(SignatureTypes.SIG_NORM);
+ }
+
+ /**
+ * @param sigNormVersion
+ * The SignationNormVersion to set.
+ */
+ public void setSignationNormVersion(String sigNormVersion)
+ {
+ setSigValue(SignatureTypes.SIG_NORM, sigNormVersion);
+ }
+
+ /**
+ * This method removes whitespaces around RDNs. Whitespaces may be assumed by the algorithm that
+ * re-merges multiple lines from a binary signature when line breaks occur after commas. Without
+ * correction this will result in broken signatures.<br/>
+ * e.g this
+ * invalid IssuerName (note the space before the second RND CN):
+ * <code>serialNumber=863532247989, CN=BMUKK - Amtssignatur Schulen,OU=Abt. IT/2,O=Bundesministerium für Unterricht, Kunst und Kultur,C=AT</code>
+ * will be normalized to:
+ * <code>serialNumber=863532247989,CN=BMUKK - Amtssignatur Schulen,OU=Abt. IT/2,O=Bundesministerium für Unterricht, Kunst und Kultur,C=AT</code>
+ * @param The invalid RFC2253 name as string.
+ * @return The normalized RFC2253 name without spaces prior to RDNs.
+ */
+ public static String prepareRFC2253Name(String name) {
+ if (name == null) {
+ return null;
+ }
+ StringTokenizer tokenizer = new StringTokenizer(name, ",", false);
+ StringBuffer result = new StringBuffer();
+ // iterate over all alleged RND=value-pairs
+ while (tokenizer.hasMoreTokens()) {
+ String rdnExpression = tokenizer.nextToken();
+ try {
+ // try to parse RDN=value
+ new RFC2253NameParser(rdnExpression.trim()).parse();
+ // rdnExpression is a RDN=value pair -> remove whitespaces before and after RDN=value
+ rdnExpression = rdnExpression.trim();
+ } catch (RFC2253NameParserException e) {
+ // this is not a RDN=value pair
+ // e.g. " Kunst und Kultur" from the javadoc example
+ // do not trim, otherwise resulting RFC2253Name will be invalid
+ }
+ // re-insert delimiter
+ if (result.length() > 0) {
+ result.append(",");
+ }
+ // add token (either trimmed RND=value pair, or not trimmed text token)
+ result.append(rdnExpression);
+ }
+ String cleanedName = result.toString();
+ if (logger_.isDebugEnabled()) {
+ logger_.debug("Cleaning RFC2253 name: \"" + name + "\" -> \"" + cleanedName + "\".");
+ }
+ return cleanedName;
+ }
+
+ /**
+ * This method depicts a workaround for a bug with RFC2253 names with RDNs that have not been
+ * resolved from ObjectID at signing time (this results from a BKU that could not resolve
+ * the respective OID).<br/>
+ * e.g. <code>2.5.4.5=#1306323030383034, CN=ForeignerCA,C=BE</code><br/>
+ * The example above shows a RDN "2.5.4.5" which should have been resolved to "serialNumber" at
+ * signing time. We also recognize that the name shows spaces prior to RDNs and that the space
+ * which between "Foreigner" and "CA" is missing due to text extraction/reconstruction.
+ * The naive approach would be to take the complete RFC2253 name from the certificate, since that
+ * name has also been used for signature. But this does not work in some cases because while
+ * the bku was not able to resolve 2.5.4.5 on signing time, the entity invoking pdfas for
+ * verification might be, so that taking the name from certificate on verification time, may not
+ * result in the name we had at signing time.<br/>
+ * e.g. at signing time: <code>2.5.4.5=#1306323030383034,CN=Foreigner CA,C=BE</code><br/>
+ * after text extraction: <code>2.5.4.5=#1306323030383034, CN=ForeignerCA,C=BE</code><br/>
+ * from certificate: <code>serialNumber=863532247989,CN=Foreigner CA,C=BE</code><br/>
+ * This method provides a workaround for that problem, by merging information from text extraction
+ * with information from the certificate. The method takes all RDNs from the extracted text and
+ * merges them with the values from the certificate (considering the case where the textual
+ * version shows BER encoded values (e.g. <code>#1306323030383034</code>).
+ * @param nameFromText The extracted RFC2253 name from the text (e.g. <code>2.5.4.5=#1306323030383034, CN=ForeignerCA,C=BE</code>).
+ * @param nameFromCertificate The RFC2253 name from the certificate (e.g. <code>serialNumber=863532247989,CN=Foreigner CA,C=BE</code>)
+ * @return The RFC2253 name that was used for signature (e.g. <code>2.5.4.5=#1306323030383034,CN=Foreigner CA,C=BE</code>).
+ */
+ public static String prepareRFC2253Name(String nameFromText, String nameFromCertificate) {
+
+ // do not invoke the workaround for performance reasons when both the extracted name and the
+ // name from certificate are equal
+ if (StringUtils.equals(nameFromText, nameFromCertificate)) {
+ return nameFromText;
+ }
+
+ logger_.debug("Checking RFC2253 name.");
+
+ // if we do not have a name from certificate just return the name from text
+ if (nameFromCertificate == null) {
+ logger_.debug("No certificate RFC2253 name provided. Applying less sophisticated workaround (does not cover all cases) without certificate usage.");
+ return prepareRFC2253Name(nameFromText);
+ }
+
+ // no name from text extraction available, just return name from certificate
+ if (nameFromText == null) {
+ logger_.debug("No extracted/reconstructed name available. Just returning the name from certificate: \"" + nameFromCertificate + "\".");
+ return nameFromCertificate;
+ }
+
+ // helper class
+ final class RDNValuePair {
+
+ private String rdn;
+ private String value;
+
+ public RDNValuePair(String rdn, String value) {
+ this.rdn = rdn;
+ this.value = value;
+ }
+
+ public String getRdn() {
+ return this.rdn;
+ }
+
+ public String getValue() {
+ return this.value;
+ }
+
+ public String toString() {
+ return rdn + "=" + value;
+ }
+ }
+
+ // retrieve RDNs from text based name
+ List rdnList = new ArrayList();
+ StringTokenizer tokenizer = new StringTokenizer(nameFromText, ",", false);
+ while (tokenizer.hasMoreTokens()) {
+ String rdnExpression = tokenizer.nextToken().trim();
+ try {
+ new RFC2253NameParser(rdnExpression).parse();
+ // token is RDN=value pair
+ // split RDN from value
+ String[] split = rdnExpression.split("=", 2);
+ rdnList.add(new RDNValuePair(split[0].trim(), split[1].trim()));
+ } catch (RFC2253NameParserException e) {
+ // no RDN in token
+ }
+ }
+
+ // get values from certificate name
+ Name nCert;
+ try {
+ nCert = new RFC2253NameParser(nameFromCertificate).parse();
+ } catch (RFC2253NameParserException e) {
+ // should never happen
+ logger_.warn("Unable to parse RFC2253 name \"" + nameFromCertificate + "\". Applying less sophisticated workaround (does not cover all cases) without certificate usage.");
+ return prepareRFC2253Name(nameFromText);
+ }
+ RDN[] values = nCert.getRDNs();
+
+ // check if results are mergeable
+ if (values.length != rdnList.size()) {
+ // unable to merge names; returning nameFromCertificate (since this should be normal
+ // behavior)
+ logger_.warn("Number of parsed text based RDNs from \"" + nameFromText + "\" does not fit the number of RDN values from certificate name \"" + nameFromCertificate + "\". Returning name from certificate.");
+ return nameFromCertificate;
+ }
+
+ // merge textual based RDNs with values from certificate
+ StringBuffer result = new StringBuffer();
+ for (int i = 0; i < values.length; i++) {
+ if (i > 0) {
+ result.append(",");
+ }
+ // take rdn from textual representation
+ RDNValuePair rdnVP = (RDNValuePair) rdnList.get(i);
+ // Note: Do not take RDN from extraction but from certificate
+ // (Bug-Fix for EMAIL/EMAILADDRESS problem in ZID documents)
+
+ // take value from certificate but make sure that we do not have a
+ // BER encoding
+ if (rdnVP.getValue().startsWith("#")) {
+
+ // take rdn from textual representation
+ result.append(rdnVP.getRdn()).append("=");
+ // BER encoding -> take value from text representation
+ result.append(rdnVP.getValue());
+ } else {
+ // no BER encoding -> take value from certificate
+ // also take RDN from certificate if possible
+ String certValue = values[values.length - 1 - i].getAVA()
+ .getValueAsString();
+ String rdn = resolveRDN(nameFromCertificate, certValue, rdnVP.getRdn());
+ result.append(rdn + "=").append(certValue);
+ }
+
+ }
+ String merged = result.toString();
+ if (logger_.isDebugEnabled()) {
+ if (merged.equals(nameFromText)) {
+ logger_.debug("Taking name from text: \"" + nameFromText + "\"");
+ } else if (merged.equals(nameFromCertificate)) {
+ logger_.debug("Taking name from certificate: \"" + nameFromText + "\"");
+ } else {
+ logger_.debug("Name has been fixed.");
+ logger_.debug("Name from text : \"" + nameFromText + "\"");
+ logger_.debug("Name from certificate : \"" + nameFromCertificate + "\"");
+ logger_.debug("Fixed name : \"" + merged + "\"");
+ }
+ }
+ return merged;
+ }
+
+ /**
+ * This method tries to resolve the RDN corresponding to a given value from the certificate String.
+ * As values might occur multiple times for different RDNs, an unambiguous resolving cannot be assured.
+ * In case of ambiguity, the RDN extracted from text is returned by default.
+ *
+ * This method is a bug fix for a problem that caused the verification of ZID documents to fail as the RDN
+ * from the extracted text ("EMAILADDRESS") was different to the RDN in the certificate ("EMAIL")
+ *
+ * @param certString
+ * The String obtained from the certificate
+ * @param value
+ * The RDN's value
+ * @param extractedRDN
+ * The RDN extracted from the given text
+ * @return
+ * The resolved RDN from the certificate, or the RDN from text extraction
+ */
+ private static String resolveRDN(String certString, String value, String extractedRDN) {
+
+ if(!certString.contains(value)) {
+
+ // given value cannot be found in certificate string
+ return extractedRDN;
+ }
+
+ if(certString.indexOf(value) != certString.lastIndexOf(value)) {
+
+ // given value is ambiguous - cannot resolve RDN from certificate string
+ return extractedRDN;
+ }
+
+ String[] parts = certString.split(",|;");
+ String val = value.trim();
+
+ for(int i=0; i<parts.length; i++) {
+
+ String part = parts[i].trim();
+
+ if(part.endsWith(val)) {
+
+ // found entry - extract RDN
+ String[] components = part.split("=");
+ if(components.length != 2) {
+ // unexpected format - return default
+ return extractedRDN;
+ }
+ String rdn = components[0].trim();
+ return rdn;
+ }
+ }
+ // default
+ return extractedRDN;
+ }
+
+ /**
+ * @return Returns the SignationIssuer.
+ */
+ public String getSignationIssuer()
+ {
+ String issuer = getSigValue(SignatureTypes.SIG_ISSUER);
+ X509Cert cert = loadCertificate(getSigValue(SignatureTypes.SIG_NUMBER), issuer);
+ if (cert != null)
+ {
+ // merge RDNs from file with values from certificate
+ if (getSigValue(SignatureTypes.SIG_ISSUER) != null) {
+ this.setSignationIssuer(prepareRFC2253Name(getSigValue(SignatureTypes.SIG_ISSUER), cert.getIssuerName()));
+ } else {
+ this.setSignationIssuer(cert.getIssuerName());
+ }
+ /*
+ if (getSigValue(SignatureTypes.SIG_ISSUER) == null) {
+ this.setSignationIssuer(cert.getIssuerName());
+ }
+ */
+ setSigValue(SIG_CER, cert.getCertString());
+ // setSigValue(SIG_CER_DIG, cert.getCertDigest());
+ x509Cert_ = cert;
+ }
+ issuer = getSigValue(SignatureTypes.SIG_ISSUER);
+ return issuer;
+ }
+
+ /**
+ * @param sigIssuer
+ * The SignationIssuer to set.
+ */
+ public void setSignationIssuer(String sigIssuer)
+ {
+ setSigValue(SignatureTypes.SIG_ISSUER, sigIssuer);
+ }
+
+ /**
+ * @return Returns the SignationValue.
+ */
+ public String getSignationValue()
+ {
+ return getSigValue(SignatureTypes.SIG_VALUE);
+ }
+
+ /**
+ * @param sigValue
+ * The SignationValue to set.
+ */
+ public void setSignationValue(String sigValue)
+ {
+ setSigValue(SignatureTypes.SIG_VALUE, sigValue);
+ }
+
+ /**
+ * @return the reference to the signature label
+ */
+ public String getOfficialSeal()
+ {
+ return getSigValue(SignatureTypes.SIG_LABEL);
+ }
+
+ /**
+ * @param serialNumber
+ * The serial number of the signature to set
+ */
+ public void setSignationSerialNumber(String serialNumber)
+ {
+ setSigValue(SignatureTypes.SIG_NUMBER, serialNumber);
+ }
+
+ /**
+ * @return sigNumber the serial number of the signature
+ */
+ public String getSignationSerialNumber()
+ {
+ return getSigValue(SignatureTypes.SIG_NUMBER);
+ }
+
+ // dferbas baik
+
+ /**
+ * signature algorithm if embedded
+ * @param sigAlg
+ */
+ public void setSigAlg(String sigAlg)
+ {
+ setSigValue(SignatureTypes.SIG_ALG, sigAlg);
+ }
+
+ /**
+ * signature algorithm if embedded
+ * @return
+ */
+ public String getSigAlg()
+ {
+ return getSigValue(SignatureTypes.SIG_ALG);
+ }
+
+ /**
+ * @param certDigest
+ * set the digest value for the X509Certificate
+ */
+ public void setX509CertificateDigest(String certDigest)
+ {
+ setSigValue(SIG_CER_DIG, certDigest);
+ }
+
+ /**
+ * This method load the current certificate getting the current SerialNumber
+ * and the current SignationIssuer. <br>
+ * It stores back the SignationIssuer, X509Certificate and
+ * X509CertificateDigest
+ */
+ private void loadCurrentCert()
+ {
+ X509Cert cert = loadCertificate(getSignationSerialNumber(), getSignationIssuer());
+ if (cert != null)
+ {
+ // merge RDNs from file with values from certificate
+ if (getSigValue(SignatureTypes.SIG_ISSUER) != null) {
+ this.setSignationIssuer(prepareRFC2253Name(getSigValue(SignatureTypes.SIG_ISSUER), cert.getIssuerName()));
+ } else {
+ this.setSignationIssuer(cert.getIssuerName());
+ }
+ /*
+ if (getSigValue(SignatureTypes.SIG_ISSUER) == null) {
+ this.setSignationIssuer(cert.getIssuerName());
+ }
+ */
+ setSigValue(SIG_CER, cert.getCertString());
+ // setSigValue(SIG_CER_DIG, cert.getCertDigest());
+ x509Cert_ = cert;
+ }
+ }
+
+ /**
+ * @return the current X509CertificateDigest value (as SHA1 digest).
+ */
+ public String getX509CertificateDigest()
+ {
+ String dig = getSigValue(SIG_CER_DIG);
+ if (dig == null)
+ {
+ loadCurrentCert();
+ byte[] cert_b64 = CodingHelper.decodeBase64(x509Cert_.getCertString());
+ byte[] cert_hash = CodingHelper.buildDigest(cert_b64, "SHA");
+ dig = new String(CodingHelper.encodeBase64(cert_hash));
+ setSigValue(SIG_CER_DIG, dig);
+ }
+ return dig;
+ }
+
+ /**
+ * @return the current X509v3 certificate string
+ */
+ public String getX509CertificateString()
+ {
+ String cert = getSigValue(SIG_CER);
+ if (cert == null)
+ {
+ loadCurrentCert();
+ cert = getSigValue(SIG_CER);
+ }
+ return cert;
+ }
+
+ /**
+ * @param x509Certificate
+ * The X509v3 certificate of the signature to set
+ */
+ public void setX509Certificate(String x509Certificate)
+ {
+ setSigValue(SIG_CER, x509Certificate);
+ storeCertificate(getSignationSerialNumber(), getSignationIssuer(), x509Certificate);
+ }
+
+ public void setX509Certificate(X509Certificate cert)
+ {
+ try
+ {
+// byte [] der = cert.getEncoded();
+// String certStr = CodingHelper.encodeBase64(der);
+// setX509Certificate(certStr);
+ X509Cert knowcenterCert = X509Cert.initByX509Certificate(cert);
+ setSigValue(SIG_CER, knowcenterCert.getCertString());
+ storeCertificate(cert.getSerialNumber().toString(), knowcenterCert.getIssuerName(), knowcenterCert.getCertString());
+ }
+ catch (CertificateEncodingException e)
+ {
+ logger_.error(e.getMessage(), e);
+ }
+ }
+
+ /**
+ * return the 509v3 certificate of the given serialNumber and the given issuer
+ * string
+ *
+ * @param serialNumber
+ * the serialNumber which the certificates should load
+ * @param issuer
+ * the issuer which the certificates should load
+ * @return the X509v3 certificate string
+ */
+ public String getX509CertificateString(String serialNumber, String issuer)
+ {
+ X509Cert cert = loadCertificate(serialNumber, issuer);
+ if (cert != null)
+ {
+ return cert.getCertString();
+ }
+ return null;
+ }
+
+ public X509Cert getX509Cert(String serialNumber, String issuer)
+ {
+ return loadCertificate(serialNumber, issuer);
+ }
+
+ public X509Cert getX509Cert()
+ {
+ if (x509Cert_ == null)
+ {
+ loadCurrentCert();
+ }
+ return x509Cert_;
+ }
+
+ /**
+ * Set the signation id's build by a BKU signated SignatureObject.
+ *
+ * @param sigIds
+ * the string to store.
+ */
+ public void setSignationIDs(String sigIds)
+ {
+ if (sigIds != null)
+ {
+ setSigValue(SignatureTypes.SIG_ID, sigIds);
+ }
+ }
+
+ // /**
+ // * Set the signation id's build by a BKU signated SignatureObject.
+ // *
+ // * @param sigIds
+ // * The sination id's are defined into five parts, that have the same
+ // * base as prefix. Therefore the ids's are reduced by the base prefix
+ // * and stored in the SignatureObject.
+ // */
+ // public void setSignationIDs(String[] sigIds)
+ // {
+ // String join = "";
+ // String base = null;
+ // for (int arr_idx = 0; arr_idx < sigIds.length; arr_idx++)
+ // {
+ // String id = sigIds[arr_idx];
+ // if (logger_.isDebugEnabled())
+ // {
+ // logger_.debug("Set BKU id:" + id);
+ // }
+ // int id_idx = id.lastIndexOf("-");
+ // if (arr_idx == 0)
+ // {
+ // base = id.substring(0, id_idx);
+ // }
+ // String cur_id = id.substring(id_idx + 1);
+ // join += "-" + cur_id;
+ // }
+ // setSignationIDs(base + "@" + join.substring(1));
+ // }
+
+ // TODO hotfix
+ public static String formatSigIds(Properties response_properties,
+ String[] sigIds) throws SignatureException
+ {
+ // ids algorithm:
+ String join = "";
+ String base = null;
+ for (int arr_idx = 0; arr_idx < sigIds.length; arr_idx++)
+ {
+ String id = sigIds[arr_idx];
+ if (logger_.isDebugEnabled())
+ {
+ logger_.debug("Set BKU id:" + id);
+ }
+ int id_idx = id.lastIndexOf("-");
+ if (arr_idx == 0)
+ {
+ base = id.substring(0, id_idx);
+ }
+ String cur_id = id.substring(id_idx + 1);
+ join += "-" + cur_id;
+ }
+ // setSignationIDs(base + "@" + join.substring(1));
+ String ids = base + "@" + join.substring(1);
+ // :ids algorithm
+
+ String productName = response_properties.getProperty("productName");
+ logger_.debug("productName = " + productName);
+// if (!productName.equals("trustDeskbasic"))
+ // modified by tknall
+ if (!productName.startsWith("trustDeskbasic"))
+ {
+ final String msg = "The BKU environment " + productName + " is not trustDeskbasic and therefore the productVersion cannot be decided.";
+ logger_.error(msg);
+ // uncomment the following line in order to check new bkus
+ throw new SignatureException(0, msg);
+ }
+
+ String productVersion = response_properties.getProperty("productVersion");
+ logger_.debug("productVersion = " + productVersion);
+ boolean new_etsi = decideNewEtsiByBKUVersion(productVersion);
+ logger_.debug("verwende neue etsi properties = " + new_etsi);
+
+ String etsi_prefix = "";
+ if (new_etsi)
+ {
+ // TODO hotfix
+ etsi_prefix = "etsi-bka-1.0@";
+ }
+
+ String final_ids = etsi_prefix + ids;
+ logger_.debug("final_ids = " + final_ids);
+
+ return final_ids;
+ }
+
+ // TODO hotfix
+ public static boolean decideNewEtsiByBKUVersion(String productVersion)
+ {
+ boolean new_etsi = true;
+ // TODO hotfix
+ if (productVersion.startsWith("2.5") || productVersion.startsWith("2.4") || productVersion.startsWith("2.3") || productVersion.startsWith("2.2") || productVersion.startsWith("2.1") || productVersion.startsWith("1") || productVersion.startsWith("0"))
+ {
+ new_etsi = false;
+ }
+ return new_etsi;
+ }
+
+ /**
+ * Checks if the current SignatureObject is siganted by MOA. It checks if the
+ * current SignatureObject has a signation id value.
+ *
+ * @return true if no signation id value is found, false otherwise
+ */
+ public boolean isMOASigned()
+ {
+ try
+ {
+ PdfASID sig_kz = getKZ();
+ String sig_id = getSignationIds();
+ return SigKZIDHelper.isMOASigned(sig_kz, sig_id);
+ //return getSignationIds() == null;
+ }
+ catch (InvalidIDException e)
+ {
+ logger_.error(e.getMessage(), e);
+ return false;
+ }
+ }
+
+ /**
+ * Tells if this SignatureObject is textual.
+ *
+ * @return Returns true, if it is textual.
+ */
+ public boolean isTextual()
+ {
+ PdfASID kz = null;
+ try
+ {
+ kz = getKZ();
+ }
+ catch (InvalidIDException e)
+ {
+ logger_.error(e.getMessage(), e);
+ }
+ return SigKZIDHelper.isTextual(kz);
+ }
+
+ /**
+ * Tells, if this SignatureObject is binary.
+ *
+ * @return Returns true, if it is binary.
+ */
+ public boolean isBinary()
+ {
+ PdfASID kz = null;
+ try
+ {
+ kz = getKZ();
+ }
+ catch (InvalidIDException e)
+ {
+ logger_.error(e.getMessage(), e);
+ }
+
+ return SigKZIDHelper.isBinary(kz);
+ }
+
+ /**
+ * Takes the signation id value of the current SignatureObject and split them
+ * into the corresponding id array added with the id-base.
+ *
+ * @return the id array
+ */
+ // TODO hotifx
+ public String getSignationIds()
+ {
+ String sig_ids = getSigValue(SignatureTypes.SIG_ID);
+ return sig_ids;
+
+ // if (sig_ids == null || sig_ids.length() == 0)
+ // {
+ // return null;
+ // }
+ //
+ // // int index = sig_ids.indexOf(PdfAS.IDS);
+ // // if (index < 0)
+ // // {
+ // // return null;
+ // // }
+ // // sig_ids = sig_ids.substring(index + PdfAS.IDS.length());
+ // //
+ // // if (sig_ids == null || sig_ids.length() == 0)
+ // // {
+ // // return null;
+ // // }
+ //
+ // String[] ids_str = sig_ids.split("@");
+ // String base = ids_str[0];
+ // String[] ids = ids_str[1].split("-");
+ // String[] real_ids = new String[5];
+ // real_ids[0] = base + "-" + ids[0];
+ // real_ids[1] = "0-" + base + "-" + ids[1];
+ // real_ids[2] = "0-" + base + "-" + ids[2];
+ // real_ids[3] = "0-" + base + "-" + ids[3];
+ // real_ids[4] = "0-" + base + "-" + ids[4];
+ // if (logger_.isDebugEnabled())
+ // {
+ // for (int id_idx = 0; id_idx < real_ids.length; id_idx++)
+ // {
+ // logger_.debug("Set BKU id:" + real_ids[id_idx]);
+ // }
+ // }
+ // return real_ids;
+ }
+
+ // TODO hotfix
+ public static String[] parseSigIds(String sig_ids)
+ {
+ if (sig_ids == null || sig_ids.length() == 0)
+ {
+ return null;
+ }
+
+ // int index = sig_ids.indexOf(PdfAS.IDS);
+ // if (index < 0)
+ // {
+ // return null;
+ // }
+ // sig_ids = sig_ids.substring(index + PdfAS.IDS.length());
+ //
+ // if (sig_ids == null || sig_ids.length() == 0)
+ // {
+ // return null;
+ // }
+
+ String[] ids_str = sig_ids.split("@");
+
+ String etsi_string = null;
+ if (ids_str.length == 3)
+ {
+ etsi_string = ids_str[0];
+ String[] rest_ids = new String[] { ids_str[1], ids_str[2] };
+ ids_str = rest_ids;
+ }
+
+ String base = ids_str[0];
+ String[] ids = ids_str[1].split("-");
+ String[] real_ids = new String[6]; // the last one contains the etsi string
+ real_ids[0] = base + "-" + ids[0];
+ real_ids[1] = "0-" + base + "-" + ids[1];
+ real_ids[2] = "0-" + base + "-" + ids[2];
+ real_ids[3] = "0-" + base + "-" + ids[3];
+ real_ids[4] = "0-" + base + "-" + ids[4];
+ real_ids[5] = etsi_string;
+
+ if (logger_.isDebugEnabled())
+ {
+ for (int id_idx = 0; id_idx < real_ids.length; id_idx++)
+ {
+ logger_.debug("real_ids[" + id_idx + "] = " + real_ids[id_idx]);
+ }
+ }
+
+ return real_ids;
+ }
+
+ /**
+ * This method normalizes the issuer string to support unique issuer string
+ * for equition. Used to store and find corresponting certificates.
+ * Normalzing: normalizing the string using the normalizer, remove all white
+ * spaces, encode as base64 and replace all "/" chars with "_".
+ *
+ * @param issuer
+ * the issuer string to normalize
+ * @return the normalized issuer string
+ * @author modified by tknall
+ */
+ private String getIssuerFileHash(String issuer)
+ {
+ try
+ {
+ if (issuer != null)
+ {
+ // use explicit method for normalization
+ issuer = normalizeIssuer(issuer);
+ /* this block may be used to enhance normalization (tknall)
+ try {
+ Name issuerName = new RFC2253NameParser(issuer).parse();
+ issuer = issuerName.getRFC2253String();
+ } catch (RFC2253NameParserException e) {
+ logger_.error(e);
+ }
+ */
+ // added the ("UTF-8")
+ issuer = CodingHelper.encodeBase64(CodingHelper.buildDigest(issuer.getBytes("UTF-8"), "sha1"));
+ issuer = issuer.replaceAll("/", "_");
+ }
+ return issuer;
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Prepares issuer for further processing (e.g. calculation of certificate store location or
+ * comparison with registered ldap mappings.)
+ * @param issuer The issuer.
+ * @return normalized issuer
+ * @see #issuerNameFilter
+ * @author tknall
+ */
+ private String normalizeIssuer(String issuer) {
+ issuer = normalizer_.normalize(issuer, false);
+ issuer = removeAllWhiteSpaces(issuer);
+ return issuer;
+ }
+
+ /**
+ * This method imports new certificates into the certstore path.
+ */
+ private void addNewCertificates()
+ {
+ String cert_add_path = certPath_ + CERT_ADD_DIR;
+ File cert_add_dir = new File(cert_add_path);
+ if (cert_add_dir.isDirectory())
+ {
+ File[] cert_files = cert_add_dir.listFiles();
+ for (int cert_file_idx = 0; cert_file_idx < cert_files.length; cert_file_idx++)
+ {
+ File cert_file = cert_files[cert_file_idx];
+ if (cert_file.isFile() && cert_file.canRead())
+ {
+ X509Cert cert = X509Cert.initByFile(cert_file);
+ // System.err.println("isCert:" + cert.isX509Cert() + ":" +
+ // cert_file.getAbsolutePath());
+ if (cert.isX509Cert())
+ {
+ String issuer = cert.getIssuerName();
+ String serial_number = cert.getSerialNumber();
+ String iss_hash = getIssuerFileHash(issuer);
+ String cert_store_path = certPath_ + iss_hash;
+
+ File cert_store_dir = new File(cert_store_path);
+ if (!cert_store_dir.exists())
+ {
+ cert_store_dir.mkdir();
+ }
+ if (cert_store_dir.isDirectory())
+ {
+ String cert_file_name = cert_store_path + FILE_SEP + serial_number + CERT_FILE_EXTENSION;
+ logger_.debug("Adding cert (issuer=\"" + cert.getIssuerName() + "\", sn=\"" + cert.getSerialNumber() + "\") to certstore: \"" + cert_file_name + "\".");
+ // boolean store =
+ FileHelper.writeToFile(cert_file_name, cert.getCertString());
+ // System.err.println("store:" + store + ":" +
+ // cert_file.getAbsolutePath());
+ }
+ }
+ boolean deleted = cert_file.delete();
+ if (deleted == false)
+ {
+ logger_.error("couldn't delete:" + cert_file.getAbsolutePath());
+ }
+ }
+ }
+ }
+ }
+
+ private X509Cert loadCertificateFromCertstore(String serialNumber, String issuer) {
+ String iss_hash = getIssuerFileHash(issuer);
+ String cert_store_path = certPath_ + iss_hash;
+ String cert_file_name = cert_store_path + FILE_SEP + serialNumber + CERT_FILE_EXTENSION;
+ if (logger_.isDebugEnabled()) {
+ logger_.debug("Trying to load cert (issuer=\"" + (issuer != null ? normalizeIssuer(issuer) : issuer) + "\", sn=\"" + serialNumber + "\") from certstore: \"" + cert_file_name + "\".");
+ }
+ return X509Cert.initByFilePath(cert_file_name);
+ }
+
+ /**
+ * This method load a X509v3 certificate from the filesystem. The reference to
+ * the stored certificate is build by the serialNumber and the issuer string.
+ * The issuer string is normalized because if getting this value from a pdf
+ * extraction it can be splited into more sections or necessary spaces are
+ * removed. The real issuer value is stored in the certificates meta file. The
+ * certficate is devided into two files: certificate.der (the binary value)
+ * and the meta information used in SignatureObjects as well in
+ * SignatureImages of a signed pdf-document. The storing path of the
+ * certificate is build by:
+ * <ol>
+ * <li>normalize the issuer string</li>
+ * <li>reduce all white spaces in the normalized issuer string</li>
+ * <li>build a hash value of this reduced string</li>
+ * <li>code this hash value as base64 value</li>
+ * <li>add the base64 normalized issuer hash value to the certificate base
+ * store path</li>
+ * <li>add the serialNumber to the cert path</li>
+ * <li>add the <code>.der</code> extension to get the certificate binary</li>
+ * <li>add the <code>.txt</code> extension to get the meta information of
+ * the certificate</li>
+ * </ol>
+ *
+ * The certificate meta file is build by the base64 coded issuer string and
+ * the cert digest value devided by the <code>@</code> char.
+ *
+ * @param serialNumber
+ * the file name of the certificate .der|.txt
+ * @param issuer
+ * the file path value of the certificate
+ * @return String array: [0]--> issuer string; [1]-->certificate binary;
+ * [2]--> cert digest value
+ */
+ private X509Cert loadCertificate(String serialNumber, String issuer)
+ {
+ addNewCertificates();
+ X509Cert cert = null;
+ if (issuer != null && serialNumber != null)
+ {
+ cert = loadCertificateFromCertstore(serialNumber, issuer);
+ if (cert == null) {
+ logger_.debug("Certificate not found. Trying alternative normalization method.");
+ try {
+ Name issuerName = new RFC2253NameParser(issuer).parse();
+ cert = loadCertificateFromCertstore(serialNumber, issuerName.getRFC2253String(false));
+ } catch (RFC2253NameParserException e) {
+ logger_.error(e.getMessage(), e);
+ }
+ }
+
+ if (cert == null)
+ {
+ logger_.info("The certificate '" + issuer + "', '" + serialNumber + "' wasn't found in the local certificate store - connecting to LDAP.");
+
+ // the certificate wasn't found in the local store
+ // - load it from the LDAP server.
+
+ byte[] cert_data = loadCertificateFromLDAP(serialNumber, issuer);
+ if (cert_data == null)
+ {
+ logger_.info("The certificate '" + issuer + "', '" + serialNumber + "' wasn't found on the LDAP server either.");
+
+ return null;
+ }
+
+ storeNewCertificateInLocalStore(cert_data);
+
+ cert = X509Cert.initByByteArray(cert_data);
+ if (cert == null)
+ {
+ logger_.debug("The certificate should be loaded here, but is null - something's wrong.");
+ }
+ }
+ } else {
+ logger_.warn("loadCertificate(\"" + serialNumber + "\", \"" + issuer + "\")");
+ }
+ return cert;
+ }
+
+ /**
+ * This is an internal counter for added certificates.
+ */
+ protected static int new_cert_num = 0;
+
+ /**
+ * Writes the certificate data to a file and stores the file in the local
+ * certificate store.
+ *
+ * @param cert_data
+ * The binary certificate data.
+ */
+ public void storeNewCertificateInLocalStore(byte[] cert_data)
+ {
+ // write the loaded certificate to the add directory
+ String cert_add_path = certPath_ + CERT_ADD_DIR;
+ File cert_add_dir = new File(cert_add_path);
+ if (!cert_add_dir.exists())
+ {
+ cert_add_dir.mkdirs();
+ }
+ File save_file = new File(cert_add_dir, "newcert_" + new_cert_num + ".der");
+ new_cert_num++;
+ try
+ {
+ FileOutputStream fos = new FileOutputStream(save_file);
+ fos.write(cert_data);
+ fos.close();
+ // fixed by tknall: if serialnumber or issuername is omitted (binary signature) the
+ // certificate could not be found in the certstore. The fix sets the issuername and
+ // serialnumber as long the are known.
+ X509Cert cert = X509Cert.initByByteArray(cert_data);
+ if (cert.isX509Cert()) {
+ this.setSignationSerialNumber(cert.getSerialNumber());
+ this.setSignationIssuer(cert.getIssuerName());
+ }
+ } catch (IOException e) {
+ logger_.error(e.getMessage(), e);
+ return;
+ }
+
+ // add the new certificate to the local store
+ addNewCertificates();
+ }
+
+ /**
+ * Connects to the LDAP server to look for the certificate.
+ *
+ * @param serialNumber
+ * The serial number String of the certificate being sought. E.g.
+ * "123455676744123432".
+ * @param issuer
+ * The issuer String of the certificate being sought.
+ *
+ * @return Returns the DER certificate file as can be stored in the local
+ * repository. Returns null, if the document wasn't found on the
+ * server.
+ * @throws ClassNotFoundException
+ */
+ protected byte[] loadCertificateFromLDAP(String serialNumber, String issuer) {
+ // START modification by TK
+ String implClassURI = System.getProperty(LDAPAPI.SYS_PROP_IMPLEMENTATION);
+ LDAPAPI ldapAPIImpl;
+ try {
+ // note: in case of implClassURI==null the default implementation
+ // at.knowcenter.wag.egov.egiz.ldap.api.LDAPAPIImpl is used
+ ldapAPIImpl = LDAPAPIFactory.getInstance(issuerNameFilter).createLDAPAPI(implClassURI);
+ } catch (LDAPAPIException e) {
+ throw new RuntimeException(e);
+ }
+ return ldapAPIImpl.loadBase64CertificateFromLDAP(serialNumber, issuer);
+ // STOP modification by TK
+ }
+
+ /**
+ * This method stores a X509v3 certificate to the filesystem. The reference to
+ * the stored certificate is build by the serialNumber and the issuer string.
+ * The issuer string is normalized because if getting this value from a pdf
+ * extraction it can be splited into more sections or necessary spaces are
+ * removed. The real issuer value is stored in the certificates meta file. The
+ * certficate is devided into two files: certificate.der (the binary value)
+ * and the meta information used in SignatureObjects as well in
+ * SignatureImages of a signed pdf-document. The storing path of the
+ * certificate is build by:
+ * <ol>
+ * <li>normalize the issuer string</li>
+ * <li>reduce all white spaces in the normalized issuer string</li>
+ * <li>build a hash value of this reduced string</li>
+ * <li>code this hash value as base64 value</li>
+ * <li>add the base64 normalized issuer hash value to the certificate base
+ * store path</li>
+ * <li>add the serialNumber to the cert path</li>
+ * <li>add the <code>.der</code> extension to get the certificate binary</li>
+ * <li>add the <code>.txt</code> extension to get the meta information of
+ * the certificate</li>
+ * </ol>
+ *
+ * The certificate meta file is build by the base64 coded issuer string and
+ * the cert digest value devided by the <code>@</code> char.
+ *
+ * @param serialNumber
+ * the file name of the certificate .der|.txt
+ * @param issuer
+ * the issuer string for the file path value of the certificate and
+ * for metainformation
+ * @param x509Certificate
+ * the x509v3 binary string
+ * @param x509Digest
+ * the digest value of the given x509Certificate
+ * @return true the certificate is stored completely, false otherwise
+ * @deprecated Use {@link #storeCertificate(String, String, String)} instead.
+ */
+ private boolean storeCertificate(String serialNumber, String issuer,
+ String x509Certificate, String x509Digest)
+ {
+ return storeCertificate(serialNumber, issuer, x509Certificate);
+ }
+
+ /**
+ * This method stores a X509v3 certificate to the filesystem. The reference to
+ * the stored certificate is build by the serialNumber and the issuer string.
+ * The issuer string is normalized because if getting this value from a pdf
+ * extraction it can be splited into more sections or necessary spaces are
+ * removed. The real issuer value is stored in the certificates meta file. The
+ * certficate is devided into two files: certificate.der (the binary value)
+ * and the meta information used in SignatureObjects as well in
+ * SignatureImages of a signed pdf-document. The storing path of the
+ * certificate is build by:
+ * <ol>
+ * <li>normalize the issuer string</li>
+ * <li>reduce all white spaces in the normalized issuer string</li>
+ * <li>build a hash value of this reduced string</li>
+ * <li>code this hash value as base64 value</li>
+ * <li>add the base64 normalized issuer hash value to the certificate base
+ * store path</li>
+ * <li>add the serialNumber to the cert path</li>
+ * <li>add the <code>.der</code> extension to get the certificate binary</li>
+ * <li>add the <code>.txt</code> extension to get the meta information of
+ * the certificate</li>
+ * </ol>
+ *
+ * The certificate meta file is build by the base64 coded issuer string and
+ * the cert digest value devided by the <code>@</code> char.
+ *
+ * @param serialNumber
+ * the file name of the certificate .der|.txt
+ * @param issuer
+ * the issuer string for the file path value of the certificate and
+ * for metainformation
+ * @param x509Certificate
+ * the x509v3 binary string
+ * @return true the certificate is stored completely, false otherwise
+ */
+ private boolean storeCertificate(String serialNumber, String issuer,
+ String x509Certificate)
+ {
+ boolean store_complete = false;
+ if (issuer != null && serialNumber != null)
+ {
+ logger_.debug("Storing certificate.");
+ // String issuer_b64 = CodingHelper.encodeBase64(issuer.getBytes());
+ String iss_hash = getIssuerFileHash(issuer);
+ File cert_path_dir = new File(certPath_);
+ if (!cert_path_dir.exists())
+ {
+ logger_.debug("Certstore path \"" + cert_path_dir + "\" does not exist. Creating.");
+ cert_path_dir.mkdir();
+ }
+ String cert_store_path = certPath_ + iss_hash;
+ File cert_store_dir = new File(cert_store_path);
+ if (!cert_store_dir.exists())
+ {
+ logger_.debug("Certstore dir \"" + cert_store_dir + "\" does not exist. Creating.");
+ cert_store_dir.mkdir();
+ }
+ if (cert_store_dir.isDirectory())
+ {
+ String cert_file_name = cert_store_path + FILE_SEP + serialNumber + CERT_FILE_EXTENSION;
+ if (logger_.isInfoEnabled())
+ {
+ logger_.info("store certificate:" + cert_file_name);
+ }
+ boolean store_cert_file = FileHelper.writeToFile(cert_file_name, x509Certificate);
+ store_complete = store_cert_file;// && store_cert_meta;
+ } else {
+ logger_.warn("Certstore dir \"" + cert_store_dir + "\" is not a directory. Skipping storage.");
+ }
+ }
+ return store_complete;
+ }
+
+ /**
+ * @return Returns the AbstractTable.
+ * @see at.knowcenter.wag.egov.egiz.table.Table
+ */
+ public Table getAbstractTable()
+ {
+ if (sigTable_ == null)
+ {
+ sigTable_ = createSigTable(SignatureTypes.MAIN_TABLE);
+ }
+ return sigTable_;
+ }
+
+ /**
+ * This method read the style definitions from the settings file.
+ *
+ * @param styleKey
+ * the key to read the style definitions
+ * @return the defined style informations
+ * @see at.knowcenter.wag.egov.egiz.table.Style
+ */
+ private Style readStyle(String styleKey)
+ {
+ ArrayList styles = settings_.getKeys(styleKey);
+ Style style = new Style();
+ for (int style_idx = 0; style_idx < styles.size(); style_idx++)
+ {
+ String style_id = (String) styles.get(style_idx);
+ String style_val = settings_.getSetting(styleKey + "." + style_id, null);
+ style.setStyle(style_id, style_val);
+ }
+ return style;
+ }
+
+ /**
+ * This method creates an abstract signature table object. It takes all keys
+ * and values set by the signature object to create the corresponding abstract
+ * table object. The table definition is read from the settings file.
+ *
+ * @param tableKey
+ * is the name of the table definition in the settings file
+ * @return a new abstract signature table
+ * @see at.knowcenter.wag.egov.egiz.table.Style
+ * @see at.knowcenter.wag.egov.egiz.table.Table
+ * @see at.knowcenter.wag.egov.egiz.table.Entry
+ */
+ private Table createSigTable(String tableKey)
+ {
+ String table_key_prefix = SignatureTypes.SIG_OBJ + getSignationType() + "." + SignatureTypes.TABLE;
+ String table_key = table_key_prefix + tableKey;
+ // String caption_prefix = SignatureTypes.SIG_OBJ + getSignationType() +
+ // ".key.";
+ // String value_prefix = SignatureTypes.SIG_OBJ + getSignationType() +
+ // ".value.";
+ // ArrayList table_def_keys = settings_.getKeys(table_key);
+ Vector table_def_keys = settings_.getSettingKeys(table_key);
+ if (table_def_keys == null)
+ {
+ return null;
+ }
+ Table sig_table = new Table(tableKey);
+ boolean found_style = false;
+ for (int table_key_idx = table_def_keys.size() - 1; table_key_idx >= 0; table_key_idx--)
+ {
+ String table_def = (String) table_def_keys.get(table_key_idx);
+ int dot_idx = (table_def.indexOf(".") > 0 ? table_def.indexOf(".") : table_def.length());
+ table_def = table_def.substring(0, dot_idx);
+ String table_def_keys_prefix = table_key + "." + table_def;
+ String table_def_string = settings_.getSetting(table_def_keys_prefix, null);
+ if (table_def.matches("\\D*"))
+ {
+ // if the table key is not a number (row number index)
+ if (SignatureTypes.COLS_WITH.equals(table_def))
+ {
+ String[] cols_s = table_def_string.split(" ");
+ float[] cols_f = new float[cols_s.length];
+ for (int i = 0; i < cols_s.length; i++)
+ {
+ cols_f[i] = Float.parseFloat(cols_s[i]);
+ }
+ sig_table.setColsRelativeWith(cols_f);
+ }
+ if (SignatureTypes.STYLE.equals(table_def) && !found_style)
+ {
+ Style style = readStyle(table_def_keys_prefix);
+ sig_table.setStyle(style);
+ found_style = true;
+ }
+ continue;
+ }
+ if (table_def_string != null)
+ {
+ // analyse the row definition
+ String[] elems = table_def_string.split("\\|");
+ ArrayList row = new ArrayList();
+ for (int elem_idx = 0; elem_idx < elems.length; elem_idx++)
+ {
+ String elem = elems[elem_idx];
+ String[] key_type = elem.split("-");
+ if (key_type.length < 2)
+ {
+ return null;
+ }
+ String key = key_type[0];
+ String type = key_type[1];
+ if (SignatureTypes.TYPE_TABLE.equals(key))
+ {
+ // add a table entry
+ Table table = createSigTable(type);
+ if (table != null)
+ {
+ Entry entry = new Entry(Entry.TYPE_TABLE, table, key);
+ row.add(entry);
+ }
+ }
+ if (SignatureTypes.TYPE_IMAGE.equals(type))
+ {
+ // add an image entry
+ String value = getSigValue(key);
+ if (value != null)
+ {
+ Entry entry = new Entry(Entry.TYPE_IMAGE, value, key);
+ entry.setStyle(defaultImageStyle_);
+ row.add(entry);
+ }
+ }
+ if (SignatureTypes.TYPE_VALUE.equals(type))
+ {
+ // add a single value entry
+ String value = getSigValue(key);
+ Entry entry = new Entry(Entry.TYPE_VALUE, value, key);
+ if (entry != null)
+ {
+ entry.setColSpan(2);
+ entry.setStyle(defaultValueStyle_);
+ row.add(entry);
+ }
+ }
+ if ((SignatureTypes.TYPE_VALUE + SignatureTypes.TYPE_CAPTION).equals(type) || (SignatureTypes.TYPE_CAPTION + SignatureTypes.TYPE_VALUE).equals(type))
+ {
+ // add a caption value pair
+ String caption = getSigCaption(key);
+ String value = getSigValue(key);
+ if (value != null)
+ {
+ Entry c_entry = new Entry(Entry.TYPE_CAPTION, caption, key);
+ c_entry.setNoWrap(true); // dferbas fix bug #331
+ c_entry.setStyle(defaultCaptionStyle_);
+
+ Entry v_entry = new Entry(Entry.TYPE_VALUE, value, key);
+ v_entry.setStyle(defaultValueStyle_);
+ if (c_entry != null && v_entry != null)
+ {
+ row.add(c_entry);
+ row.add(v_entry);
+ }
+ }
+ }
+ }
+ sig_table.addRow(table_def, row);
+ }
+ }
+
+ return sig_table;
+ }
+
+ /**
+ * This method inits the signature object by the given type. It loads the
+ * configured values and captions from the config.properties file.
+ */
+ public void initByType() throws SignatureTypesException
+ {
+ if (sigType_ == null)
+ {
+ sigType_ = getDefaultSigType();
+ }
+ SignatureTypes sig_types = SignatureTypes.getInstance();
+ signatureDefinition_ = sig_types.getSignatureTypeDefinition(sigType_);
+ if (signatureDefinition_ == null)
+ {
+ final String msg = "The SignatureObject's sigType '" + sigType_ + "' wasn't found in the configuration file's specified signature profiles. This usually happens if the sig_obj.type.default object has been turned off or is misspelled.";
+ logger_.error(msg);
+ throw new SignatureTypesException(msg);
+ }
+ Map key_cap_map = signatureDefinition_.getKeyCaptionMap();
+ if (key_cap_map != null)
+ {
+ Iterator key_cap = key_cap_map.entrySet().iterator();
+ while (key_cap.hasNext())
+ {
+ Map.Entry entry = (Map.Entry) key_cap.next();
+ String key = (String) entry.getKey();
+ String caption = (String) entry.getValue();
+ SignatureEntry sig_entry = null;
+ if (sigEntries_.containsKey(key))
+ {
+ sig_entry = (SignatureEntry) sigEntries_.get(key);
+ }
+ else
+ {
+ sig_entry = new SignatureEntry(key);
+ sigEntries_.put(key, sig_entry);
+ }
+ sig_entry.setCaption(caption);
+ }
+ }
+
+ Map key_val_map = signatureDefinition_.getKeyValueMap();
+ if (key_val_map != null)
+ {
+ Set key_val_set = key_val_map.entrySet();
+ Iterator key_val = key_val_set.iterator();
+ while (key_val.hasNext())
+ {
+ Map.Entry entry = (Map.Entry) key_val.next();
+ String key = (String) entry.getKey();
+ String value = (String) entry.getValue();
+ if (SignatureTypes.SIG_NORM.equals(key))
+ {
+ try
+ {
+ normalizer_.setVersion(value);
+ }
+ catch (NormalizeException e)
+ {
+ throw new SignatureTypesException(e);
+ }
+ }
+ // value = new String(CodingHelper.encodeUTF8(value));
+ // if (logger_.isDebugEnabled())
+ // {
+ // logger_.debug("key:" + key + " value:" + value);
+ // }
+ setSigValue(key, value);
+ }
+ }
+ }
+
+ /**
+ * This method returns a signature entry object.
+ *
+ * @param key
+ * the corresponding key
+ * @return the signature entry object of the given key, null if the key does
+ * not exist
+ */
+ public SignatureEntry getSigEntry(String key)
+ {
+ return (SignatureEntry) sigEntries_.get(key);
+ }
+
+ /**
+ * This method is a helper function to remove all white spaces from a text.
+ *
+ * @param text
+ * the white spaces should remove from
+ * @return a text without white spaces
+ */
+ private static String removeAllWhiteSpaces(String text)
+ {
+ return text.replaceAll("\\s", "");
+ }
+
+ public SignatureTypeDefinition getSignatureTypeDefinition()
+ {
+ return this.signatureDefinition_;
+ }
+
+ /**
+ *
+ * @param placeholder
+ * @return Returns the list of SignatureFieldDefinitions that's values in the
+ * SignatureObject have been filled out with placeholders.
+ */
+ public List fillValues(final char placeholder, boolean has_SIG_ID, boolean baikEnabled)
+ {
+ List variable_fields = new ArrayList();
+
+ List field_definitions = this.signatureDefinition_.getFieldDefinitions();
+ Iterator it = field_definitions.iterator();
+ while (it.hasNext())
+ {
+ SignatureFieldDefinition sfd = (SignatureFieldDefinition) it.next();
+ String value_string = null;
+ if (sfd.placeholder_length > 0)
+ {
+ if (sfd.field_name.equals(SignatureTypes.SIG_ID) && has_SIG_ID == false)
+ {
+ setValueBruteForce(SignatureTypes.SIG_ID, null);
+ continue;
+ }
+
+ if (sfd.field_name.equals(SignatureTypes.SIG_ALG) && !baikEnabled) {
+ setValueBruteForce(SignatureTypes.SIG_ID, null);
+ continue;
+ }
+
+ char[] placeholder_chars = new char[sfd.placeholder_length];
+ for (int i = 0; i < placeholder_chars.length; i++)
+ {
+ placeholder_chars[i] = placeholder;
+ }
+ value_string = new String(placeholder_chars);
+
+ variable_fields.add(sfd);
+
+ setSigValue(sfd.field_name, value_string, true);
+ }
+ }
+
+ return variable_fields;
+ }
+
+ /**
+ * Returns the raw signature response XML string as set by the signing
+ * Connector.
+ *
+ * @return Returns the XML response String.
+ */
+ public String getRawSignatureResponse()
+ {
+ return this.raw_signature_response;
+ }
+
+ /**
+ * Sets the raw signature response XML string.
+ *
+ * <p>
+ * This should be used by the Connector to pass the response String to the
+ * signer.
+ * </p>
+ *
+ * @param raw_response_string
+ * The new raw signature response string.
+ */
+ public void setRawSignatureResponse(String raw_response_string)
+ {
+ this.raw_signature_response = raw_response_string;
+ }
+
+
+
+ /**
+ * get timestamp if available
+ * @return
+ */
+ public String getTimeStamp() {
+ return this.timeStamp;
+ }
+
+ /**
+ * set timestamp
+ * @param timeStamp
+ */
+ public void setTimeStamp(String timeStamp) {
+ this.timeStamp = timeStamp;
+ }
+
+/**
+ * The toString method, used for tests or debugging.
+ */
+ public String toString()
+ {
+ String strg = "";
+ Iterator it = sigEntries_.values().iterator();
+ while (it.hasNext())
+ {
+ SignatureEntry sig_entry = (SignatureEntry) it.next();
+ String key = sig_entry.getKey();
+ String caption = sig_entry.getCaption();
+ String value = sig_entry.getValue();
+ strg += key + "=" + caption + ":" + value + "\n";
+ }
+ strg += "Signation Type:" + getSignationType() + "\n";
+ return strg;
+ }
+
+ public Map getSigEntries() {
+ return sigEntries_;
+ }
+
+} \ No newline at end of file
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureResponse.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureResponse.java
new file mode 100644
index 0000000..0c733f6
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureResponse.java
@@ -0,0 +1,559 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: SignatureResponse.java,v 1.4 2006/08/03 07:43:04 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.sig;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.log4j.Logger;
+
+import at.gv.egiz.pdfas.api.exceptions.PdfAsException;
+import at.knowcenter.wag.egov.egiz.cfg.ConfigLogger;
+import at.knowcenter.wag.egov.egiz.cfg.PropertyTree;
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.exceptions.SettingNotFoundException;
+import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
+import at.knowcenter.wag.egov.egiz.exceptions.SignatureException;
+
+/**
+ * The response of a verification.
+ *
+ * @author wlackner
+ */
+public class SignatureResponse
+{
+ /**
+ * The siganture response config key
+ */
+ private static String SIG_RESP_KEY = "signature.response.";
+
+ /**
+ * Default response message
+ */
+ private static String SIG_RESP_DEFAULT_INFO = "Es ist leider keine nähere Information verfügbar:";
+
+ /**
+ * Response value for x509SubjectName_
+ */
+ private String x509SubjectName_ = null;
+
+ /**
+ * Response value for x509IssuerName
+ */
+ private String x509IssuerName = null;
+
+ /**
+ * Response value for x509SerialNumber
+ */
+ private String x509SerialNumber = null;
+
+ /**
+ * Response value for signatureCheckCode_
+ */
+ private String signatureCheckCode_ = null;
+
+ /**
+ * Response value for signatureCheckInfo_
+ */
+ private String signatureCheckInfo_ = null;
+
+ /**
+ * Response value for signatureManifestCheckCode_
+ */
+ private String signatureManifestCheckCode_ = null;
+
+ /**
+ * Response value for signatureManifestCheckInfo_
+ */
+ private String signatureManifestCheckInfo_ = null;
+
+ /**
+ * Response value for certificateCheckCode_
+ */
+ private String certificateCheckCode_ = null;
+
+ /**
+ * Response value for certificateCheckInfo_
+ */
+ private String certificateCheckInfo_ = null;
+
+ /**
+ * The X.509 certificated parsed from the response string.
+ */
+ protected X509Cert certificate_ = null;
+
+ // [tknall] start qualified certificate
+ private boolean qualifiedCertificate = false;
+ // [tknall] stop qualified certificate
+
+ private boolean publicAuthority = false;
+ private String publicAuthorityCode = null;
+
+ protected String hashInputData = null;
+
+ private PdfAsException verificationImpossibleEx = null;
+
+ // /**
+ // * Flag the marks that the response is an error response
+ // */
+ // private boolean isError_ = false;
+ //
+ // /**
+ // * The error code of an external application
+ // */
+ // private String errorCode_ = null;
+
+ /**
+ * The SettingsReader instance
+ */
+ private SettingsReader settings_ = null;
+
+ /**
+ * The logger definition.
+ */
+ private static final Logger logger_ = ConfigLogger.getLogger(SignatureResponse.class);
+
+ /**
+ *
+ *
+ */
+ public SignatureResponse()
+ {
+ try
+ {
+ loadSettings();
+ }
+ catch (SignatureException e)
+ {
+ logger_.warn(e.getMessage(), e);
+ }
+ }
+
+ /**
+ * load the inital signature settings
+ *
+ * @throws SignatureException
+ * @see SettingsReader
+ */
+ private void loadSettings() throws SignatureException
+ {
+ if (settings_ == null)
+ {
+ try
+ {
+ settings_ = SettingsReader.getInstance();
+ }
+ catch (SettingsException e)
+ {
+ String log_message = "Can not load signature settings. Cause:\n" + e.getMessage();
+ logger_.error(log_message);
+ throw new SignatureException(101, log_message, e);
+ }
+ }
+ }
+
+ /**
+ * @return Returns the certificateCheckCode.
+ */
+ public String getCertificateCheckCode()
+ {
+ return certificateCheckCode_;
+ }
+
+ /**
+ * @param certificateCheckCode
+ * The certificateCheckCode to set.
+ */
+ public void setCertificateCheckCode(String certificateCheckCode)
+ {
+ if (logger_.isDebugEnabled())
+ {
+ logger_.debug("setCertificateCheckCode:" + certificateCheckCode);
+ }
+ certificateCheckCode_ = certificateCheckCode;
+ }
+
+ /**
+ * @return Returns the signatureCheckCode.
+ */
+ public String getSignatureCheckCode()
+ {
+ return signatureCheckCode_;
+ }
+
+ /**
+ * @param signatureCheckCode
+ * The signatureCheckCode to set.
+ */
+ public void setSignatureCheckCode(String signatureCheckCode)
+ {
+ if (logger_.isDebugEnabled())
+ {
+ logger_.debug("setSignatureCheckCode:" + signatureCheckCode);
+ }
+ signatureCheckCode_ = signatureCheckCode;
+ }
+
+ /**
+ * @return Returns the signatureManifestCheckCode.
+ */
+ public String getSignatureManifestCheckCode()
+ {
+ return signatureManifestCheckCode_;
+ }
+
+ /**
+ * Returns {@code true} if the underlying certificate indicates public authority.
+ * @return {@code true} if public authority, {@code false} if not.
+ */
+ public boolean isPublicAuthority() {
+ return this.publicAuthority;
+ }
+
+ /**
+ * Sets the public authority flag.
+ * @param publicAuthority The public authority flag.
+ */
+ public void setPublicAuthority(boolean publicAuthority) {
+ this.publicAuthority = publicAuthority;
+ }
+
+ /**
+ * Returns the public authority code of {@code null} if no code was provided.
+ * @return The public authority code.
+ */
+ public String getPublicAuthorityCode() {
+ return this.publicAuthorityCode;
+ }
+
+ /**
+ * Sets the public authority code.
+ * @param publicAuthorityCode The public authority code.
+ */
+ public void setPublicAuthorityCode(String publicAuthorityCode) {
+ this.publicAuthorityCode = publicAuthorityCode;
+ }
+
+/**
+ * @param signatureManifestCheckCode
+ * The signatureManifestCheckCode to set.
+ */
+ public void setSignatureManifestCheckCode(String signatureManifestCheckCode)
+ {
+ if (logger_.isDebugEnabled())
+ {
+ logger_.debug("setSignatureManifestCheckCode:" + signatureManifestCheckCode);
+ }
+ signatureManifestCheckCode_ = signatureManifestCheckCode;
+ }
+
+ /**
+ * @return Returns the x509IssuerName.
+ */
+ public String getX509IssuerName()
+ {
+ return x509IssuerName;
+ }
+
+ /**
+ * @param issuerName
+ * The x509IssuerName to set.
+ */
+ public void setX509IssuerName(String issuerName)
+ {
+ if (logger_.isDebugEnabled())
+ {
+ logger_.debug("setX509IssuerName:" + issuerName);
+ }
+ x509IssuerName = issuerName;
+ }
+
+ /**
+ * @return Returns the x509SerialNumber.
+ */
+ public String getX509SerialNumber()
+ {
+ return x509SerialNumber;
+ }
+
+ /**
+ * @param serialNumber
+ * The x509SerialNumber to set.
+ */
+ public void setX509SerialNumber(String serialNumber)
+ {
+ if (logger_.isDebugEnabled())
+ {
+ logger_.debug("setX509SerialNumber:" + serialNumber);
+ }
+ x509SerialNumber = serialNumber;
+ }
+
+ /**
+ * @return Returns the x509SubjectName.
+ */
+ public String getX509SubjectName()
+ {
+ return x509SubjectName_;
+ }
+
+ /**
+ * @param subjectName
+ * The x509SubjectName to set.
+ */
+ public void setX509SubjectName(String subjectName)
+ {
+ if (logger_.isDebugEnabled())
+ {
+ logger_.debug("setX509SubjectName:" + subjectName);
+ }
+ x509SubjectName_ = subjectName;
+ }
+
+ /**
+ * @return Returns the certificateCheckInfo.
+ */
+ public String getCertificateCheckInfo()
+ {
+ if (certificateCheckInfo_ == null)
+ {
+ if (settings_ != null)
+ {
+ certificateCheckInfo_ = settings_.getValueFromKey(SIG_RESP_KEY + "certificateCheckInfo." + getCertificateCheckCode());
+ }
+ }
+ if (certificateCheckInfo_ == null)
+ {
+ certificateCheckInfo_ = SIG_RESP_DEFAULT_INFO + getCertificateCheckCode();
+ }
+ return certificateCheckInfo_;
+ }
+
+ /**
+ * @param certificateCheckInfo
+ * The certificateCheckInfo to set.
+ */
+ public void setCertificateCheckInfo(String certificateCheckInfo)
+ {
+ if (logger_.isDebugEnabled())
+ {
+ logger_.debug("setCertificateCheckInfo:" + certificateCheckInfo);
+ }
+ certificateCheckInfo_ = certificateCheckInfo;
+ }
+
+ // [tknall] start qualified certificate
+
+ /**
+ * Returns <code>true</code> if certificate is qualified, <code>false</code> if not.
+ * @return <code>true</code> if certificate is qualified, <code>false</code> if not.
+ */
+ public boolean isQualifiedCertificate() {
+ return this.qualifiedCertificate;
+ }
+
+ /**
+ * Sets the flag for qualified certificate.
+ * @param qualifiedCertificate The new qualified certificate status.
+ */
+ public void setQualifiedCertificate(boolean qualifiedCertificate) {
+ this.qualifiedCertificate = qualifiedCertificate;
+ }
+ // [tknall] stop qualified certificate
+
+ /**
+ * @return Returns the signatureCheckInfo.
+ */
+ public String getSignatureCheckInfo()
+ {
+ if (signatureCheckInfo_ == null)
+ {
+ if (settings_ != null)
+ {
+ signatureCheckInfo_ = settings_.getValueFromKey(SIG_RESP_KEY + "signatureCheckInfo." + getSignatureCheckCode());
+ }
+ }
+ if (signatureCheckInfo_ == null)
+ {
+ signatureCheckInfo_ = SIG_RESP_DEFAULT_INFO + getSignatureCheckCode();
+ }
+ return signatureCheckInfo_;
+ }
+
+ /**
+ * @param signatureCheckInfo
+ * The signatureCheckInfo to set.
+ */
+ public void setSignatureCheckInfo(String signatureCheckInfo)
+ {
+ if (logger_.isDebugEnabled())
+ {
+ logger_.debug("setSignatureCheckInfo:" + signatureCheckInfo);
+ }
+ signatureCheckInfo_ = signatureCheckInfo;
+ }
+
+ /**
+ * @return Returns the signatureManifestCheckInfo.
+ */
+ public String getSignatureManifestCheckInfo()
+ {
+ if (signatureManifestCheckInfo_ == null)
+ {
+ if (settings_ != null)
+ {
+ signatureManifestCheckInfo_ = settings_.getValueFromKey(SIG_RESP_KEY + "signatureManifestCheckInfo." + getSignatureManifestCheckCode());
+ }
+ }
+ if (signatureManifestCheckInfo_ == null)
+ {
+ signatureManifestCheckInfo_ = SIG_RESP_DEFAULT_INFO + getSignatureManifestCheckCode();
+ }
+ return signatureManifestCheckInfo_;
+ }
+
+ /**
+ * @param signatureManifestCheckInfo
+ * The signatureManifestCheckInfo to set.
+ */
+ public void setSignatureManifestCheckInfo(String signatureManifestCheckInfo)
+ {
+ if (logger_.isDebugEnabled())
+ {
+ logger_.debug("setSignatureManifestCheckInfo:" + signatureManifestCheckInfo);
+ }
+ signatureManifestCheckInfo_ = signatureManifestCheckInfo;
+ }
+
+ /**
+ * Returns the X.509 certificate of this response.
+ *
+ * @return Returns the X.509 certificate of this response.
+ */
+ public X509Cert getCertificate()
+ {
+ return certificate_;
+ }
+
+ /**
+ * Sets the X.509 certificate of this response.
+ *
+ * @param certificate
+ * The X.509 certificate to be set.
+ */
+ public void setCertificate(X509Cert certificate)
+ {
+ this.certificate_ = certificate;
+ }
+
+ public String getHashInputData()
+ {
+ return this.hashInputData;
+ }
+
+ public void setHashInputData(String hashInputData)
+ {
+ this.hashInputData = hashInputData;
+ }
+
+ public PdfAsException getVerificationImpossibleEx() {
+ return verificationImpossibleEx;
+ }
+
+ public void setVerificationImpossibleEx(PdfAsException verificationImpossibleEx) {
+ this.verificationImpossibleEx = verificationImpossibleEx;
+ }
+
+/**
+ * Returns a list of Strings each stating one public property of the
+ * certificate.
+ *
+ * <p>
+ * 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".
+ * </p>
+ * <p>
+ * This methods reads out the list of possible properties from the config file
+ * and compares these to the extensions defined on the certificate. If they
+ * match, a String containing useful information about the property is added
+ * to the list returned.
+ * </p>
+ *
+ * @return Returns the list of Strings representing the public properties of
+ * this certificate, if any.
+ * @throws SettingNotFoundException
+ */
+ public List getPublicProperties() throws SettingNotFoundException
+ {
+ List props = new ArrayList();
+
+ SettingsReader settings = this.settings_;
+
+ String root_oid = settings.getSetting("oid.root");
+
+ PropertyTree oids = settings.getPTree().getSubTree("oid");
+
+ Set non_critial_oids = this.certificate_.getX509Certificate().getNonCriticalExtensionOIDs();
+ Iterator ext_it = non_critial_oids.iterator();
+ while (ext_it.hasNext())
+ {
+ String oid = (String) ext_it.next();
+
+ if (oid.startsWith(root_oid))
+ {
+ String key = oid.replaceAll("\\.", "_");
+
+ String value = oids.getLastValue(key);
+ if (value == null)
+ {
+ value = oid;
+ }
+
+ props.add(value);
+ }
+ }
+
+ return props;
+ }
+
+ /**
+ * The toString method
+ */
+ public String toString()
+ {
+ String str = "";
+ str += "\nSignator:" + getX509SubjectName();
+ str += "\nAusteller:" + getX509IssuerName();
+ str += "\nSeriennummer:" + getX509SerialNumber();
+ str += "\nZertifikat-Code:" + getCertificateCheckCode() + "=" + getCertificateCheckInfo();
+ str += "\nSignatur-Check-Code:" + getSignatureCheckCode() + "=" + getSignatureCheckInfo();
+ str += "\nManifest-Check-Code:" + getSignatureManifestCheckCode() + "=" + getSignatureManifestCheckInfo();
+ return str;
+ }
+} \ No newline at end of file
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureSeparator.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureSeparator.java
new file mode 100644
index 0000000..5b80490
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureSeparator.java
@@ -0,0 +1,146 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: SignatureSeparator.java,v 1.4 2006/10/31 08:18:56 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.sig;
+
+import java.util.List;
+import java.util.Stack;
+
+import at.knowcenter.wag.egov.egiz.exceptions.SignatureException;
+import at.knowcenter.wag.egov.egiz.exceptions.SignatureTypesException;
+
+/**
+ * This class separates all signature blocks in a raw text.
+ * @deprecated This process of separating signature blocks is obsolete - use AbsoluteTextSignature etc. instead.
+ */
+public class SignatureSeparator {
+ /**
+ * The signature block stack. On top of the stack is the first signature block that can be
+ * extracted. First means nearest to the document text.
+ */
+ private Stack signatureBlocks_ = null;
+ /**
+ * A list of signature type definitions.
+ */
+ private List signatureTypes_ = null;
+ /**
+ * Indicator that shows that a raw text is signated
+ */
+ private boolean hasSignatureBlock_ = false;
+
+ /**
+ * The empty constructor. It loads all signature type infos to extract the signature block from
+ * the raw text.
+ *
+ * @throws SignatureTypesException
+ */
+ public SignatureSeparator() throws SignatureTypesException {
+ SignatureTypes sig_types = SignatureTypes.getInstance();
+ signatureTypes_ = sig_types.getSignatureTypeDefinitions();
+ }
+
+ /**
+ * This method takes a raw text as input and trys to separate all signature blocks. It returns
+ * true if a signature block is found.
+ *
+ * @param rawText
+ * @return true if a signature block is found false otherwise
+ */
+ public boolean separateBlock(String rawText) {
+ signatureBlocks_ = new Stack();
+ hasSignatureBlock_ = separateBlock(rawText, rawText.length());
+ return hasSignatureBlock_;
+ }
+
+ /**
+ * This method calls itself rekursively while signature blocks can be extracted. If a signature
+ * block is found (search from the bottom of the raw text) the raw text would be reduced by the
+ * length of the found signature block text.
+ *
+ * @param rawText the text to be separated
+ * @param endIndex the index to cut the tail from the raw text
+ * @return true if a signature block is found false otherwise
+ */
+ private boolean separateBlock(String rawText, int endIndex) {
+ boolean found = false;
+ boolean can_separate = true;
+ while (can_separate) {
+ SignatureBlock sig_block = new SignatureBlock(signatureTypes_);
+ String raw_text = rawText.substring(0, endIndex);
+ can_separate = sig_block.separateBlockFromRawText(raw_text, true);
+ if (can_separate) {
+ signatureBlocks_.push(sig_block);
+ endIndex = sig_block.getStartIndex();
+ found = true;
+ }
+ }
+ return found;
+ }
+
+ /**
+ * This method returns the start index of the first signature block. It is used to separate the
+ * real document text from the signature block texts.
+ *
+ * @return the start index of the first signature block
+ */
+ public int getStartIndex() {
+ int start_index = -1;
+ if (signatureBlocks_ != null && signatureBlocks_.size() > 0) {
+ SignatureBlock sig_block = (SignatureBlock) signatureBlocks_.peek();
+ return sig_block.getStartIndex();
+ }
+ return start_index;
+ }
+
+ /**
+ * @return the first found signature object in the given raw text or null if the raw text does not
+ * contain any signature objects
+ */
+ public SignatureObject getFirstSignatureObject() {
+ if (signatureBlocks_ != null && signatureBlocks_.size() > 0) {
+ SignatureBlock sig_block = (SignatureBlock) signatureBlocks_.peek();
+ try {
+ return sig_block.getSignatureObject();
+ } catch (SignatureException e) {
+ return null;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @return all separated signature blocks as stack, first is on top
+ */
+ public Stack getSignatureBlocks() {
+ return signatureBlocks_;
+ }
+
+ /**
+ * @return true if a signature block is found false otherwise
+ */
+ public boolean hasSignatureBlock() {
+ return hasSignatureBlock_;
+ }
+} \ No newline at end of file
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureTypeDefinition.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureTypeDefinition.java
new file mode 100644
index 0000000..de099bf
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureTypeDefinition.java
@@ -0,0 +1,605 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: SignatureTypeDefinition.java,v 1.3 2006/08/25 17:09:41 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.sig;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
+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 at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.exceptions.SignatureException;
+
+public class SignatureTypeDefinition implements Serializable
+{
+
+ /**
+ * SVUID.
+ */
+ private static final long serialVersionUID = 1327407307346061147L;
+
+ /**
+ * The log.
+ */
+ private static final Log logger_ = LogFactory.getLog(SignatureTypeDefinition.class);
+
+ /**
+ * The type of this definition
+ */
+ protected String type_ = null;
+
+ /**
+ * A map of all key to caption tupls.
+ */
+ private Map keyCaptionMap_ = new HashMap();
+
+ /**
+ * A map of all key to value tupls.
+ */
+ private Map keyValueMap_ = new HashMap();
+
+ /**
+ * A list of sorted keys
+ */
+ private Vector sortedKeys_ = null;
+
+ /**
+ * A list of sorted captions
+ */
+ private Vector sortedCaptions_ = null;
+
+ /**
+ * A revert of sorted keys
+ */
+ private Vector revertSortedKeys_ = new Vector();
+
+ /**
+ * A revert list of sorted captions
+ */
+ private Vector revertSortedCaptions_ = new Vector();
+
+ /**
+ * The settings reader reference
+ */
+ private SettingsReader settings_ = null;
+
+ /**
+ * List of (visible) field definitions.
+ */
+ protected Map field_definitions_ = null;
+
+ /**
+ * List of invisible field definitions.
+ *
+ * <p>
+ * If empty, all definitions are visible.
+ * </p>
+ */
+ protected Map invisible_field_definitions = null;
+
+
+
+ /**
+ * The constructor of the signature type definition. It reads the configured
+ * table definition of the signature block and load the type definition of a
+ * given type.
+ *
+ * @param settings
+ * a SettingsReader instance
+ * @param type
+ * the signature type to load
+ * @throws SignatureException
+ * @see SettingsReader
+ */
+ public SignatureTypeDefinition(SettingsReader settings, String type) throws SignatureException
+ {
+ settings_ = settings;
+ type_ = type;
+ readSigTable(SignatureTypes.MAIN_TABLE);
+ loadTypeDefinition();
+ readFieldDefinitions();
+ readInvisibleFieldDefinitions();
+ }
+
+ protected void readInvisibleFieldDefinitions()
+ {
+ this.invisible_field_definitions = new HashMap();
+ for (int i = 0; i < SignatureTypes.REQUIRED_SIG_KEYS.length; i++)
+ {
+ String requiredKey = SignatureTypes.REQUIRED_SIG_KEYS[i];
+ if (!this.sortedKeys_.contains(requiredKey))
+ {
+ SignatureFieldDefinition sfd = readFieldDefinition(requiredKey);
+ this.invisible_field_definitions.put(sfd.field_name, sfd);
+ }
+ }
+ }
+
+ /**
+ * Returns the List of invisible field definitions, if any.
+ *
+ * <p>
+ * Invisible field definitions are the field definitions of required fields that are not explicitely specified in the signature profile.
+ * </p>
+ * <p>
+ * Note that the concept of invisible fields can only be used by binary signatures.
+ * </p>
+ *
+ * @return Returns the List of invisible field definitions, if any.
+ */
+ public List getInvisibleFieldDefinitions()
+ {
+ return new ArrayList(this.invisible_field_definitions.values());
+ }
+
+ /**
+ * Tells, if the signature type is text-extractable, which means that all required fields are visible.
+ *
+ * @return Returns true, if the signature type is text-extractable.
+ */
+ public boolean isTextExtractable()
+ {
+ if (logger_.isDebugEnabled()) {
+ Iterator it = this.invisible_field_definitions.values().iterator();
+ StringBuffer buffer = new StringBuffer();
+ while (it.hasNext()) {
+ SignatureFieldDefinition sfd = (SignatureFieldDefinition) it.next();
+ buffer.append(sfd.field_name);
+ if (it.hasNext()) {
+ buffer.append(", ");
+ }
+ }
+ if (buffer.length() != 0) {
+ logger_.debug("Invisible field definitions for profile \"" + this.type_ + "\" = " + buffer.toString());
+ }
+ }
+ return this.invisible_field_definitions.isEmpty();
+ }
+
+ /**
+ * Load the configured signature type definitions. It reads all key-captions
+ * tupls that are used in the signature table. It also reads all key-value
+ * tupls.
+ *
+ * @throws SignatureException
+ */
+ private void loadTypeDefinition() throws SignatureException
+ {
+ if (sortedKeys_ == null)
+ {
+ sortKeys();
+ }
+
+ String key_prefix = SignatureTypes.SIG_OBJ + type_ + ".key";
+ ArrayList keys = settings_.getKeys(key_prefix);
+ if (keys == null)
+ {
+ // exthex: no exception to enable invisible signatures
+ logger_.debug("There is no key defined for type:" + type_ +". assuming invisible signature");
+ return;
+// keep this incredible wprinz(?) lines as a puzzle: Can anyone do same thing in just one line?
+// SignatureException se = new SignatureException(100, "There is no key defined for type:" + type_);
+// ;
+// throw se;
+ }
+ for (int key_idx = 0; key_idx < keys.size(); key_idx++)
+ {
+ String sig_key = (String) keys.get(key_idx);
+ String sig_key_val = settings_.getValueFromKey(key_prefix + "." + sig_key);
+ if (sortedKeys_.contains(sig_key))
+ {
+ keyCaptionMap_.put(sig_key, sig_key_val);
+ }
+ }
+ String value_prefix = SignatureTypes.SIG_OBJ + type_ + ".value";
+ ArrayList values = settings_.getKeys(value_prefix);
+ if (values != null)
+ {
+ for (int key_idx = 0; key_idx < values.size(); key_idx++)
+ {
+ String val_key = (String) values.get(key_idx);
+ String val_key_val = settings_.getValueFromKey(value_prefix + "." + val_key);
+ keyValueMap_.put(val_key, val_key_val);
+ }
+ }
+ }
+
+ /**
+ * This method reads the table definition of singature type. It takes care
+ * about the linearization of the defined key-value pairs or sub tables. The
+ * linearisation is done reading a table from left to right and top to bottom.
+ * A sub table is alwais a normal cell element in the linearisation prozess.
+ * If a sub table exists therefore the linearisation of the subtable is taken
+ * es cell element in the parent table. t This method stores a revert sorted
+ * linearisation list of used keys in the table. This method is called
+ * recursivley if defined nested tables.
+ *
+ * @param tableKey
+ * the name of the table definition
+ */
+ private void readSigTable(String tableKey)
+ {
+ // System.err.println("read table:" + type_ + "." + tableKey);
+ String table_key_prefix = SignatureTypes.SIG_OBJ + type_ + "." + SignatureTypes.TABLE;
+ String table_key = table_key_prefix + tableKey;
+ String key_prefix = SignatureTypes.SIG_OBJ + type_ + ".key.";
+
+ // ArrayList table_def_keys = settings_.getKeys(table_key);
+ Vector table_def_keys = settings_.getSettingKeys(table_key);
+ if (table_def_keys != null)
+ {
+ for (int table_key_idx = 0; table_key_idx < table_def_keys.size(); table_key_idx++)
+ {
+ String table_row_id = (String) table_def_keys.get(table_key_idx);
+ String table_def_keys_name = table_key + "." + table_row_id;
+ String table_def_string = settings_.getValueFromKey(table_def_keys_name);
+ if (table_row_id.matches("\\D*"))
+ {
+ continue;
+ }
+ if (table_def_string != null)
+ {
+ // analyse the row definition
+ String[] elems = table_def_string.split("\\|");
+ // ArrayList row = new ArrayList();
+ int elem_idx = elems.length;
+ while (elem_idx > 0)
+ {
+ elem_idx--;
+ String elem = elems[elem_idx];
+ String[] key_type = elem.split("-");
+ if (key_type.length < 2)
+ {
+ return;
+ }
+ String key = key_type[0];
+ String type = key_type[1];
+ // System.err.println("key:" + type_ + "." + tableKey +
+ // "." + key + "=" + type);
+
+ if (SignatureTypes.TYPE_TABLE.equals(key))
+ {
+ // read sub table
+ readSigTable(type);
+ }
+ if (SignatureTypes.TYPE_IMAGE.equals(type))
+ {
+ // ignore images
+ }
+ if (SignatureTypes.TYPE_VALUE.equals(type))
+ {
+ String sig_key_val = settings_.getValueFromKey(key_prefix + key);
+ if (sig_key_val != null)
+ {
+ revertSortedKeys_.add(key);
+ revertSortedCaptions_.add(sig_key_val);
+ }
+ // ignore values without caption
+ }
+ if ((SignatureTypes.TYPE_VALUE + SignatureTypes.TYPE_CAPTION).equals(type) || (SignatureTypes.TYPE_CAPTION + SignatureTypes.TYPE_VALUE).equals(type))
+ {
+ String sig_key_val = settings_.getValueFromKey(key_prefix + key);
+ if (sig_key_val != null)
+ {
+ revertSortedKeys_.add(key);
+ revertSortedCaptions_.add(sig_key_val);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * @return Returns the keys.
+ */
+ public Map getKeyCaptionMap()
+ {
+ return keyCaptionMap_;
+ }
+
+ /**
+ * @return Returns the keyValueMap.
+ */
+ public Map getKeyValueMap()
+ {
+ return keyValueMap_;
+ }
+
+ /**
+ * Returns a caption to a given key
+ *
+ * @param key
+ * @return the caption or null if the key is not found
+ */
+ public String getCaptionFromKey(String key)
+ {
+ return (String) keyCaptionMap_.get(key);
+ }
+
+ /**
+ * Returns a value to given key
+ *
+ * @param key
+ * @return the value or null if the key is not found
+ */
+ public String getValueFromKey(String key)
+ {
+ return (String) keyValueMap_.get(key);
+ }
+
+ /**
+ * @return Returns the sortedKeys.
+ */
+ public Vector getSortedKeys()
+ {
+ if (sortedKeys_ == null)
+ {
+ sortKeys();
+ }
+ return sortedKeys_;
+ }
+
+ /**
+ * @return Returns the sortedCaptions.
+ */
+ public Vector getSortedCaptions()
+ {
+ if (sortedCaptions_ == null)
+ {
+ sortKeys();
+ }
+ return sortedCaptions_;
+ }
+
+ /**
+ * @return Returns the revertSortedCaptions.
+ */
+ public Vector getRevertSortedCaptions()
+ {
+ return revertSortedCaptions_;
+ }
+
+ /**
+ * @return Returns the revertSortedKeys.
+ */
+ public Vector getRevertSortedKeys()
+ {
+ return revertSortedKeys_;
+ }
+
+ /**
+ * This method sort the reverted sorted key-caption and key-value lists.
+ *
+ */
+ private void sortKeys()
+ {
+ // String key_prefix = SignatureTypes.SIG_OBJ + type_ + ".key.";
+ sortedKeys_ = new Vector(revertSortedKeys_.size());
+ sortedCaptions_ = new Vector(revertSortedCaptions_.size());
+ for (int key_idx = revertSortedKeys_.size() - 1; key_idx >= 0; key_idx--)
+ {
+ sortedKeys_.add(revertSortedKeys_.get(key_idx));
+ sortedCaptions_.add(revertSortedCaptions_.get(key_idx));
+ }
+ }
+
+ /**
+ * This method checks if a given key is defined.
+ *
+ * @param key
+ * to find
+ * @return true if the key is find false otherwise
+ */
+ public boolean contains(String key)
+ {
+ return (keyValueMap_.get(key) != null);
+ }
+
+ /**
+ * The standard toString method. Used for internal tests only.
+ */
+ public String toString()
+ {
+ String strg = this.type_ + "\n";
+ Vector sk = getSortedKeys();
+ Vector sc = getSortedCaptions();
+ for (int i = 0; i < sk.size(); i++)
+ {
+ strg += sk.get(i) + "=" + sc.get(i) + "\n";
+ }
+ return strg;
+ }
+
+ /**
+ * @return Returns the signature type string.
+ */
+ public String getType()
+ {
+ return type_;
+ }
+
+ /**
+ * @return Returns the signature type description.
+ */
+ public String getDescription()
+ {
+ String descr_key = SignatureTypes.SIG_OBJ + type_ + ".description";
+ return settings_.getValueFromKey(descr_key);
+ }
+
+ protected String getSettingsKeyBase()
+ {
+ return getSettingsKeyBase(type_);
+ }
+
+ /**
+ * Gets the field definition of the given Field.
+ *
+ * @param field_name
+ * The name of the field.
+ * @return Returns the field's definition.
+ */
+ public SignatureFieldDefinition readFieldDefinition(String field_name)
+ {
+ SignatureFieldDefinition sfd = new SignatureFieldDefinition();
+
+ sfd.field_name = field_name;
+ sfd.caption = this.settings_.getValueFromKey(getSettingsKeyBase() + ".key." + field_name);
+ sfd.value = this.settings_.getValueFromKey(getSettingsKeyBase() + ".value." + field_name);
+ //sfd.value = this.settings_.getValueFromKey(getSettingsKeyBase() + type_ + ".value." + field_name);
+ sfd.placeholder_length = -1;
+ String phlen_str = readPhLenStringFromSettings(this.settings_, this.type_, field_name);
+ if (phlen_str != null)
+ {
+ sfd.placeholder_length = Integer.parseInt(phlen_str);
+ }
+
+ return sfd;
+ }
+
+ protected static String getSettingsKeyBase (String type)
+ {
+ return SignatureTypes.SIG_OBJ + type;
+ }
+
+ public static String readPhLenStringFromSettings(SettingsReader settings, String profile, String field_name)
+ {
+ String phlen_str = settings.getValueFromKey(getSettingsKeyBase(profile) + ".phlength." + field_name);
+ if (phlen_str == null)
+ {
+ phlen_str = settings.getValueFromKey("defaults.phlength." + field_name);
+ }
+ return phlen_str;
+ }
+
+ protected void readFieldDefinitions()
+ {
+ this.field_definitions_ = new HashMap();
+ for (int i = 0; i < this.sortedKeys_.size(); i++)
+ {
+ String key = (String) this.sortedKeys_.get(i);
+ SignatureFieldDefinition sfd = readFieldDefinition(key);
+ // sfd.brev = SignatureTypes.ALL_SIG_BREV[i];
+ this.field_definitions_.put(sfd.field_name, sfd);
+ }
+ }
+
+ /**
+ * Returns the list of field definitions of this Signature profile.
+ *
+ * @return Returns the list of field definitions of this Signature profile.
+ */
+ public List getFieldDefinitions()
+ {
+ return new ArrayList(this.field_definitions_.values());
+ }
+
+ /**
+ * Tells if this signature profile is semantically equal to the other
+ * signature profile.
+ *
+ * <p>
+ * One profile is semantically equal to another one if the captions and keys
+ * of both profiles are equal and have the same order.
+ * </p>
+ *
+ * @param other
+ * The other signature profile.
+ * @return Returns true, if this profile is semantically equivalent to the
+ * other profile.
+ */
+ public boolean isSemanticallyEqual(SignatureTypeDefinition other)
+ {
+ List this_keys = filterOutNonRequiredFoundKeys(this.sortedKeys_);
+ List other_keys = filterOutNonRequiredFoundKeys(other.sortedKeys_);
+
+ if (this_keys.size() != other_keys.size())
+ {
+ return false;
+ }
+
+ for (int i = 0; i < this_keys.size(); i++)
+ {
+ String this_key = (String) this_keys.get(i);
+ String other_key = (String) other_keys.get(i);
+
+ if (!this_key.equals(other_key))
+ {
+ return false;
+ }
+
+ String this_caption = this.getCaptionFromKey(this_key);
+ String other_caption = other.getCaptionFromKey(other_key);
+
+ if (!this_caption.equals(other_caption))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Filters out all non required keys from the List of keys.
+ *
+ * @param keys The List of keys.
+ *
+ * @return Returns the subset List which contains only the required keys.
+ */
+ protected static List filterOutNonRequiredFoundKeys (List keys)
+ {
+ List required_keys = new ArrayList(keys.size());
+ for (int i = 0; i < keys.size(); i++)
+ {
+ String this_key = (String) keys.get(i);
+
+ if (!SignatureTypes.isRequiredKey(this_key))
+ {
+ continue;
+ }
+
+ required_keys.add(this_key);
+ }
+ return required_keys;
+ }
+
+ public SignatureFieldDefinition getSignatureFieldDefinition(String key) {
+ SignatureFieldDefinition res = (SignatureFieldDefinition) this.field_definitions_.get(key);
+ if (res == null) {
+ res = (SignatureFieldDefinition) this.invisible_field_definitions.get(key);
+ }
+ return res;
+ }
+} \ No newline at end of file
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureTypes.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureTypes.java
new file mode 100644
index 0000000..783512c
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/SignatureTypes.java
@@ -0,0 +1,515 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: SignatureTypes.java,v 1.5 2006/10/31 08:18:56 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.sig;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.log4j.Logger;
+
+import at.knowcenter.wag.egov.egiz.cfg.ConfigLogger;
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+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.exactparser.ByteArrayUtils;
+
+public class SignatureTypes
+{
+
+// 03.11.2010 changed by exthex - commented unneeded setDefaultStyles method to reduce confusion
+
+ /**
+ * The settings key prefix for signature definitions. <code>"sig_obj."</code>
+ */
+ public static final String SIG_OBJ = "sig_obj.";
+
+ /**
+ * The settings key prefix for signature object types
+ */
+ public static final String TYPES = SIG_OBJ + "types";
+
+ /**
+ * The settings key prefix for the default signature object type
+ */
+ public static final String DEFAULT_TYPE = SIG_OBJ + "type.default";
+
+ /**
+ * The settings key postfix for the type description
+ */
+ public static final String SIG_DESCR = "description";
+
+ /**
+ * The state value activating an signature definition
+ */
+ private static final String STATE_ON = "on";
+
+ // /**
+ // * The state value de activating an signature definition
+ // */
+ // private static final String STATE_OFF = "off";
+
+ /**
+ * The settings key prefix for the signature table object definition
+ */
+ public static final String TABLE = "table.";
+
+ /**
+ * The settings key sub prefix getting the main table definition
+ */
+ public static final String MAIN_TABLE = "main";
+
+ /**
+ * The settings value refering to a table
+ */
+ public final static String TYPE_TABLE = "TABLE";
+
+ /**
+ * The settings value refering to an image
+ */
+ public final static String TYPE_IMAGE = "i";
+
+ /**
+ * The settings value refering to a text caption
+ */
+ public final static String TYPE_CAPTION = "c";
+
+ /**
+ * The settings value refering to a text value
+ */
+ public final static String TYPE_VALUE = "v";
+
+ /**
+ * The settings key sub prefix getting the width of columns for a table
+ * definition
+ */
+ public final static String COLS_WITH = "ColsWidth";
+
+ /**
+ * The settings key sub prefix getting the style definition
+ */
+ public final static String STYLE = "Style";
+
+// /**
+// * The default style definition for images.
+// */
+// private Style defaultImageStyle_ = new Style();
+//
+// /**
+// * The default style definition for captions.
+// */
+// private Style defaultCaptionStyle_ = new Style();
+//
+// /**
+// * The default style definition for values.
+// */
+// private Style defaultValueStyle_ = new Style();
+
+ /**
+ * Standard key get/set the singature name
+ */
+ public static final String SIG_NAME = "SIG_NAME";
+
+ /**
+ * Standard key get/set the signature date
+ */
+ public static final String SIG_DATE = "SIG_DATE";
+
+ /**
+ * Standard key get/set the signator issuer
+ */
+ public static final String SIG_ISSUER = "SIG_ISSUER";
+
+ /**
+ * Standard key get/set the siganture value
+ */
+ public static final String SIG_VALUE = "SIG_VALUE";
+
+ /**
+ * Standard key get/set the normalisation method used
+ */
+ public static final String SIG_NORM = "SIG_NORM";
+
+ /**
+ * Standard key get/set the signation id's used by BKU signated documents
+ */
+ public static final String SIG_ID = "SIG_ID";
+
+ /**
+ * The EGIZ Algorithm "Kennzeichnung".
+ */
+ public static final String SIG_KZ = "SIG_KZ";
+
+ /**
+ * Standard key get/set the reference to the signature label (image mark)
+ */
+ public static final String SIG_LABEL = "SIG_LABEL";
+
+ /**
+ * Standard key get/set the serial number of the signature
+ */
+ public static final String SIG_NUMBER = "SIG_NUMBER";
+
+ // public static final String SIG_TYPE = "SIG_TYPE";
+ /**
+ * Standard key get/set the signature meta informations
+ */
+ public static final String SIG_META = "SIG_META";
+
+ /**
+ * Standard key get/set the signature algorithm (sign + hash)
+ */
+ public static final String SIG_ALG = "SIG_ALG";
+
+ /**
+ * Standard key get/set the signature note
+ * added by rpiazzi
+ */
+ public static final String SIG_NOTE = "SIG_NOTE";
+
+
+ /**
+ * Standard key get/set the signature subject
+ * Added to be able to define static signator name within config file
+ * added by rpiazzi
+ */
+ public static final String SIG_SUBJECT = "SIG_SUBJECT";
+
+ /**
+ * The logger definition.
+ */
+ private static final Logger logger_ = ConfigLogger.getLogger(SignatureTypes.class);
+
+ // /**
+ // * The normalizer reference
+ // */
+ // private Normalizer normalizer_ = null;
+
+ /**
+ * The settings reader reference
+ */
+ private SettingsReader settings_ = null;
+
+
+ // /**
+ // * The reference to the settings property tree
+ // */
+ // private PropertyTree pTree_ = null;
+
+ // /**
+ // * The current signature type used reading and analysing the property tree
+ // */
+ // private String sigType_ = null;
+
+ // /**
+ // * List of all keys used in the current signature definition
+ // */
+ // private ArrayList sigKeys_ = null;
+
+ /**
+ * Array of required signature keys
+ */
+ // public static String[] REQUIRED_SIG_KEYS = new String[]{SIG_NAME, SIG_DATE,
+ // SIG_ISSUER, SIG_VALUE, SIG_NUMBER, SIG_ID};
+ public static String[] REQUIRED_SIG_KEYS = new String[] { SIG_DATE,
+ SIG_ISSUER, SIG_VALUE, SIG_NUMBER, SIG_ID, SIG_KZ };
+
+ /**
+ * Tells, if the given key is a required key.
+ * <p>
+ * Note that the SIG_KZ is a required key.
+ * </p>
+ * @param key The key to be tested if it is a required key.
+ * @return Returns true, if the key is required, false otherwise.
+ */
+ public static boolean isRequiredKey (String key)
+ {
+ if (key.equals(SIG_KZ))
+ {
+ return true;
+ }
+
+ for (int i = 0; i < REQUIRED_SIG_KEYS.length; i++)
+ {
+ if (key.equals(REQUIRED_SIG_KEYS[i]))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static String[] ALL_SIG_KEYS = new String[] { SIG_NAME, SIG_DATE,
+ SIG_ISSUER, SIG_VALUE, SIG_NORM, SIG_ID, SIG_LABEL, SIG_NUMBER, SIG_META , SIG_ALG, SIG_NOTE};
+
+ public static byte [][] ALL_SIG_BREV = new byte[][] { { 'n', 'a', 'm' },
+ { 'd', 'a', 't' }, { 'i', 's', 's' }, { 'v', 'a', 'l' },
+ { 'n', 'o', 'r' }, { 's', 'i', 'd' }, { 'l', 'a', 'b' },
+ { 's', 'n', 'r' }, { 'm', 'e', 't' }, { 'a', 'l', 'g' } };
+
+ // /**
+ // * Sorted representation of keys defined in rows
+ // */
+ // private ArrayList sortedSigKeys_ = new ArrayList();
+
+ // /**
+ // * Reference from signature key to there corresponding value
+ // */
+ // private Hashtable sigEntries_ = new Hashtable(8);
+
+// /**
+// * A list of all configured signature type definitions
+// */
+// private List signatureTypeDefinitions_ = new Vector();
+
+ /**
+ * A type-name to type-definition map
+ */
+ private Map typeDefMap_ = new HashMap();
+
+ // /**
+ // * A map of required keys used to reconstruct a signature block
+ // */
+ // private static HashMap requiredSigKeys_ = new HashMap();
+
+ /**
+ * A plain list of signature type names
+ */
+// ArrayList typeList_ = new ArrayList(4);
+
+ /**
+ * Used as singleton to read the singnature type definitions only one times of
+ * a session
+ */
+ private static SignatureTypes instance_ = null;
+
+ /**
+ * This is the private constructor method to provide a singleton instance of
+ * this class. It inits a normalizer, the settings reader, read the default
+ * styles and load the configured signature types.
+ *
+ * @throws SignatureTypesException
+ * @see SettingsReader
+ */
+ private SignatureTypes() throws SignatureTypesException
+ {
+ try
+ {
+ loadSettings();
+ }
+ catch (SettingsException e)
+ {
+ throw new SignatureTypesException(e);
+ }
+// setDefaultStyles();
+ loadSignatureTypes();
+ }
+
+ /**
+ * This static method returns the stored instance of this class. If the
+ * singleton does not exist, this method creates a new singleton and gives
+ * this instance back to the caller.
+ *
+ * @return the stored instance of this class
+ * @throws SignatureTypesException
+ */
+ public static SignatureTypes getInstance() throws SignatureTypesException
+ {
+ if (instance_ == null)
+ {
+ instance_ = new SignatureTypes();
+ }
+ return instance_;
+ }
+
+ /**
+ * Reloads the instance.
+ * @throws SignatureTypesException
+ */
+ public static void createInstance() throws SignatureTypesException
+ {
+ instance_ = null;
+ getInstance();
+ }
+
+ /**
+ * This method load the signature definitions
+ *
+ * @throws SettingsException
+ *
+ * @throws SettingsException
+ * ErrorCode:101
+ */
+ private void loadSettings() throws SettingsException
+ {
+ if (settings_ == null)
+ {
+ settings_ = SettingsReader.getInstance();
+ }
+ // pTree_ = settings_.getPTree();
+ }
+
+// /**
+// * This method set the default styles for images, captions and values.
+// */
+// private void setDefaultStyles()
+// {
+// defaultImageStyle_.setPadding(3);
+// defaultImageStyle_.setHAlign(Style.CENTER);
+// defaultImageStyle_.setVAlign(Style.MIDDLE);
+// defaultImageStyle_.setBgColor(new Color(255, 255, 255));
+//
+// defaultCaptionStyle_.setHAlign(Style.CENTER);
+// defaultCaptionStyle_.setVAlign(Style.MIDDLE);
+//
+// defaultValueStyle_.setVAlign(Style.MIDDLE);
+// }
+
+ /**
+ * This method load the configured signature types. It stores the definition
+ * representations only if the type is set to ON. It stores the type
+ * definition object, the definition map and the simple type name list.
+ */
+ private void loadSignatureTypes()
+ {
+ if (settings_ != null)
+ {
+ ArrayList types = settings_.getKeys(TYPES);
+ for (int type_idx = 0; type_idx < types.size(); type_idx++)
+ {
+ String type = (String) types.get(type_idx);
+ addSignatureType(type);
+ }
+ }
+ }
+
+ public void removeSignatureType(String typeName) {
+ this.typeDefMap_.remove(typeName);
+ }
+
+ /**
+ * Create and add {@link SignatureTypeDefinition} from its name
+ * @param typeName
+ */
+ public void addSignatureType(String typeName) {
+
+ if (STATE_ON.equals(settings_.getSetting(TYPES + "." + typeName, null)))
+ {
+ SignatureTypeDefinition sig_type_def;
+ try
+ {
+ sig_type_def = new SignatureTypeDefinition(settings_, typeName);
+ //signatureTypeDefinitions_.add(sig_type_def);
+ typeDefMap_.put(typeName, sig_type_def);
+ //typeList_.add(type);
+ }
+ catch (SignatureException e)
+ {
+ logger_.error(e.getMessage(), e);
+ }
+ }
+ }
+
+ /**
+ * @return a arrayList (String) of signature types names
+ */
+ public Set getSignatureTypes()
+ {
+ return this.typeDefMap_.keySet();
+ }
+
+ /**
+ * @return a list of signature type definitions
+ */
+ public List getSignatureTypeDefinitions()
+ {
+ return new ArrayList(this.typeDefMap_.values());
+ }
+
+ /**
+ * This method returns the corresponding signature type definition to a given
+ * type key
+ *
+ * @param type
+ * the key to get the signature type definition
+ * @return the stored signature type definition
+ */
+ public SignatureTypeDefinition getSignatureTypeDefinition(String type)
+ {
+ return (SignatureTypeDefinition) typeDefMap_.get(type);
+ }
+
+ public static String convertBrevToType (final byte [] brev)
+ {
+ for (int i = 0; i < ALL_SIG_BREV.length; i++)
+ {
+ if (ByteArrayUtils.compareByteArrays(ALL_SIG_BREV[i], 0, brev))
+ {
+ return ALL_SIG_KEYS[i];
+ }
+ }
+ return null;
+ }
+
+ public static byte [] convertTypeToBrev (final String type)
+ {
+ for (int i = 0; i < ALL_SIG_KEYS.length; i++)
+ {
+ if (ALL_SIG_KEYS.equals(type))
+ {
+ return ALL_SIG_BREV[i];
+ }
+ }
+ return null;
+ }
+
+ public static boolean isRequredSigTypeKey(String name) {
+ return ArrayUtils.contains(REQUIRED_SIG_KEYS, name);
+ }
+
+ /**
+ * The standard toString method. Used for testing only.
+ *
+ * @return the string representation of the class
+ */
+ public String toString()
+ {
+ String strg = "";
+ for (Iterator it = this.typeDefMap_.values().iterator(); it.hasNext();) {
+ SignatureTypeDefinition std = (SignatureTypeDefinition) it.next();
+
+ strg += "----------TYPE:" + std.getType() + "----------\n";
+ strg += std.toString();
+ }
+ return strg;
+ }
+
+} \ No newline at end of file
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/X509Cert.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/X509Cert.java
new file mode 100644
index 0000000..7b4e463
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/X509Cert.java
@@ -0,0 +1,490 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: X509Cert.java,v 1.4 2006/08/25 17:09:41 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.sig;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.Serializable;
+import java.security.PublicKey;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.CertificateParsingException;
+import java.security.cert.X509Certificate;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import at.knowcenter.wag.egov.egiz.cfg.ConfigLogger;
+import at.knowcenter.wag.egov.egiz.tools.CodingHelper;
+import at.knowcenter.wag.egov.egiz.tools.FileHelper;
+
+public class X509Cert implements Serializable
+{
+
+ /**
+ * SVUID.
+ */
+ private static final long serialVersionUID = 6945327015386694557L;
+
+ /**
+ * The x509 certificate binary string Base64 coded
+ */
+ private String certString_ = null;
+
+ /**
+ * The name value of the issuer
+ */
+ private String issuerName_ = null;
+
+ /**
+ * The serial number of the certificate
+ */
+ private String serialNumber_ = null;
+
+ /**
+ * The digest value of the certificate
+ */
+ private String certDigest_ = null;
+
+ /**
+ * The name value of the subject
+ */
+ private String subjectName_ = null;
+
+ /**
+ * The X509Certificate object
+ */
+ private X509Certificate x509Cert_ = null;
+
+ /**
+ * The logger definition.
+ */
+ private static final Logger logger_ = ConfigLogger.getLogger(X509Cert.class);
+
+ /**
+ * The empty constructor not acessible from outside --> use the static init
+ * methods instead
+ */
+ private X509Cert()
+ {
+ }
+
+ /**
+ * Normalize the base64 coded .cer or .der string. Remove the begin and end
+ * statement and remove all whitespaces in the string. The result string
+ * (base64) is used by reconstructing the certiface sign by the verification
+ * process.
+ *
+ * @param certString
+ * the string to normalize
+ * @return the normalized cert string
+ */
+ private static String normalizeCertString(String certString)
+ {
+ certString = certString.replaceAll("-----BEGIN CERTIFICATE-----", "");
+ certString = certString.replaceAll("-----END CERTIFICATE-----", "");
+ certString = certString.replaceAll("\\s", "");
+ return certString;
+ }
+
+ /**
+ * This method initialzes a X509Certificate by a string value. It must be
+ * coded Base64 or as plain binary stream.
+ *
+ * @param certString
+ * the certificate string to analyse
+ * @return the X509Cert object
+ * @see CertificateFactory
+ * @see X509Certificate
+ */
+ public static X509Cert initByString(String certString)
+ {
+ if (certString == null)
+ {
+ return null;
+ }
+ certString = normalizeCertString(certString);
+ X509Cert x509_cert = new X509Cert();
+ x509_cert.setCertString(certString);
+ try
+ {
+ byte[] b64_dec = certString.getBytes("US-ASCII");
+ if (CodingHelper.isB64(b64_dec))
+ {
+ b64_dec = CodingHelper.decodeBase64(b64_dec);
+ }
+ else
+ {
+ b64_dec = CodingHelper.encodeBase64(b64_dec).getBytes("US-ASCII");
+ }
+ ByteArrayInputStream bais = new ByteArrayInputStream(b64_dec);
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ X509Certificate cert = (X509Certificate) cf.generateCertificate(bais);
+ bais.close();
+ x509_cert.setX509Cert(cert);
+
+ String serial_num = cert.getSerialNumber().toString();
+ String issuer = cert.getIssuerDN().getName();
+ issuer = issuer.replaceAll(", ", ",");
+ String subject_name = cert.getSubjectDN().toString();
+ x509_cert.setSerialNumber(serial_num);
+ x509_cert.setIssuerName(issuer);
+ x509_cert.setSubjectName(subject_name);
+ if (logger_.isDebugEnabled())
+ {
+ logger_.debug("Serial number from certificate:" + serial_num);
+ logger_.debug("Issuer name from certificate :" + issuer);
+ logger_.debug("Subject name from certificate :" + subject_name);
+ }
+ }
+ catch (java.security.cert.CertificateException ce)
+ {
+ // nothing to do, cause certString is not X509 conformc
+ logger_.error(ce.getMessage(), ce);
+ }
+ catch (IOException ioe)
+ {
+ // nothing to do, cause certString is not X509 conform
+ logger_.error(ioe.getMessage(), ioe);
+ }
+ return x509_cert;
+ }
+
+ public static X509Cert initByX509Certificate(X509Certificate cert) throws CertificateEncodingException {
+ X509Cert x509_cert = new X509Cert();
+ x509_cert.setX509Cert(cert);
+ x509_cert.setCertString(CodingHelper.encodeBase64(cert.getEncoded()));
+
+ String serial_num = cert.getSerialNumber().toString();
+ String issuer = cert.getIssuerDN().getName();
+ issuer = issuer.replaceAll(", ", ",");
+ String subject_name = cert.getSubjectDN().toString();
+ x509_cert.setSerialNumber(serial_num);
+ x509_cert.setIssuerName(issuer);
+ x509_cert.setSubjectName(subject_name);
+ if (logger_.isDebugEnabled())
+ {
+ logger_.debug("Serial number from certificate:" + serial_num);
+ logger_.debug("Issuer name from certificate :" + issuer);
+ logger_.debug("Subject name from certificate :" + subject_name);
+ }
+ return x509_cert;
+ }
+
+ public static X509Cert initByByteArray(byte[] data)
+ {
+ X509Cert x509_cert = new X509Cert();
+ try
+ {
+ ByteArrayInputStream bais = new ByteArrayInputStream(data);
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ X509Certificate cert = (X509Certificate) cf.generateCertificate(bais);
+ bais.close();
+
+ x509_cert.setX509Cert(cert);
+
+ String serial_num = cert.getSerialNumber().toString();
+ String issuer = cert.getIssuerDN().getName();
+ issuer = issuer.replaceAll(", ", ",");
+ String subject_name = cert.getSubjectDN().toString();
+ x509_cert.setSerialNumber(serial_num);
+ x509_cert.setIssuerName(issuer);
+ x509_cert.setSubjectName(subject_name);
+ if (logger_.isDebugEnabled())
+ {
+ logger_.debug("Serial number from certificate:" + serial_num);
+ logger_.debug("Issuer name from certificate :" + issuer);
+ logger_.debug("Subject name from certificate :" + subject_name);
+ }
+ }
+ catch (java.security.cert.CertificateException ce)
+ {
+ // nothing to do, cause certString is not X509 conformc
+ logger_.error(ce.getMessage(), ce);
+
+ }
+ catch (IOException ioe)
+ {
+ // nothing to do, cause certString is not X509 conform
+ logger_.error(ioe.getMessage(), ioe);
+ }
+
+ return x509_cert;
+ }
+
+ /**
+ * This method initialzes a X509Certificate by a file path value. The file
+ * must be a plain binary file like .cer format.
+ *
+ * @param filePath
+ * the certificate file to analyse
+ * @return the X509Cert object
+ * @see CertificateFactory
+ * @see X509Certificate
+ */
+ public static X509Cert initByFilePath(String filePath)
+ {
+ if (filePath == null)
+ {
+ return null;
+ }
+ X509Cert x509_cert = new X509Cert();
+ try
+ {
+ FileInputStream fis = new FileInputStream(filePath);
+ X509Certificate cert = null;
+ try
+ {
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ cert = (X509Certificate) cf.generateCertificate(fis);
+ }
+ catch (java.security.cert.CertificateException ce)
+ {
+ fis.close();
+ String cert_string = FileHelper.readFromFile(filePath);
+ return initByString(cert_string);
+ }
+ fis.close();
+ x509_cert.setX509Cert(cert);
+ String cert_string = FileHelper.readFromFile(filePath);
+ x509_cert.setCertString(normalizeCertString(cert_string));
+
+ String serial_num = cert.getSerialNumber().toString();
+ String issuer = cert.getIssuerDN().getName();
+ issuer = issuer.replaceAll(", ", ",");
+ String subject_name = cert.getSubjectDN().toString();
+ x509_cert.setSerialNumber(serial_num);
+ x509_cert.setIssuerName(issuer);
+ x509_cert.setSubjectName(subject_name);
+ if (logger_.isDebugEnabled())
+ {
+ logger_.debug("Serial number from certificate:" + serial_num);
+ logger_.debug("Issuer name from certificate :" + issuer);
+ logger_.debug("Subject name from certificate :" + subject_name);
+ }
+ }
+ catch (IOException ioe)
+ {
+ String cert_string = FileHelper.readFromFile(filePath);
+ return initByString(cert_string);
+ }
+ return x509_cert;
+
+ }
+
+ /**
+ * This method initialzes a X509Certificate by a file value. The file must be
+ * a plain binary file like .cer format.
+ *
+ * @param certFile
+ * the certificate file to analyse
+ * @return the X509Cert object
+ * @see CertificateFactory
+ * @see X509Certificate
+ */
+ public static X509Cert initByFile(File certFile)
+ {
+ return initByFilePath(certFile.getAbsolutePath());
+ }
+
+ /**
+ * This method checks if a certificate file is X509 conform.
+ *
+ * @return true if a certificate file is X509 conform, false otherwise
+ */
+ public boolean isX509Cert()
+ {
+ return x509Cert_ != null;
+ }
+
+ /**
+ * @return Returns the certificate digest value.
+ * @deprecated Should not be used any more.
+ */
+ public String getCertDigest()
+ {
+ if (certDigest_ == null)
+ {
+ if (certString_ != null)
+ {
+ byte[] cert_b64 = CodingHelper.decodeBase64(certString_);
+ String sigAlgName = this.x509Cert_.getSigAlgName();
+ String digestAlg = sigAlgName.split("/")[0];
+ if (sigAlgName.toLowerCase().indexOf("with") != -1 ) {
+ digestAlg = sigAlgName.substring(0,sigAlgName.toLowerCase().indexOf("with"));
+ }
+ byte[] cert_hash = CodingHelper.buildDigest(cert_b64, digestAlg);
+ certDigest_ = new String(CodingHelper.encodeBase64(cert_hash));
+ }
+ }
+ return certDigest_;
+ }
+
+ /**
+ * @return Returns the certificate Base64 binary string.
+ */
+ public String getCertString()
+ {
+ return certString_;
+ }
+
+ /**
+ * @return Returns the issuer string.
+ */
+ public String getIssuerName()
+ {
+ return issuerName_;
+ }
+
+ /**
+ * @return Returns the serial number.
+ */
+ public String getSerialNumber()
+ {
+ return serialNumber_;
+ }
+
+ /**
+ * @return Returns the real X509Certifcate object.
+ * @see X509Certificate
+ */
+ public X509Certificate getX509Certificate()
+ {
+ return x509Cert_;
+ }
+
+ /**
+ * @return Returns the subject name.
+ */
+ public String getSubjectName()
+ {
+ return subjectName_;
+ }
+
+ // /**
+ // * @param certDigest
+ // * The certDigest to set.
+ // */
+ // private void setCertDigest(String certDigest)
+ // {
+ // certDigest_ = certDigest;
+ // }
+
+ /**
+ * @param certString
+ * The certString to set.
+ */
+ private void setCertString(String certString)
+ {
+ certString_ = certString;
+ }
+
+ /**
+ * @param issuerString
+ * The issuerString to set.
+ */
+ private void setIssuerName(String issuerString)
+ {
+ issuerName_ = issuerString;
+ }
+
+ /**
+ * @param serialNumber
+ * The serialNumber to set.
+ */
+ private void setSerialNumber(String serialNumber)
+ {
+ serialNumber_ = serialNumber;
+ }
+
+ /**
+ * @param cert
+ * The x509Cert to set.
+ */
+ private void setX509Cert(X509Certificate cert)
+ {
+ x509Cert_ = cert;
+ }
+
+ /**
+ * @param subjectName
+ * The subjectName to set.
+ */
+ private void setSubjectName(String subjectName)
+ {
+ subjectName_ = subjectName;
+ }
+
+ public byte[] getTBSCertificate() throws CertificateEncodingException
+ {
+ return x509Cert_.getTBSCertificate();
+ }
+
+ public String getSigAlgName()
+ {
+ return x509Cert_.getSigAlgName();
+ }
+
+ public String getSigAlgOID()
+ {
+ return x509Cert_.getSigAlgOID();
+ }
+
+ public List getExtendedKeyUsage()
+ {
+ List list = null;
+ try
+ {
+ list = x509Cert_.getExtendedKeyUsage();
+ }
+ catch (CertificateParsingException e)
+ {
+ logger_.error(e.getMessage(), e);
+ }
+ return null;
+ }
+
+ /**
+ * @return the public key of the X509Certificate
+ */
+ public PublicKey getPublicKey()
+ {
+ return x509Cert_.getPublicKey();
+ }
+
+ /**
+ * This method checks, if a X509Certificate has a public key with the rsa
+ * algorithm.
+ *
+ * @return true if the public key is produced with rsa, false otherwise
+ */
+ public boolean isRSA()
+ {
+ return (x509Cert_.getPublicKey().getAlgorithm()).indexOf("RSA") >= 0;
+ }
+} \ No newline at end of file
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/A1Connector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/A1Connector.java
new file mode 100644
index 0000000..aab8e6b
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/A1Connector.java
@@ -0,0 +1,63 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: A1Connector.java,v 1.2 2006/08/25 17:09:17 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors;
+
+import at.knowcenter.wag.egov.egiz.exceptions.SignatureException;
+import at.knowcenter.wag.egov.egiz.sig.ConnectorInformation;
+
+/**
+ * @author wprinz
+ */
+public class A1Connector extends BKUConnector
+{
+ /**
+ * ConnectorInformation that identifies this Connector to the system.
+ *
+ * @see at.knowcenter.wag.egov.egiz.sig.ConnectorFactory
+ * @see ConnectorInformation
+ */
+ public static final ConnectorInformation CONNECTOR_INFORMATION = new ConnectorInformation("a1", "A-1");
+
+ /**
+ * Constructor.
+ *
+ * @throws SignatureException
+ * F.e.
+ */
+ public A1Connector() throws SignatureException
+ {
+ super();
+ }
+
+ /**
+ * Overrides the type of the BKUConnector to use the A1 settings.
+ */
+ protected String getType()
+ {
+ return CONNECTOR_INFORMATION.getIdentifier();
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/BKUConnector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/BKUConnector.java
new file mode 100644
index 0000000..c3b6421
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/BKUConnector.java
@@ -0,0 +1,896 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: BKUConnector.java,v 1.5 2006/10/31 08:18:41 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Properties;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.gv.egiz.pdfas.exceptions.external.ExternalErrorException;
+import at.knowcenter.wag.egov.egiz.cfg.ConfigLogger;
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+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.sig.ConnectorInformation;
+import at.knowcenter.wag.egov.egiz.sig.LocalConnector;
+import at.knowcenter.wag.egov.egiz.sig.SignatureObject;
+import at.knowcenter.wag.egov.egiz.sig.SignatureResponse;
+import at.knowcenter.wag.egov.egiz.sig.X509Cert;
+import at.knowcenter.wag.egov.egiz.tools.CodingHelper;
+
+/**
+ * Connector for communicating with BKU.
+ *
+ * @deprecated use the new connectors.
+ *
+ * @author wlackner
+ * @author wprinz
+ */
+public class BKUConnector implements LocalConnector
+{
+ /**
+ * ConnectorInformation that identifies this Connector to the system.
+ *
+ * @see at.knowcenter.wag.egov.egiz.sig.ConnectorFactory
+ * @see ConnectorInformation
+ */
+ public static final ConnectorInformation CONNECTOR_INFORMATION = new ConnectorInformation("bku", "BKU");
+
+ /**
+ * The SettingsReader instance
+ */
+ private SettingsReader settings_ = null;
+
+ /**
+ * The logger definition.
+ */
+ private static final Logger logger_ = ConfigLogger.getLogger(BKUConnector.class);
+
+ /**
+ * The empty constructor
+ */
+ public BKUConnector() //throws SignatureException
+ {
+ //loadSettings();
+ }
+
+ /**
+ * load the inital signature settings
+ *
+ * @see SettingsReader
+ */
+ public void loadSettings() throws SignatureException
+ {
+ if (settings_ == null)
+ {
+ try
+ {
+ settings_ = SettingsReader.getInstance();
+ }
+ catch (SettingsException e)
+ {
+ String log_message = "Can not load signature settings. Cause:\n" + e.getMessage();
+ logger_.error(log_message);
+ throw new SignatureException(101, log_message, e);
+ }
+ }
+ }
+
+ /**
+ * This method calls the BKU signing a given text. The signaton type is to
+ * used initializing the corresponding SigantureObject. The initialized
+ * SignatureObject is filled out by the parsed BKU-Response. <br>
+ * If an error request is send back from BKU, an error message is generated an
+ * an exception is thrown.
+ *
+ * @param sigType
+ * the type of the SignatureObject that should be returned
+ * @param userName
+ * the name of the user calling this method
+ * @param signText
+ * the text that shoulf be signed from BKU
+ * @return the complete SingatureObject of the given type filled by values
+ * from the BKU-Request
+ * @throws SignatureException
+ * @see SignatureObject
+ */
+ public SignatureObject doSign(String sigType, String userName, String signText) throws SignatureException
+ {
+ String request_string = prepareSignRequest(userName, signText, sigType);
+
+ String sign_url = getSignURL(sigType);
+ Properties response_properties = sendRequest(sign_url, request_string);
+
+ return analyzeSignResponse(response_properties, sigType);
+ }
+
+ /**
+ * This method generates the BKU verify prozess. It checks if the given
+ * SignatureObject is signed by MOA or BKU. The verify template string is
+ * filled out by the corresponding method.
+ *
+ * @param normalizedText
+ * the normalized text to verify
+ * @param sigObject
+ * the SignatureObject holding the singature values
+ * @return a SignatureResponse object if the verify prozess does not fails
+ * @throws SignatureException
+ * @see SignatureResponse
+ */
+ public SignatureResponse doVerify(String normalizedText,
+ SignatureObject sigObject) throws SignatureException
+ {
+ String request_string = prepareVerifyRequest(normalizedText, sigObject);
+
+ String verify_url = getVerifyURL(sigObject.getSignationType());
+ Properties response_properties = sendRequest(verify_url, request_string);
+
+ return analyzeVerifyResponse(response_properties);
+ }
+
+ /**
+ * This method parses the BKU-Response string. It separates the
+ * SignatureValue, X509IssuerName, SigningTime, X509SerialNumber,
+ * X509Certificate, CertDigest, DigestValue and the signation id-s. If the
+ * X509Certificate is extracted it would be stored in the certificates
+ * directory.
+ *
+ * @param xmlResponse
+ * the response string from the BKU sign-request
+ * @param sigObj
+ * the SignatureObject that should be filled
+ * @throws SignatureException
+ * ErrorCode (303, 304)
+ * @see SignatureObject
+ * @see CodingHelper
+ * @see X509Cert
+ */
+ private void parseCreateXMLResponse(Properties response_properties, SignatureObject sigObj) throws SignatureException
+ {
+ String xmlResponse = response_properties.getProperty("response_string");
+
+ Pattern sig_val_p_s = Pattern.compile("<[\\w]*:?SignatureValue>");
+ Pattern sig_val_p_e = Pattern.compile("</[\\w]*:?SignatureValue>");
+ Pattern iss_nam_p_s = Pattern.compile("<[\\w]*:?X509IssuerName>");
+ Pattern iss_nam_p_e = Pattern.compile("</[\\w]*:?X509IssuerName>");
+ Pattern sig_tim_p_s = Pattern.compile("<[\\w]*:?SigningTime>");
+ Pattern sig_tim_p_e = Pattern.compile("</[\\w]*:?SigningTime>");
+ Pattern ser_num_p_s = Pattern.compile("<[\\w]*:?X509SerialNumber>");
+ Pattern ser_num_p_e = Pattern.compile("</[\\w]*:?X509SerialNumber>");
+ Pattern sig_cer_p_s = Pattern.compile("<[\\w]*:?X509Certificate>");
+ Pattern sig_cer_p_e = Pattern.compile("</[\\w]*:?X509Certificate>");
+
+ Pattern sig_cer_d_p_s = Pattern.compile("<[\\w]*:?CertDigest>");
+ Pattern sig_cer_d_p_e = Pattern.compile("</[\\w]*:?CertDigest>");
+ Pattern dig_val_p_s = Pattern.compile("<[\\w]*:?DigestValue>");
+ Pattern dig_val_p_e = Pattern.compile("</[\\w]*:?DigestValue>");
+
+ Matcher sig_val_m_s = sig_val_p_s.matcher(xmlResponse);
+ Matcher sig_val_m_e = sig_val_p_e.matcher(xmlResponse);
+ Matcher iss_nam_m_s = iss_nam_p_s.matcher(xmlResponse);
+ Matcher iss_nam_m_e = iss_nam_p_e.matcher(xmlResponse);
+ Matcher sig_tim_m_s = sig_tim_p_s.matcher(xmlResponse);
+ Matcher sig_tim_m_e = sig_tim_p_e.matcher(xmlResponse);
+ Matcher ser_num_m_s = ser_num_p_s.matcher(xmlResponse);
+ Matcher ser_num_m_e = ser_num_p_e.matcher(xmlResponse);
+ Matcher sig_cer_m_s = sig_cer_p_s.matcher(xmlResponse);
+ Matcher sig_cer_m_e = sig_cer_p_e.matcher(xmlResponse);
+
+ Matcher sig_cer_d_m_s = sig_cer_d_p_s.matcher(xmlResponse);
+ Matcher sig_cer_d_m_e = sig_cer_d_p_e.matcher(xmlResponse);
+
+ String sig_val = "";
+ String iss_nam = "";
+ String ser_num = "";
+ String sig_tim = "";
+ String sig_cer = "";
+ String sig_dig = "";
+
+ // SignatureValue
+ if (sig_val_m_s.find() && sig_val_m_e.find())
+ {
+ sig_val = xmlResponse.substring(sig_val_m_s.end(), sig_val_m_e.start());
+ sig_val = sig_val.replaceAll("\\s", "");
+ sigObj.setSignationValue(sig_val);
+ }
+ // X509IssuerName
+ if (iss_nam_m_s.find() && iss_nam_m_e.find())
+ {
+ iss_nam = xmlResponse.substring(iss_nam_m_s.end(), iss_nam_m_e.start());
+ sigObj.setSignationIssuer(iss_nam);
+ }
+ // X509SerialNumber
+ if (ser_num_m_s.find() && ser_num_m_e.find())
+ {
+ ser_num = xmlResponse.substring(ser_num_m_s.end(), ser_num_m_e.start());
+ sigObj.setSignationSerialNumber(ser_num);
+ }
+ // SigningTime
+ if (sig_tim_m_s.find() && sig_tim_m_e.find())
+ {
+ sig_tim = xmlResponse.substring(sig_tim_m_s.end(), sig_tim_m_e.start());
+ sigObj.setSignationDate(sig_tim);
+ }
+ // CertDigest
+ if (sig_cer_d_m_s.find() && sig_cer_d_m_e.find())
+ {
+ String cert_digest = xmlResponse.substring(sig_cer_d_m_s.end(), sig_cer_d_m_e.start());
+ Matcher dig_val_m_s = dig_val_p_s.matcher(cert_digest);
+ Matcher dig_val_m_e = dig_val_p_e.matcher(cert_digest);
+ if (dig_val_m_s.find() && dig_val_m_e.find())
+ {
+ sig_dig = cert_digest.substring(dig_val_m_s.end(), dig_val_m_e.start());
+ sigObj.setX509CertificateDigest(sig_dig);
+ }
+ }
+ // extract Subject Name from X509Certificate
+ if (sig_cer_m_s.find() && sig_cer_m_e.find())
+ {
+ sig_cer = xmlResponse.substring(sig_cer_m_s.end(), sig_cer_m_e.start());
+ sig_cer = sig_cer.replaceAll("\\s", "");
+ sigObj.setX509Certificate(sig_cer);
+ X509Cert cert = X509Cert.initByString(sig_cer);
+ if (cert.isX509Cert())
+ {
+ sigObj.setX509Certificate(cert.getCertString());
+ String serial_num = cert.getSerialNumber();
+ String subject_name = cert.getSubjectName();
+ if (!ser_num.equals(serial_num))
+ {
+ SignatureException se = new SignatureException(303, "Serialnumber of certificate and tag X509SerialNumber differs!");
+ throw se;
+ }
+ sigObj.setSignationName(subject_name);
+ }
+ }
+
+ // extract Signature Id's
+ String[] ids = new String[5];
+ ids[0] = extractId(xmlResponse, "signature-");
+ ids[1] = extractId(xmlResponse, "signed-data-reference-");
+ ids[2] = extractId(xmlResponse, "signed-data-object-");
+ ids[3] = extractId(xmlResponse, "etsi-data-reference-");
+ ids[4] = extractId(xmlResponse, "etsi-data-object-");
+
+ //TODO hotfix - already deprecated
+ String final_ids =SignatureObject.formatSigIds(response_properties, ids);
+ //sigObj.setSignationIDs(ids);
+ sigObj.setSignationIDs(final_ids);
+ }
+
+ /**
+ * This emthod extracts id-values from a text. The id is given by the name.
+ *
+ * @param text
+ * the id-value that should extract from
+ * @param name
+ * the id-key
+ * @return the value of the given key in the text
+ */
+ private String extractId(String text, String name)
+ {
+ String id = null;
+ int start_idx = text.indexOf(name) + name.length();
+ int end_idx = text.indexOf("\"", start_idx);
+
+ // TODO hotfix! - already deprecated
+ final int quot_end_idx = end_idx;
+ final int squot_end_idx = text.indexOf("'", start_idx);
+ end_idx = Math.min(quot_end_idx, squot_end_idx);
+ // TODO hotfix end! - already deprecated
+
+ id = text.substring(start_idx, end_idx);
+ if (logger_.isDebugEnabled())
+ {
+ logger_.debug("extract id:" + name + id);
+ }
+ return id;
+ }
+
+ /**
+ * This method reads the verify template from the file system and fills out
+ * the template with the SignatureObject values.
+ *
+ * @param normalizedText
+ * the normalized text to veryfied
+ * @param sigObject
+ * the SignatureObject holding the singature values
+ * @return the filled verify template string
+ * @throws SignatureException
+ * ErrorCode (311, 312, 313)
+ * @see SignatureObject
+ * @see CodingHelper
+ */
+ public String getVerifyTemplate(String normalizedText,
+ SignatureObject sigObject) throws SignatureException
+ {
+ try
+ {
+ if (normalizedText == null || normalizedText.length() == 0)
+ {
+ SignatureException se = new SignatureException(311, "Document can not be verified because normalized text is empty.");
+ throw se;
+ }
+ if (sigObject == null)
+ {
+ SignatureException se = new SignatureException(312, "Document can not be verified because no signature object are set.");
+ throw se;
+ }
+
+ String verify_template = getVerifyTemplateFileName(sigObject.getSignationType());
+ String sig_prop_filename = getSigPropFileName(sigObject.getSignationType());
+
+ String ids_string = sigObject.getSignationIds();
+ logger_.debug("ids_string = " + ids_string);
+ String[] ids = SignatureObject.parseSigIds(ids_string);
+
+ // TODO hotfix - already deprecated
+ final boolean neue_bku = ids[5] != null;
+ logger_.debug("ids[5] = " + ids[5]);
+ logger_.debug("neue_bku = " + neue_bku);
+ if (neue_bku)
+ {
+ verify_template = getConnectorValueFromProfile(sigObject.getSignationType(), "bku.verify.template2"); //"./templates/BKUVerifyTemplateB64_neueBKU.xml";
+ sig_prop_filename = getConnectorValueFromProfile(sigObject.getSignationType(), "bku.verify.template2.SP"); //"./templates/BKUVerifyTemplateSP_neueBKU.xml";
+ }
+
+
+ //String ver_temp_str = FileHelper.readFromFile(SettingsReader.relocateFile(verify_template));
+ String ver_temp_str = this.settings_.readInternalResourceAsString(verify_template);
+ //String sig_prop_str = FileHelper.readFromFile(SettingsReader.relocateFile(sig_prop_filename));
+ String sig_prop_str = this.settings_.readInternalResourceAsString(sig_prop_filename);
+ if (logger_.isDebugEnabled())
+ {
+ //logger_.debug(verify_template);
+ logger_.debug(sig_prop_filename);
+ }
+
+ String x509_cert_string = sigObject.getX509CertificateString();
+ if (x509_cert_string == null)
+ {
+ SignatureException se = new SignatureException(ErrorCode.CERTIFICATE_NOT_FOUND, "Document certificate is not defined.");
+ throw se;
+ }
+ String cert_alg = settings_.getValueFromKey("cert.alg.ecdsa");
+ X509Cert x509_cert = sigObject.getX509Cert();
+ if (x509_cert.isRSA())
+ {
+ cert_alg = settings_.getValueFromKey("cert.alg.rsa");
+ }
+
+ sig_prop_str = sig_prop_str.replaceFirst("SigningTimeReplace", sigObject.getSignationDate());
+
+ String issuer_name = sigObject.getSignationIssuer();
+ // The issuer is already unicode, so it mustn't be encoded again.
+ //byte[] issuer_name = CodingHelper.encodeUTF8(sigObject.getSignationIssuer());
+ // new String(issuer_name); // this would double encode the String, not to mention the missing encoding
+ sig_prop_str = sig_prop_str.replaceFirst("X509IssuerNameReplace", issuer_name);
+
+ sig_prop_str = sig_prop_str.replaceFirst("X509SerialNumberReplace", sigObject.getSignationSerialNumber());
+ sig_prop_str = sig_prop_str.replaceFirst("DigestValueX509CertificateReplace", sigObject.getX509CertificateDigest());
+ sig_prop_str = sig_prop_str.replaceFirst("SigIdReplace", ids[0]);
+ sig_prop_str = sig_prop_str.replaceFirst("SigDataRefReplace", ids[1]);
+
+ ver_temp_str = ver_temp_str.replaceFirst("CertAlgReplace", cert_alg);
+ ver_temp_str = ver_temp_str.replaceFirst("TemplateQualifyingPropertiesReplace", sig_prop_str);
+ byte[] sig_prop_code = CodingHelper.buildDigest(sig_prop_str.getBytes("UTF-8"), "sha1");
+
+ // TODO hotfix - already deprecated
+ if (neue_bku)
+ {
+ final String ETSI_SIGNED_PROPERTIES_START_TAG = "<etsi:SignedProperties"; // xml name spaces follow, so this is not a complete tag...
+ final String ETSI_SIGNED_PROPERTIES_END_TAG = "</etsi:SignedProperties>";
+
+ final int hash_start = sig_prop_str.indexOf(ETSI_SIGNED_PROPERTIES_START_TAG);
+ assert hash_start >= 0;
+ final int hash_end = sig_prop_str.indexOf(ETSI_SIGNED_PROPERTIES_END_TAG, hash_start) + ETSI_SIGNED_PROPERTIES_END_TAG.length();
+ assert hash_end - ETSI_SIGNED_PROPERTIES_END_TAG.length() >= 0;
+ assert hash_end > hash_start;
+
+ final String string_to_be_hashed = sig_prop_str.substring(hash_start, hash_end);
+ logger_.debug("etsi:SignedProperties string to be hashed: " + string_to_be_hashed);
+
+ logger_.debug("\n--------------------- ETSI properties string to be hashed: start ---------------------");
+ logger_.debug(string_to_be_hashed);
+ logger_.debug("\n--------------------- ETSI properties string to be hashed: stop ---------------------");
+
+ final byte [] bytes_to_be_hashed = string_to_be_hashed.getBytes("UTF-8");
+ sig_prop_code = CodingHelper.buildDigest(bytes_to_be_hashed, "sha1");
+ }
+
+ String sig_prop_hash = CodingHelper.encodeBase64(sig_prop_code);
+ ver_temp_str = ver_temp_str.replaceFirst("DigestValueSignedPropertiesReplace", sig_prop_hash);
+ if (logger_.isDebugEnabled())
+ {
+ logger_.debug("build digest from QualifyingProperties:start");
+ //logger_.debug("DATA :" + sig_prop_str);
+ logger_.debug("DIGEST:" + sig_prop_hash);
+ logger_.debug("build digest from QualifyingProperties:end");
+ }
+
+ ver_temp_str = ver_temp_str.replaceFirst("SignatureValueReplace", sigObject.getSignationValue());
+ ver_temp_str = ver_temp_str.replaceFirst("X509CertificateReplace", x509_cert_string);
+ byte[] data_value = normalizedText.getBytes("UTF-8");
+ byte[] data_value_hash = CodingHelper.buildDigest(data_value, "sha1");
+ String object_data_hash = CodingHelper.encodeBase64(data_value_hash);
+ // String object_data = new String(data_value);
+ if (logger_.isDebugEnabled())
+ {
+ logger_.debug("build digest from data object:start");
+ //logger_.debug("DATA :" + normalizedText);
+ logger_.debug("DIGEST:" + object_data_hash);
+ logger_.debug("build digest from data object:end");
+ }
+
+ //String raw_b64 = CodingHelper.encodeUTF8AsBase64(normalizedText);
+ String raw_b64 = CodingHelper.encodeBase64(data_value);
+
+ ver_temp_str = ver_temp_str.replaceFirst("Base64ContentReplace", raw_b64);
+ ver_temp_str = ver_temp_str.replaceFirst("DigestValueSignedDataReplace", object_data_hash);
+
+ ver_temp_str = ver_temp_str.replaceAll("SigIdReplace", ids[0]);
+ ver_temp_str = ver_temp_str.replaceAll("SigDataRefReplace", ids[1]);
+ ver_temp_str = ver_temp_str.replaceAll("SigDataObjURIReplace", ids[2]);
+ ver_temp_str = ver_temp_str.replaceAll("EtsiDataRefReplace", ids[3]);
+ ver_temp_str = ver_temp_str.replaceAll("EtsiDataObjURIReplace", ids[4]);
+ if (logger_.isDebugEnabled())
+ {
+ //logger_.debug("VERIFY REQUEST:" + ver_temp_str);
+ }
+
+ return ver_temp_str;
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ throw new SignatureException(310, e);
+ }
+ }
+
+ /**
+ * This method parses the verify response string and return a
+ * SignatureResponse object. The SignatureResponse object is filled out by the
+ * response values from the BKU-response.
+ *
+ * @param xmlResponse
+ * the response values from the BKU-verify request
+ * @return SignatureResponse object
+ * @see SignatureResponse
+ */
+ private SignatureResponse parseVerifyXMLResponse(String xmlResponse)
+ {
+ if (logger_.isInfoEnabled())
+ {
+ logger_.info("Try parsing the verify response");
+ }
+
+ Pattern sub_nam_p_s = Pattern.compile("<dsig:X509SubjectName>");
+ Pattern sub_nam_p_e = Pattern.compile("</dsig:X509SubjectName>");
+ Pattern iss_nam_p_s = Pattern.compile("<dsig:X509IssuerName>");
+ Pattern iss_nam_p_e = Pattern.compile("</dsig:X509IssuerName>");
+ Pattern ser_num_p_s = Pattern.compile("<dsig:X509SerialNumber>");
+ Pattern ser_num_p_e = Pattern.compile("</dsig:X509SerialNumber>");
+
+ Pattern sig_chk_p_s = Pattern.compile("<sl:SignatureCheck>");
+ Pattern sig_chk_p_e = Pattern.compile("</sl:SignatureCheck>");
+ Pattern man_chk_p_s = Pattern.compile("<sl:SignatureManifestCheck>");
+ Pattern man_chk_p_e = Pattern.compile("</sl:SignatureManifestCheck>");
+ Pattern cer_chk_p_s = Pattern.compile("<sl:CertificateCheck>");
+ Pattern cer_chk_p_e = Pattern.compile("</sl:CertificateCheck>");
+
+ // [tknall] start qualified certificate
+ Pattern cert_qualified_p = Pattern.compile("<sl:QualifiedCertificate/>");
+ Matcher cert_qualified_m = cert_qualified_p.matcher(xmlResponse);
+ // [tknall] stop qualified certificate
+
+ Pattern code_p_s = Pattern.compile("<sl:Code>");
+ Pattern code_p_e = Pattern.compile("</sl:Code>");
+ Pattern info_p_s = Pattern.compile("<sl:Info>");
+ Pattern info_p_e = Pattern.compile("</sl:Info>");
+
+ Pattern cert_p_s = Pattern.compile("<dsig:X509Certificate>");
+ Pattern cert_p_e = Pattern.compile("</dsig:X509Certificate>");
+
+ Matcher sub_nam_m_s = sub_nam_p_s.matcher(xmlResponse);
+ Matcher sub_nam_m_e = sub_nam_p_e.matcher(xmlResponse);
+ Matcher iss_nam_m_s = iss_nam_p_s.matcher(xmlResponse);
+ Matcher iss_nam_m_e = iss_nam_p_e.matcher(xmlResponse);
+ Matcher ser_num_m_s = ser_num_p_s.matcher(xmlResponse);
+ Matcher ser_num_m_e = ser_num_p_e.matcher(xmlResponse);
+
+ Matcher sig_chk_m_s = sig_chk_p_s.matcher(xmlResponse);
+ Matcher sig_chk_m_e = sig_chk_p_e.matcher(xmlResponse);
+ Matcher man_chk_m_s = man_chk_p_s.matcher(xmlResponse);
+ Matcher man_chk_m_e = man_chk_p_e.matcher(xmlResponse);
+ Matcher cer_chk_m_s = cer_chk_p_s.matcher(xmlResponse);
+ Matcher cer_chk_m_e = cer_chk_p_e.matcher(xmlResponse);
+
+ Matcher cert_m_s = cert_p_s.matcher(xmlResponse);
+ Matcher cert_m_e = cert_p_e.matcher(xmlResponse);
+
+ SignatureResponse sig_res = new SignatureResponse();
+
+ // [tknall] start qualified certificate
+ sig_res.setQualifiedCertificate(cert_qualified_m.find());
+ // [tknall] stop qualified certificate
+
+ if (sub_nam_m_s.find() && sub_nam_m_e.find())
+ {
+ String sub_nam = xmlResponse.substring(sub_nam_m_s.end(), sub_nam_m_e.start());
+ sig_res.setX509SubjectName(sub_nam);
+ }
+ if (iss_nam_m_s.find() && iss_nam_m_e.find())
+ {
+ String iss_nam = xmlResponse.substring(iss_nam_m_s.end(), iss_nam_m_e.start());
+ sig_res.setX509IssuerName(iss_nam);
+ }
+ if (ser_num_m_s.find() && ser_num_m_e.find())
+ {
+ String ser_num = xmlResponse.substring(ser_num_m_s.end(), ser_num_m_e.start());
+ sig_res.setX509SerialNumber(ser_num);
+ }
+ if (sig_chk_m_s.find() && sig_chk_m_e.find())
+ {
+ String sig_chk = xmlResponse.substring(sig_chk_m_s.end(), sig_chk_m_e.start());
+ Matcher code_m_s = code_p_s.matcher(sig_chk);
+ Matcher code_m_e = code_p_e.matcher(sig_chk);
+ Matcher info_m_s = info_p_s.matcher(sig_chk);
+ Matcher info_m_e = info_p_e.matcher(sig_chk);
+ if (code_m_s.find() && code_m_e.find())
+ {
+ String code = sig_chk.substring(code_m_s.end(), code_m_e.start());
+ sig_res.setSignatureCheckCode(code);
+ }
+ if (info_m_s.find() && info_m_e.find())
+ {
+ String info = sig_chk.substring(info_m_s.end(), info_m_e.start());
+ sig_res.setSignatureCheckInfo(info);
+ }
+ }
+ if (man_chk_m_s.find() && man_chk_m_e.find())
+ {
+ String man_chk = xmlResponse.substring(man_chk_m_s.end(), man_chk_m_e.start());
+ Matcher code_m_s = code_p_s.matcher(man_chk);
+ Matcher code_m_e = code_p_e.matcher(man_chk);
+ Matcher info_m_s = info_p_s.matcher(man_chk);
+ Matcher info_m_e = info_p_e.matcher(man_chk);
+ if (code_m_s.find() && code_m_e.find())
+ {
+ String code = man_chk.substring(code_m_s.end(), code_m_e.start());
+ sig_res.setSignatureManifestCheckCode(code);
+ }
+ if (info_m_s.find() && info_m_e.find())
+ {
+ String info = man_chk.substring(info_m_s.end(), info_m_e.start());
+ sig_res.setSignatureManifestCheckInfo(info);
+ }
+ }
+ if (cer_chk_m_s.find() && cer_chk_m_e.find())
+ {
+ String cer_chk = xmlResponse.substring(cer_chk_m_s.end(), cer_chk_m_e.start());
+ Matcher code_m_s = code_p_s.matcher(cer_chk);
+ Matcher code_m_e = code_p_e.matcher(cer_chk);
+ Matcher info_m_s = info_p_s.matcher(cer_chk);
+ Matcher info_m_e = info_p_e.matcher(cer_chk);
+ if (code_m_s.find() && code_m_e.find())
+ {
+ String code = cer_chk.substring(code_m_s.end(), code_m_e.start());
+ sig_res.setCertificateCheckCode(code);
+ }
+ if (info_m_s.find() && info_m_e.find())
+ {
+ String info = cer_chk.substring(info_m_s.end(), info_m_e.start());
+ sig_res.setCertificateCheckInfo(info);
+ }
+ }
+ if (cert_m_s.find() && cert_m_e.find())
+ {
+ String cert_string = xmlResponse.substring(cert_m_s.end(), cert_m_e.start());
+
+ X509Cert resp_cert = X509Cert.initByString(cert_string);
+ sig_res.setCertificate(resp_cert);
+ }
+
+ return sig_res;
+ }
+
+
+
+ public String prepareSignRequest(String userName, String signText,
+ String signType) throws SignatureException
+ {
+ if (logger_.isInfoEnabled())
+ {
+ logger_.info("Call " + getType() + " connector from user:" + userName);
+ }
+ String keybox_identifier = getSignKeyboxIdentifier(signType);
+ String sign_request_filename = getSignRequestTemplateFileName(signType);
+
+ //String sign_req_str = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename));
+ String sign_req_str = this.settings_.readInternalResourceAsString(sign_request_filename);
+ //this.verify_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_request_filename));
+ if (logger_.isDebugEnabled())
+ {
+ //logger_.debug(sign_request_filename + "_signText.xml :" + signText);
+ }
+ String raw_b64 = CodingHelper.encodeUTF8AsBase64(signText);
+ if (sign_req_str == null || raw_b64 == null)
+ {
+ throw new SignatureException(300, "Can not read the create xml request template");
+ }
+ sign_req_str = sign_req_str.replaceFirst("KeyboxIdentifierReplace", keybox_identifier);
+ sign_req_str = sign_req_str.replaceFirst("Base64ContentReplace", raw_b64);
+ if (logger_.isDebugEnabled())
+ {
+ //logger_.debug(sign_request_filename + "_request.xml :"+ sign_req_str);
+ }
+
+ return sign_req_str;
+ }
+
+ public String prepareVerifyRequest(String normalizedText,
+ SignatureObject sigObject) throws SignatureException
+ {
+ String verify_request = getVerifyRequestTemplateFileName(sigObject.getSignationType());
+
+ //String verify_req_str = FileHelper.readFromFile(SettingsReader.relocateFile(verify_request));
+ String verify_req_str = this.settings_.readInternalResourceAsString(verify_request);
+
+ if (logger_.isDebugEnabled())
+ {
+ //logger_.debug(verify_request);
+ }
+
+ String verify_template_str = null;
+ if (sigObject.isMOASigned())
+ {
+ MOAConnector moa_conn = new MOAConnector();
+ // get the MOA-template
+ verify_template_str = moa_conn.getVerifyTemplate(normalizedText, sigObject);
+ }
+ else
+ {
+ // get the BKU-template
+ verify_template_str = getVerifyTemplate(normalizedText, sigObject);
+ }
+ verify_req_str = verify_req_str.replaceFirst("XMLContentReplace", verify_template_str);
+ if (logger_.isDebugEnabled())
+ {
+ logger_.debug("verify_req_str.xml : " + verify_req_str);
+ }
+
+ return verify_req_str;
+ }
+
+ /**
+ * Sends the request to the given URL.
+ *
+ * @param url
+ * The URL.
+ * @param request_string
+ * The request string.
+ * @return Returns the response string.
+ * @throws SignatureException
+ * F.e.
+ */
+ protected Properties sendRequest(String url, String request_string) throws SignatureException
+ {
+ try
+ {
+ Properties response_properties = BKUPostConnection.doPostRequest(url, request_string);
+ return response_properties;
+ }
+ catch (Exception e)
+ {
+ SignatureException se = new SignatureException(320, e);
+ throw se;
+ }
+ }
+
+ public SignatureObject analyzeSignResponse(Properties response_properties,
+ String sigType) throws SignatureException
+ {
+ //String sign_request_filename = getSignRequestTemplateFileName(sigType);
+
+ // TODO hotfix - already deprecated
+ String response_string = response_properties.getProperty("response_string");
+
+ SignatureObject sig_obj = new SignatureObject();
+ sig_obj.setRawSignatureResponse(response_string);
+ try
+ {
+ sig_obj.setSigType(sigType);
+ sig_obj.initByType();
+ }
+ catch (SignatureTypesException e)
+ {
+ SignatureException se = new SignatureException(300, "Cannot init signature object with type:" + sigType, e);
+ throw se;
+ }
+ if (logger_.isDebugEnabled())
+ {
+ logger_.debug("Signature Type is:" + sig_obj.getSignationType());
+ }
+
+ if (!response_string.equals(""))
+ {
+ Pattern erc_p_s = Pattern.compile("<[\\w]*:?ErrorCode>");
+ Pattern erc_p_e = Pattern.compile("</[\\w]*:?ErrorCode>");
+ Matcher erc_m_s = erc_p_s.matcher(response_string);
+ Matcher erc_m_e = erc_p_e.matcher(response_string);
+ // System.err.println(response_string);
+
+ if (erc_m_s.find() && erc_m_e.find())
+ {
+ if (logger_.isEnabledFor(Level.ERROR))
+ {
+ //logger_.debug(sign_request_filename + "_response.xml : " + response_string);
+ logger_.error("BKU Error response: " + response_string);
+ }
+ Pattern erm_p_s = Pattern.compile("<[\\w]*:?Info>");
+ Pattern erm_p_e = Pattern.compile("</[\\w]*:?Info>");
+ Matcher erm_m_s = erm_p_s.matcher(response_string);
+ Matcher erm_m_e = erm_p_e.matcher(response_string);
+ String error_code = response_string.substring(erc_m_s.end(), erc_m_e.start());
+ String error_mess = null;
+ if (erm_m_s.find() && erm_m_e.find())
+ {
+ error_mess = response_string.substring(erm_m_s.end(), erm_m_e.start());
+ }
+ throw new SignatureException(new ExternalErrorException(error_code, error_mess));
+ }
+ else
+ {
+ if (logger_.isDebugEnabled())
+ {
+ logger_.debug("signature_response_string: " + response_string);
+ }
+ parseCreateXMLResponse(response_properties, sig_obj);
+ }
+ }
+ sig_obj.setSigResponse(response_string);
+ return sig_obj;
+ }
+
+ public SignatureResponse analyzeVerifyResponse(Properties response_properties) throws SignatureException
+ {
+ String response_string = response_properties.getProperty("response_string");
+
+ if (!response_string.equals(""))
+ {
+ Pattern erc_p_s = Pattern.compile("<[\\w]*:?ErrorCode>");
+ Pattern erc_p_e = Pattern.compile("</[\\w]*:?ErrorCode>");
+ Matcher erc_m_s = erc_p_s.matcher(response_string);
+ Matcher erc_m_e = erc_p_e.matcher(response_string);
+
+ if (erc_m_s.find() && erc_m_e.find())
+ {
+ if (logger_.isEnabledFor(Level.ERROR))
+ {
+ //logger_.debug(getType() + "_response.xml : " + response_string);
+ logger_.error(getType() + "_response.xml : " + response_string);
+ }
+ Pattern erm_p_s = Pattern.compile("<[\\w]*:?Info>");
+ Pattern erm_p_e = Pattern.compile("</[\\w]*:?Info>");
+ Matcher erm_m_s = erm_p_s.matcher(response_string);
+ Matcher erm_m_e = erm_p_e.matcher(response_string);
+ String error_code = null;
+ if (erc_m_s.find() && erc_m_e.find())
+ {
+ error_code = response_string.substring(erc_m_s.end(), erc_m_e.start());
+ }
+ String error_mess = null;
+ if (erm_m_s.find() && erm_m_e.find())
+ {
+ error_mess = response_string.substring(erm_m_s.end(), erm_m_e.start());
+ }
+ throw new SignatureException(new ExternalErrorException(error_code, error_mess));
+ }
+ else
+ {
+ if (logger_.isDebugEnabled())
+ {
+ //logger_.debug(getType() + "_response.xml : " + response_string);
+ }
+ return parseVerifyXMLResponse(response_string);
+ }
+ }
+ return null;
+ }
+
+ protected String getConnectorValueFromProfile(String profile, String key)
+ {
+ String value = settings_.getValueFromKey("sig_obj." + profile + "." + key);
+ if (value == null)
+ {
+ value = settings_.getValueFromKey(key);
+ }
+ return value;
+ }
+
+ public String getSignURL(String profile)
+ {
+ final String key = getType() + "." + ConnectorConfigurationKeys.VALUE_MODE_SIGN + ".url";
+ return getConnectorValueFromProfile(profile, key);
+ }
+
+ protected String getSignRequestTemplateFileName(String profile)
+ {
+ String key = getType() + "." + ConnectorConfigurationKeys.VALUE_MODE_SIGN + ".request";
+ return getConnectorValueFromProfile(profile, key);
+ }
+
+ protected String getSignKeyboxIdentifier(String profile)
+ {
+ String key = getType() + "." + ConnectorConfigurationKeys.VALUE_MODE_SIGN + ".KeyboxIdentifier";
+ return getConnectorValueFromProfile(profile, key);
+ }
+
+ public String getVerifyURL(String profile)
+ {
+ String key = getType() + "." + ConnectorConfigurationKeys.VALUE_MODE_VERIFY + ".url";
+ return getConnectorValueFromProfile(profile, key);
+ }
+
+ protected String getVerifyRequestTemplateFileName(String profile)
+ {
+ String key = getType() + "." + ConnectorConfigurationKeys.VALUE_MODE_VERIFY + ".request";
+ return getConnectorValueFromProfile(profile, key);
+ }
+
+ protected String getVerifyTemplateFileName(String profile)
+ {
+ String key = getType() + "." + ConnectorConfigurationKeys.VALUE_MODE_VERIFY + ".template";
+ return getConnectorValueFromProfile(profile, key);
+ }
+
+ protected String getSigPropFileName(String profile)
+ {
+ String key = getType() + "." + ConnectorConfigurationKeys.VALUE_MODE_VERIFY + ".template.SP";
+ return getConnectorValueFromProfile(profile, key);
+ }
+
+ /**
+ * Returns the type of this BKU-like connector.
+ *
+ * <p>
+ * All settings keys will be prefixed by this type. So to reuse the BKU
+ * connector, a deriving class has to implement this method specifying an own
+ * type.
+ * </p>
+ *
+ * @return Returns the type of this BKU-like connector.
+ */
+ protected String getType()
+ {
+ return CONNECTOR_INFORMATION.getIdentifier();
+ }
+} \ No newline at end of file
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/BKUPostConnection.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/BKUPostConnection.java
new file mode 100644
index 0000000..b676ed8
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/BKUPostConnection.java
@@ -0,0 +1,157 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: BKUPostConnection.java,v 1.3 2006/10/11 07:56:10 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors;
+
+import java.io.IOException;
+import java.util.Properties;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.httpclient.Header;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpException;
+import org.apache.commons.httpclient.NameValuePair;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.params.HttpMethodParams;
+import org.apache.log4j.Logger;
+
+import at.knowcenter.wag.egov.egiz.cfg.ConfigLogger;
+
+/**
+ * @author wprinz
+ */
+public abstract class BKUPostConnection
+{
+ /**
+ * The logger definition.
+ */
+ private static final Logger logger_ = ConfigLogger.getLogger(BKUPostConnection.class);
+
+ /**
+ * This method connects the BKU server getting the request and the url. The
+ * request is an XML Message send and recieve by the HttpClient module. The
+ * Response message of the BKU server is is send back to the calling method.
+ *
+ * @param url
+ * the URL which the BKU server is running
+ * @param request
+ * the request string (XML) to send.
+ * @return the response string (XML) of the BKU server
+ * @throws IOException
+ * @throws HttpException
+ * ErrorCode:320
+ */
+ public static Properties doPostRequest(String url, String request) throws HttpException, IOException
+ {
+
+ PostMethod post_method = new PostMethod(url);
+
+ // It is very important to specify the charset of the content (the request)
+ // as UTF-8 this way.
+ // The HttpClient will then perform the URL encoding assuming that the
+ // request is UTF-8 as the BKU expects.
+ // If the MethodParams are omitted, the HttpClient will assume that the
+ // request is ISO-8859-1 and thereby the BKU cannot properly decode it.
+ HttpMethodParams method_params = new HttpMethodParams();
+ method_params.setContentCharset("UTF-8");
+ post_method.setParams(method_params);
+
+ // This is just a hint: do not set the content-type this way or the BKU will
+ // assume it as text/XML, but the HttpClient sends it as URL-encoded.
+ // The HttpClient will automatically generate the proper Content-Type:
+ // application/x-www-form-urlencoded
+ // post.addRequestHeader(new Header("Content-Type",
+ // "text/xml;charset=UTF-8"));
+
+ NameValuePair[] data = { new NameValuePair("XMLRequest", request) };
+ post_method.setRequestBody(data);
+
+ HttpClient http_client = new HttpClient();
+ int method_response = http_client.executeMethod(post_method);
+ logger_.debug("method_response = " + method_response);
+
+ Properties response_properties = new Properties();
+
+ if (logger_.isDebugEnabled())
+ {
+ Header[] response_headers = post_method.getResponseHeaders();
+ logger_.debug("#" + response_headers.length + " headers in response:");
+ for (int i = 0; i < response_headers.length; i++)
+ {
+ logger_.debug(" response_header[" + i + "]: name = " + response_headers[i].getName() + ", value = " + response_headers[i].getValue());
+ }
+ }
+
+ Header server_header = post_method.getResponseHeader("Server");
+ logger_.debug("server_header: name = " + server_header.getName() + ", value = " + server_header.getValue());
+
+ parseBKUVersion(server_header.getValue(), response_properties);
+
+
+ byte[] response_body = post_method.getResponseBody();
+ String response_string = new String(response_body, "UTF-8");
+
+ // Alternatively this could be used.
+ // The HttpClient is assumed to use the Content-Type provided by the
+ // response.
+ // String response_string = post.getResponseBodyAsString();
+
+ response_properties.setProperty("response_string", response_string);
+
+ return response_properties;
+ }
+
+ // TODO hotfix
+ public static void parseBKUVersion(String header_value, Properties properties)
+ {
+ // dummy bku header starts with Apache Coyote...
+ //Pattern pattern = Pattern.compile("^citizen-card-environment/(\\d+\\.\\d+) (.+)/(\\d+\\.\\d+\\.\\d+)$");
+ //Pattern pattern = Pattern.compile("^.*citizen-card-environment/(\\d+\\.\\d+) (.+)/(\\d+\\.\\d+\\.\\d+)$");
+ Pattern pattern = Pattern.compile("^.*citizen-card-environment/(\\d+\\.\\d+) (.+)/(\\d+\\.\\d+\\.\\d+)(.*)$");
+ Matcher m = pattern.matcher(header_value);
+
+ m.matches();
+
+ logger_.debug("group count = " + m.groupCount());
+
+ for (int i = 0; i <= m.groupCount(); i++)
+ {
+ logger_.debug(" group[" + i + "] = " + m.group(i));
+ }
+
+ final String cceVersion = m.group(1);
+ final String productName = m.group(2);
+ final String productVersion = m.group(3);
+
+ logger_.debug("cceVersion = " + cceVersion);
+ logger_.debug("productName = " + productName);
+ logger_.debug("productVersion = " + productVersion);
+
+ properties.setProperty("cceVersion", cceVersion);
+ properties.setProperty("productName", productName);
+ properties.setProperty("productVersion", productVersion);
+ }
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/Connector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/Connector.java
new file mode 100644
index 0000000..24dd728
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/Connector.java
@@ -0,0 +1,77 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors;
+
+import at.gv.egiz.pdfas.api.xmldsig.XMLDsigData;
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
+import at.knowcenter.wag.egov.egiz.sig.SignatureData;
+import at.knowcenter.wag.egov.egiz.sig.SignatureResponse;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject;
+
+/**
+ * @author wprinz
+ *
+ */
+public interface Connector
+{
+//23.11.2010 changed by exthex - added reconstructXMLDsig(SignatureData data, SignSignatureObject so)
+
+ /**
+ * Performs a sign.
+ *
+ * @param data
+ * The data to be signed.
+ * @return Returns the signature object containing the signature data.
+ * @throws ConnectorException
+ * Thrown if something goes wrong.
+ */
+
+ public SignSignatureObject doSign(SignatureData data) throws ConnectorException;
+
+ /**
+ * Performs a verification.
+ *
+ * @param data
+ * The data to be verified.
+ * @param so
+ * The signature object with the signature information.
+ * @param dsig
+ * The xmldsig info which will be enveloped in the verify request.
+ * @return Returns the SignatureResponse with the result of the verification.
+ * @throws ConnectorException
+ * Thrown if something goes wrong.
+ */
+ public SignatureResponse doVerify(SignatureData data, SignSignatureObject so, XMLDsigData dsig) throws ConnectorException;
+
+ /**
+ * Reconstruct the xmldsig info of the given {@link SignSignatureObject}
+ *
+ * @param data
+ * @param so
+ * @return
+ * @throws ConnectorException
+ */
+ public XMLDsigData reconstructXMLDsig(SignatureData data, SignSignatureObject so) throws ConnectorException;
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/ConnectorChooser.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/ConnectorChooser.java
new file mode 100644
index 0000000..2fee4da
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/ConnectorChooser.java
@@ -0,0 +1,353 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import at.gv.egiz.pdfas.api.commons.Constants;
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.gv.egiz.pdfas.framework.ConnectorParameters;
+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.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.moa.EnvelopingBase64MOAConnector;
+import at.knowcenter.wag.egov.egiz.sig.connectors.moa.MOASoapWithAttachmentConnector;
+import at.knowcenter.wag.egov.egiz.sig.connectors.mocca.LocRefDetachedMOCCAConnector;
+import at.knowcenter.wag.egov.egiz.sig.sigid.HotfixIdFormatter;
+
+/**
+ * Helper class that provides static methods that help the application to
+ * "choose" the right connector for a given task.
+ *
+ * @deprecated functionality split to ConnectorChooser implementations in framework commandline and web
+ *
+ * @author wprinz
+ */
+public final class ConnectorChooser
+{
+ /**
+ * The log.
+ */
+ private static Log log = LogFactory.getLog(ConnectorChooser.class);
+
+ public static LocalConnector chooseLocalConnectorForSign(String connector,
+ String profile, String loc_ref_url) throws ConnectorException
+ {
+ log.debug("Choosing LocalConnector for signation...");
+
+ log.debug("connector type = " + connector);
+
+ ConnectorParameters cp = new ConnectorParameters();
+ cp.setProfileId(profile);
+
+ if (Constants.SIGNATURE_DEVICE_MOC.equals(connector)) {
+
+ return new LocRefDetachedMOCCAConnector(cp, loc_ref_url);
+
+ } else if (Constants.SIGNATURE_DEVICE_BKU.equals(connector)){
+
+ return new LocRefDetachedBKUConnector(cp, loc_ref_url);
+
+ }
+
+ log.error("Currently only the BKU connector is fully implemented.");
+ return new LocRefDetachedBKUConnector(cp, loc_ref_url);
+ }
+
+ public static Connector chooseWebConnectorForSign(String connector,
+ String profile, String loc_ref_url) throws ConnectorException
+ {
+ log.debug("Choosing Connector for WEB signation...");
+
+ log.debug("connector type = " + connector);
+
+ if (!connector.equals(Constants.SIGNATURE_DEVICE_MOA))
+ {
+ log.error("Currently only the MOA connector is available for non local WEB signation.");
+ }
+
+ log.debug("choosing locref detached MOA connector.");
+
+ //TODO TR: Hier umschalten, um von SwA-Requests zurueckzuwechseln.
+ // Loc_Ref-Connector
+// return new DetachedLocRefMOAConnector(profile, loc_ref_url);
+ // SwA-Connector
+ ConnectorParameters cp = new ConnectorParameters();
+ cp.setProfileId(profile);
+ return new MOASoapWithAttachmentConnector(cp);
+ }
+
+// public static Connector chooseCommandlineConnectorForSign(String connector,
+// String profile) throws ConnectorException
+// {
+// log.debug("Choosing Connector for commandline signation...");
+//
+// log.debug("connector type = " + connector);
+//
+// if (connector.equals(BKU))
+// {
+// log.debug("sig_app is BKU ==> MultipartDetachedBKUConnector"); //$NON-NLS-1$
+//
+// return new MultipartDetachedBKUConnector(profile);
+// }
+// if (connector.equals(MOA))
+// {
+// // TODO MOA detached signing is not allowed at the commandline
+// log.warn("Detached MOA is not supported on the commandline. -> choosing Base64 temporarily.");
+// return new EnvelopingBase64MOAConnector(profile);
+// }
+//
+// throw new ConnectorException(300, "Unknown connector type '" + connector + "' specified.");
+// }
+
+ public static 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. Please get a new version of PDF-AS. Your version is: " + PdfAS.PDFAS_VERSION);
+ }
+
+ public static Connector chooseWebConnectorForVerify(String connector,
+ PdfASID sig_kz, String sig_id, String profile, String loc_ref_url) throws ConnectorException
+ {
+ log.debug("Choosing Connector for WEB verification...");
+
+ log.debug("connector type = " + connector);
+ log.debug("sig_kz = " + sig_kz);
+ log.debug("sig_id = " + sig_id);
+
+ if (!connector.equals("moa"))
+ {
+ log.error("Currently only the MOA connector is available for non local WEB signation.");
+ }
+
+ if (sig_kz == null || sig_kz.getVersion().equals(SignatorFactory.VERSION_1_0_0))
+ {
+ log.debug("sig_kz is null or sig_kz version is 1.0.0 -> choosing Base64 connector.");
+
+ ConnectorParameters cp = new ConnectorParameters();
+ cp.setProfileId(profile);
+ return new EnvelopingBase64MOAConnector(cp);
+ }
+
+ 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.");
+
+ //throw new ConnectorException(ErrorCode.DETACHED_SIGNATURE_NOT_SUPPORTED, "The MOA detached connector is not suitable for verification.");
+ // TODO TR: Switch her for SwA or Detached-URL Connector
+ // the following line is used in connection with LocRef-Connector
+// return new DetachedLocRefMOAConnector(profile, loc_ref_url);
+ // the following line is uesed in connection with SwA-Connector
+ ConnectorParameters cp = new ConnectorParameters();
+ cp.setProfileId(profile);
+ return new MOASoapWithAttachmentConnector(cp);
+ }
+ 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);
+ }
+
+// public static Connector chooseCommandlineConnectorForVerify(String connector,
+// PdfASID sig_kz, String sig_id, String profile) throws ConnectorException
+// {
+// log.debug("Choosing Connector for Commandline verification...");
+//
+// log.debug("connector type = " + connector);
+// 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 -> chose an old enveloped base64 connector"); //$NON-NLS-1$
+//
+// return chooseEnvelopedBase64ConnectorOld(profile, connector);
+// }
+//
+// 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 chooseEnvelopedBase64ConnectorHotfix(profile, connector);
+// }
+//
+// 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 chooseEnvelopedBase64ConnectorOld(profile, connector);
+// }
+// if (sig_id_parts[0].equals(HotfixIdFormatter.SIG_ID_PREFIX))
+// {
+// log.debug("sig_id prefix is hotfix -> choosing hotfix base64 connector");
+//
+// return chooseEnvelopedBase64ConnectorHotfix(profile, connector);
+// }
+//
+// 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(profile, connector);
+// }
+//
+// throw new ConnectorException(310, "The SIG_KZ version '" + sig_kz.getVersion() + "' is unknown.");
+// }
+
+ protected static final String BKU = "bku"; //$NON-NLS-1$
+
+ protected static final String MOA = "moa"; //$NON-NLS-1$
+
+ protected static Connector chooseEnvelopedBase64ConnectorOld(String profile,
+ String sig_app) throws ConnectorException
+ {
+ if (sig_app.equals(BKU))
+ {
+ log.debug("sig_app is BKU ==> OldEnvelopingBase64BKUConnector"); //$NON-NLS-1$
+
+ return new OldEnvelopingBase64BKUConnector(profile);
+ }
+ if (sig_app.equals(MOA))
+ {
+ log.debug("sig_app is MOA ==> EnvelopingBase64MOAConnector"); //$NON-NLS-1$
+
+ ConnectorParameters cp = new ConnectorParameters();
+ cp.setProfileId(profile);
+ return new EnvelopingBase64MOAConnector(cp);
+ }
+ throw new ConnectorException(310, "Unknown sig_app '" + sig_app + "'."); //$NON-NLS-1$ //$NON-NLS-2$
+
+ }
+
+ protected static Connector chooseEnvelopedBase64ConnectorHotfix(
+ String profile, String sig_app) throws ConnectorException
+ {
+ if (sig_app.equals(BKU))
+ {
+ log.debug("sig_app is BKU ==> EnvelopedBase64BKUConnector"); //$NON-NLS-1$
+
+ return new EnvelopedBase64BKUConnector(profile);
+ }
+ if (sig_app.equals(MOA))
+ {
+ log.debug("sig_app is MOA ==> EnvelopedBase64MOAConnector"); //$NON-NLS-1$
+
+ ConnectorParameters cp = new ConnectorParameters();
+ cp.setProfileId(profile);
+ return new EnvelopingBase64MOAConnector(cp);
+ }
+ throw new ConnectorException(310, "Unknown sig_app '" + sig_app + "'."); //$NON-NLS-1$ //$NON-NLS-2$
+
+ }
+
+ protected static Connector chooseDetachedMultipartConnector(String profile,
+ String sig_app) throws ConnectorException
+ {
+ if (sig_app.equals(BKU))
+ {
+ log.debug("sig_app is BKU ==> DetachedMultipartBKUConnector"); //$NON-NLS-1$
+
+ ConnectorParameters cp = new ConnectorParameters();
+ cp.setProfileId(profile);
+ return new MultipartDetachedBKUConnector(cp);
+ }
+ 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);
+ }
+ 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/knowcenter/wag/egov/egiz/sig/connectors/ConnectorConfigurationKeys.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/ConnectorConfigurationKeys.java
new file mode 100644
index 0000000..fa340cd
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/ConnectorConfigurationKeys.java
@@ -0,0 +1,55 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors;
+
+/**
+ * This class contains the key constants used by the Connectors to retrieve
+ * templates etc. from the Configuration.
+ *
+ * @author wprinz
+ */
+public abstract class ConnectorConfigurationKeys
+{
+
+ /**
+ * 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 key used to read out the available for web property.
+ */
+ public static final String AVAILABLE_FOR_WEB = "available_for_web";
+
+ /**
+ * The key used to read out the available for commandline property.
+ */
+ public static final String AVAILABLE_FOR_COMMANDLINE = "available_for_commandline";
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/ConnectorEnvironment.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/ConnectorEnvironment.java
new file mode 100644
index 0000000..451f367
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/ConnectorEnvironment.java
@@ -0,0 +1,52 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors;
+
+import java.security.cert.X509Certificate;
+
+/**
+ * Base class for connector environments
+ *
+ * @author dferbas
+ *
+ */
+public abstract class ConnectorEnvironment {
+
+ public abstract String getCertAlgEcdsa();
+
+ public abstract String getCertAlgRsa();
+
+ public abstract String getVerifyTemplate();
+
+ public String getDefaultAlgForCert(X509Certificate cert) {
+ String cert_alg;
+ cert_alg = getCertAlgEcdsa();
+ if (cert.getPublicKey().getAlgorithm().indexOf("RSA") >= 0) //$NON-NLS-1$
+ {
+ cert_alg = getCertAlgRsa();
+ }
+ return cert_alg;
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/LocalConnector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/LocalConnector.java
new file mode 100644
index 0000000..5279a03
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/LocalConnector.java
@@ -0,0 +1,91 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors;
+
+import java.util.Properties;
+
+import at.gv.egiz.pdfas.api.xmldsig.XMLDsigData;
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
+import at.knowcenter.wag.egov.egiz.sig.SignatureData;
+import at.knowcenter.wag.egov.egiz.sig.SignatureResponse;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject;
+
+/**
+ * @author wprinz
+ */
+public interface LocalConnector
+{
+//23.11.2010 changed by exthex - added XMLDsigData parameter to prepareVerifyRequest to allow reuse
+
+ /**
+ * Prepares the sign request xml to be sent using the sign request template.
+ *
+ * @param data
+ * The SignatureData.
+ * @return Returns the sign request xml to be sent.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public String prepareSignRequest(SignatureData data) throws ConnectorException;
+
+ /**
+ * Analyzes the sign response xml and extracts the signature data.
+ *
+ * @param response_properties
+ * The response properties containing the response String and
+ * transport related information.
+ * @return Returns the extracted data encapsulated in a SignatureObject.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public SignSignatureObject analyzeSignResponse(Properties response_properties) throws ConnectorException;
+
+ /**
+ * Prepares the verify request xml to be sent using the verify request
+ * template.
+ *
+ * @param data
+ * The SignatureData.
+ * @param so
+ * The signature information object.
+ * @param dsigData
+ * The previously recreated xmldsig block of the signature
+ * @return Returns the verify request xml to be sent.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public String prepareVerifyRequest(SignatureData data, SignSignatureObject so, XMLDsigData dsigData) throws ConnectorException;
+
+ /**
+ * Analyzes the verify response string.
+ *
+ * @param response_properties
+ * The response properties containing the response XML.
+ * @return Returns the SignatureResponse containing the verification result.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public SignatureResponse analyzeVerifyResponse(Properties response_properties) throws ConnectorException;
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/MOAConnector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/MOAConnector.java
new file mode 100644
index 0000000..ef355a0
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/MOAConnector.java
@@ -0,0 +1,921 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: MOAConnector.java,v 1.5 2006/10/31 08:18:41 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.Vector;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.rpc.Call;
+import javax.xml.rpc.Service;
+import javax.xml.rpc.ServiceFactory;
+
+import org.apache.axis.message.SOAPBodyElement;
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.apache.xml.serialize.OutputFormat;
+import org.apache.xml.serialize.XMLSerializer;
+import org.w3c.dom.Document;
+
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.gv.egiz.pdfas.exceptions.external.ExternalErrorException;
+import at.knowcenter.wag.egov.egiz.cfg.ConfigLogger;
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+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.exceptions.WebException;
+import at.knowcenter.wag.egov.egiz.sig.Connector;
+import at.knowcenter.wag.egov.egiz.sig.ConnectorInformation;
+import at.knowcenter.wag.egov.egiz.sig.SignatureObject;
+import at.knowcenter.wag.egov.egiz.sig.SignatureResponse;
+import at.knowcenter.wag.egov.egiz.sig.X509Cert;
+import at.knowcenter.wag.egov.egiz.tools.CodingHelper;
+
+/**
+ * Connector to access the MOA service.
+ *
+ * @deprecated
+ * @author wlackner
+ * @author wprinz
+ */
+public class MOAConnector implements Connector
+{
+ /**
+ * ConnectorInformation that identifies this Connector to the system.
+ *
+ * @see at.knowcenter.wag.egov.egiz.sig.ConnectorFactory
+ * @see ConnectorInformation
+ */
+ public static final ConnectorInformation CONNECTOR_INFORMATION = new ConnectorInformation("moa", "MOA");
+
+ /**
+ * The class type value.
+ *
+ * <p>
+ * Just for convenience.
+ * </p>
+ */
+ private static final String TYPE = CONNECTOR_INFORMATION.getIdentifier();
+
+ /**
+ * The connector description.
+ */
+ public static final String DESCRIPTION = "MOA";
+
+ /**
+ * The SettingsReader instance
+ */
+ private SettingsReader settings_ = null;
+
+ /**
+ * MOA siganture verification mode
+ */
+ public static final String SERVICE_VERIFY = "SignatureVerification";
+
+ /**
+ * MOA siganture creation mode
+ */
+ public static final String SERVICE_SIGN = "SignatureCreation";
+
+ /**
+ * The logger definition.
+ */
+ private static final Logger logger_ = ConfigLogger.getLogger(MOAConnector.class);
+
+ /**
+ * The empty constructor
+ */
+ public MOAConnector() throws SignatureException
+ {
+ loadSettings();
+ }
+
+ /**
+ * load the inital signature settings
+ *
+ * @see SettingsReader
+ */
+ private void loadSettings() throws SignatureException
+ {
+ if (settings_ == null)
+ {
+ try
+ {
+ settings_ = SettingsReader.getInstance();
+ }
+ catch (SettingsException e)
+ {
+ String log_message = "Can not load signature settings. Cause:\n" + e.getMessage();
+ logger_.error(log_message);
+ throw new SignatureException(101, log_message, e);
+ }
+ }
+ }
+
+ /**
+ * This method calls the MOA signing a given text. The signaton type is to
+ * used initializing the corresponding SigantureObject. The initialized
+ * SignatureObject is filled out by the parsed MOA-Response. <br>
+ * If an error request is send back from MOA, an error message is generated an
+ * an exception is thrown.
+ *
+ * @param sigType
+ * the type of the SignatureObject that should be returned
+ * @param userName
+ * the name of the user calling this method
+ * @param signText
+ * the text that shoulf be signed from MOA
+ * @return the complete SingatureObject of the given type filled by values
+ * from the MOA-Request
+ * @throws SignatureException
+ * ErrorCode 300
+ * @see SignatureObject
+ */
+ public SignatureObject doSign(String sigType, String userName, String signText) throws SignatureException
+ {
+ SignatureObject sig_obj = new SignatureObject();
+ try
+ {
+ sig_obj.setSigType(sigType);
+ sig_obj.initByType();
+ }
+ catch (SignatureTypesException e)
+ {
+ SignatureException se = new SignatureException(300, "Can ot init signature object with type:" + sigType, e);
+ throw se;
+ }
+ if (logger_.isDebugEnabled())
+ {
+ logger_.debug("Signature Type is:" + sig_obj.getSignationType());
+ }
+ if (logger_.isInfoEnabled())
+ {
+ logger_.info("Call " + TYPE + " from user:" + userName);
+ }
+
+ String url = getSignURL(sigType);
+
+ String sign_request_filename = getSignRequestTemplateFileName(sigType);
+ String key_ident = getSignKeyIdentifier(sigType);
+
+ //String sign_req_str = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename));
+ String sign_req_str = this.settings_.readInternalResourceAsString(sign_request_filename);
+ if (sign_req_str == null)
+ {
+ SignatureException se = new SignatureException(300, "File not found:" + sign_request_filename);
+ throw se;
+ }
+
+ sign_req_str = sign_req_str.replaceFirst("KeyIdentifierReplace", key_ident);
+ if (logger_.isDebugEnabled())
+ {
+ //logger_.debug("error_signature_response = " + sign_req_str);
+ // FileHelper.writeToFile(sign_request_filename + "_signText.xml",
+ // signText);
+ }
+ // sign_req_str = sign_req_str.replaceFirst("XMLContentReplace", signText);
+ // now use the the base64 Template
+ signText = CodingHelper.encodeUTF8AsBase64(signText);
+ sign_req_str = sign_req_str.replaceFirst("Base64ContentReplace", signText);
+ if (logger_.isDebugEnabled())
+ {
+ //logger_.debug(sign_req_str);
+ // FileHelper.writeToFile(sign_request_filename + "_request.xml",
+ // sign_req_str);
+ }
+
+ String response_string = "";
+ try
+ {
+ response_string = MOAConnector.connectMOA(sign_req_str, MOAConnector.SERVICE_SIGN, url);
+ sig_obj.setRawSignatureResponse(response_string);
+ }
+ catch (WebException we)
+ {
+ SignatureException se = new SignatureException(we.getErrorCode(), we);
+ throw se;
+ }
+
+ if (!response_string.equals(""))
+ {
+ if (logger_.isInfoEnabled())
+ {
+ logger_.info("get MOA response");
+ }
+ Pattern erc_p_s = Pattern.compile("<ErrorCode>");
+ Pattern erc_p_e = Pattern.compile("</ErrorCode>");
+ Matcher erc_m_s = erc_p_s.matcher(response_string);
+ Matcher erc_m_e = erc_p_e.matcher(response_string);
+ // System.err.println(response_string);
+
+ if (erc_m_s.find() && erc_m_e.find())
+ {
+ if (logger_.isEnabledFor(Level.ERROR))
+ {
+ logger_.error("error_signature_response = " + response_string);
+ // FileHelper.writeToFile(sign_request_filename + "_response.xml",
+ // response_string);
+ //logger_.error("Write error response to file:" + sign_request_filename + "_response.xml");
+ }
+ Pattern erm_p_s = Pattern.compile("<Info>");
+ Pattern erm_p_e = Pattern.compile("</Info>");
+ Matcher erm_m_s = erm_p_s.matcher(response_string);
+ Matcher erm_m_e = erm_p_e.matcher(response_string);
+
+ String error_code = response_string.substring(erc_m_s.end(), erc_m_e.start());
+ logger_.debug("error_code = " + error_code);
+ String error_mess = "";
+ if (erm_m_s.find() && erm_m_e.find())
+ {
+ error_mess = response_string.substring(erm_m_s.end(), erm_m_e.start());
+ logger_.debug(error_mess);
+ }
+ throw new SignatureException(new ExternalErrorException(error_code, error_mess));
+ }
+ else
+ {
+ if (logger_.isDebugEnabled())
+ {
+ //logger_.debug("response_string = " + response_string);
+ // FileHelper.writeToFile(sign_request_filename + "_response.xml",
+ // response_string);
+ }
+ parseCreateXMLResponse(response_string, sig_obj);
+ }
+ }
+ sig_obj.setSigResponse(response_string);
+ return sig_obj;
+ }
+
+ /**
+ * This method parses the MOA-Response string. It separates the
+ * SignatureValue, X509IssuerName, SigningTime, X509SerialNumber,
+ * X509Certificate, CertDigest and DigestValues. If the X509Certificate is
+ * extracted it would be stored in the certificates directory.
+ *
+ * @param xmlResponse
+ * the response string from the MOA sign-request
+ * @param sigObj
+ * the SignatureObject that should be filled
+ * @throws SignatureException
+ * ErrorCode (303, 304)
+ * @see SignatureObject
+ * @see CodingHelper
+ * @see X509Cert
+ */
+ private void parseCreateXMLResponse(String xmlResponse, SignatureObject sigObj) throws SignatureException
+ {
+ Pattern sig_val_p_s = Pattern.compile("<[\\w]*:?SignatureValue>");
+ Pattern sig_val_p_e = Pattern.compile("</[\\w]*:?SignatureValue>");
+ Pattern iss_nam_p_s = Pattern.compile("<[\\w]*:?X509IssuerName>");
+ Pattern iss_nam_p_e = Pattern.compile("</[\\w]*:?X509IssuerName>");
+ Pattern sig_tim_p_s = Pattern.compile("<[\\w]*:?SigningTime>");
+ Pattern sig_tim_p_e = Pattern.compile("</[\\w]*:?SigningTime>");
+ Pattern ser_num_p_s = Pattern.compile("<[\\w]*:?X509SerialNumber>");
+ Pattern ser_num_p_e = Pattern.compile("</[\\w]*:?X509SerialNumber>");
+ Pattern sig_cer_p_s = Pattern.compile("<[\\w]*:?X509Certificate>");
+ Pattern sig_cer_p_e = Pattern.compile("</[\\w]*:?X509Certificate>");
+
+ Pattern sig_cer_d_p_s = Pattern.compile("<[\\w]*:?CertDigest>");
+ Pattern sig_cer_d_p_e = Pattern.compile("</[\\w]*:?CertDigest>");
+ Pattern dig_val_p_s = Pattern.compile("<[\\w]*:?DigestValue>");
+ Pattern dig_val_p_e = Pattern.compile("</[\\w]*:?DigestValue>");
+
+ Matcher sig_val_m_s = sig_val_p_s.matcher(xmlResponse);
+ Matcher sig_val_m_e = sig_val_p_e.matcher(xmlResponse);
+ Matcher iss_nam_m_s = iss_nam_p_s.matcher(xmlResponse);
+ Matcher iss_nam_m_e = iss_nam_p_e.matcher(xmlResponse);
+ Matcher sig_tim_m_s = sig_tim_p_s.matcher(xmlResponse);
+ Matcher sig_tim_m_e = sig_tim_p_e.matcher(xmlResponse);
+ Matcher ser_num_m_s = ser_num_p_s.matcher(xmlResponse);
+ Matcher ser_num_m_e = ser_num_p_e.matcher(xmlResponse);
+ Matcher sig_cer_m_s = sig_cer_p_s.matcher(xmlResponse);
+ Matcher sig_cer_m_e = sig_cer_p_e.matcher(xmlResponse);
+
+ Matcher sig_cer_d_m_s = sig_cer_d_p_s.matcher(xmlResponse);
+ Matcher sig_cer_d_m_e = sig_cer_d_p_e.matcher(xmlResponse);
+
+ String sig_val = "";
+ String iss_nam = "";
+ String ser_num = "";
+ String sig_tim = "";
+ String sig_cer = "";
+ String sig_dig = "";
+
+ // SignatureValue
+ if (sig_val_m_s.find() && sig_val_m_e.find())
+ {
+ sig_val = xmlResponse.substring(sig_val_m_s.end(), sig_val_m_e.start());
+ sig_val = sig_val.replaceAll("\\s", "");
+ sigObj.setSignationValue(sig_val);
+ }
+ // X509IssuerName
+ if (iss_nam_m_s.find() && iss_nam_m_e.find())
+ {
+ iss_nam = xmlResponse.substring(iss_nam_m_s.end(), iss_nam_m_e.start());
+ sigObj.setSignationIssuer(iss_nam);
+ }
+ // X509SerialNumber
+ if (ser_num_m_s.find() && ser_num_m_e.find())
+ {
+ ser_num = xmlResponse.substring(ser_num_m_s.end(), ser_num_m_e.start());
+ sigObj.setSignationSerialNumber(ser_num);
+ }
+ // SigningTime
+ if (sig_tim_m_s.find() && sig_tim_m_e.find())
+ {
+ sig_tim = xmlResponse.substring(sig_tim_m_s.end(), sig_tim_m_e.start());
+ sigObj.setSignationDate(sig_tim);
+ }
+ // CertDigest
+ if (sig_cer_d_m_s.find() && sig_cer_d_m_e.find())
+ {
+ String cert_digest = xmlResponse.substring(sig_cer_d_m_s.end(), sig_cer_d_m_e.start());
+ Matcher dig_val_m_s = dig_val_p_s.matcher(cert_digest);
+ Matcher dig_val_m_e = dig_val_p_e.matcher(cert_digest);
+ if (dig_val_m_s.find() && dig_val_m_e.find())
+ {
+ sig_dig = cert_digest.substring(dig_val_m_s.end(), dig_val_m_e.start());
+ sigObj.setX509CertificateDigest(sig_dig);
+ }
+ }
+ // extract Subject Name from X509Certificate
+ if (sig_cer_m_s.find() && sig_cer_m_e.find())
+ {
+ sig_cer = xmlResponse.substring(sig_cer_m_s.end(), sig_cer_m_e.start());
+ sig_cer = sig_cer.replaceAll("\\s", "");
+ X509Cert cert = X509Cert.initByString(sig_cer);
+ if (cert.isX509Cert())
+ {
+ sigObj.setX509Certificate(cert.getCertString());
+ String serial_num = cert.getSerialNumber();
+ String subject_name = cert.getSubjectName();
+ if (!ser_num.equals(serial_num))
+ {
+ SignatureException se = new SignatureException(303, "Serialnumber of certificate and tag X509SerialNumber differs!");
+ throw se;
+ }
+ sigObj.setSignationName(subject_name);
+ }
+ }
+ }
+
+ /**
+ * This method reads the verify template from the file system and fills out
+ * the template with the SignatureObject values.
+ *
+ * @param normalizedText
+ * the normalized text to veryfied
+ * @param sigObject
+ * the SignatureObject holding the singature values
+ * @return the filled verify template string
+ * @throws SignatureException
+ * ErrorCode (311, 312, 313)
+ * @see SignatureObject
+ * @see CodingHelper
+ */
+ public String getVerifyTemplate(String normalizedText,
+ SignatureObject sigObject) throws SignatureException
+ {
+ try
+ {
+ if (normalizedText == null || normalizedText.length() == 0)
+ {
+ SignatureException se = new SignatureException(311, "Document can not be verified because normalized text is empty.");
+ throw se;
+ }
+ if (sigObject == null)
+ {
+ SignatureException se = new SignatureException(312, "Document can not be verified because no signature object are set.");
+ throw se;
+ }
+ String verify_template = getVerifyTemplateFileName(sigObject.getSignationType());
+ String sig_prop_template = getSigPropFileName(sigObject.getSignationType());
+
+ //String verify_req_str = FileHelper.readFromFile(SettingsReader.relocateFile(verify_template));
+ String verify_req_str = this.settings_.readInternalResourceAsString(verify_template);
+
+ //String sig_prop_str = FileHelper.readFromFile(SettingsReader.relocateFile(sig_prop_template));
+ String sig_prop_str = this.settings_.readInternalResourceAsString(sig_prop_template);
+
+ if (logger_.isDebugEnabled())
+ {
+ //logger_.debug(verify_template);
+ //logger_.debug(sig_prop_template);
+ }
+
+ String x509Certificate = sigObject.getX509CertificateString();
+ if (x509Certificate == null)
+ {
+ SignatureException se = new SignatureException(ErrorCode.CERTIFICATE_NOT_FOUND, "Document certificate is not defined.");
+ throw se;
+ }
+ String cert_alg = settings_.getValueFromKey("cert.alg.ecdsa");
+ X509Cert x509_cert = sigObject.getX509Cert();
+ if (x509_cert.isRSA())
+ {
+ cert_alg = settings_.getValueFromKey("cert.alg.rsa");
+ }
+
+ sig_prop_str = sig_prop_str.replaceFirst("SigningTimeReplace", sigObject.getSignationDate());
+ // The issuer is already a valid Unicode String.
+ // No need to convert it - not to mention the missing encoding.
+ // byte[] issuer_name =
+ // CodingHelper.encodeUTF8(sigObject.getSignationIssuer());
+ // new String(issuer_name)
+ sig_prop_str = sig_prop_str.replaceFirst("X509IssuerNameReplace", sigObject.getSignationIssuer());
+ sig_prop_str = sig_prop_str.replaceFirst("X509SerialNumberReplace", sigObject.getSignationSerialNumber());
+ sig_prop_str = sig_prop_str.replaceFirst("DigestValueX509CertificateReplace", sigObject.getX509CertificateDigest());
+
+ verify_req_str = verify_req_str.replaceFirst("CertAlgReplace", cert_alg);
+ verify_req_str = verify_req_str.replaceFirst("TemplateSignedPropertiesReplace", sig_prop_str);
+ byte[] sig_prop_code = CodingHelper.buildDigest(sig_prop_str.getBytes("UTF-8"), "sha1"); // added
+ // the
+ // ("UTF-8")
+ // encoding
+ String sig_prop_hash = CodingHelper.encodeBase64(sig_prop_code);
+ verify_req_str = verify_req_str.replaceFirst("DigestValueSignedPropertiesReplace", sig_prop_hash);
+ if (logger_.isDebugEnabled())
+ {
+ logger_.debug("build digest from SignedProperties:start");
+ //logger_.debug("DATA :" + sig_prop_str);
+ logger_.debug("DIGEST:" + sig_prop_hash);
+ logger_.debug("build digest from SignedProperties:end");
+ }
+
+ verify_req_str = verify_req_str.replaceFirst("SignatureValueReplace", sigObject.getSignationValue());
+ verify_req_str = verify_req_str.replaceFirst("X509CertificateReplace", x509Certificate);
+ byte[] data_value = normalizedText.getBytes("UTF-8");
+ byte[] data_value_hash = CodingHelper.buildDigest(data_value, "sha1");
+ // byte[] data_value_hash =
+ // CodingHelper.buildDigest(normalizedText.getBytes());
+ String object_data_hash = CodingHelper.encodeBase64(data_value_hash);
+ //String object_data = normalizedText; // new String(data_value);
+ // System.err.println(object_data_hash);
+ // very_req_str = very_req_str.replaceFirst("ObjectDataReplace",
+ // object_data);
+ String raw_b64 = CodingHelper.encodeBase64(data_value);
+ verify_req_str = verify_req_str.replaceFirst("Base64ContentReplace", raw_b64);
+
+ verify_req_str = verify_req_str.replaceFirst("DigestValueSignedDataReplace", object_data_hash);
+ if (logger_.isDebugEnabled())
+ {
+ // FileHelper.writeToFile(verify_template + "_verifyText.xml",
+ // normalizedText);
+ logger_.debug("build digest from data object:start");
+ //logger_.debug("DATA :" + object_data);
+ logger_.debug("DIGEST:" + object_data_hash);
+ logger_.debug("build digest from data object:end");
+ }
+ return verify_req_str;
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ throw new SignatureException(310, e);
+ }
+ }
+
+ /**
+ * This method generates the MOA verify prozess. It checks if the given
+ * SignatureObject is signed by MOA or BKU. The verify template string is
+ * filled out by the corresponding method.
+ *
+ * @param normalizedText
+ * the normalized text to verify
+ * @param sigObject
+ * the SignatureObject holding the singature values
+ * @return a SignatureResponse object if the verify prozess does not fails
+ * @throws SignatureException
+ * @see SignatureResponse
+ */
+ public SignatureResponse doVerify(String normalizedText,
+ SignatureObject sigObject) throws SignatureException
+ {
+ String verify_url = getVerifyURL(sigObject.getSignationType()); // settings_.getValueFromKey(TYPE
+ // + "." +
+ // Signature.VALUE_MODE_VERIFY
+ // +
+ // ".url");
+ String verify_request = getVerifyRequestTemplateFileName(sigObject.getSignationType()); // settings_.getValueFromKey(TYPE
+ // +
+ // "."
+ // +
+ // Signature.VALUE_MODE_VERIFY
+ // +
+ // ".request");
+ String trust_profile = getVerifyTrustProfileID(sigObject.getSignationType());
+
+ //String verify_req_str = FileHelper.readFromFile(SettingsReader.relocateFile(verify_request));
+ String verify_req_str = this.settings_.readInternalResourceAsString(verify_request);
+
+ String verify_template_str = null;
+ if (sigObject.isMOASigned())
+ {
+ verify_template_str = getVerifyTemplate(normalizedText, sigObject);
+ }
+ else
+ {
+ BKUConnector bku_conn = new BKUConnector();
+ verify_template_str = bku_conn.getVerifyTemplate(normalizedText, sigObject);
+ }
+ verify_req_str = verify_req_str.replaceFirst("XMLContentReplace", verify_template_str);
+ verify_req_str = verify_req_str.replaceFirst("TrustProfileIDReplace", trust_profile);
+
+ if (logger_.isDebugEnabled())
+ {
+ //logger_.debug(verify_req_str);
+ // FileHelper.writeToFile(verify_request + "_request.xml",
+ // verify_req_str);
+ }
+ String response_string = "";
+ try
+ {
+ response_string = MOAConnector.connectMOA(verify_req_str, MOAConnector.SERVICE_VERIFY, verify_url);
+ }
+ catch (WebException we)
+ {
+ if (logger_.isDebugEnabled())
+ {
+ we.printStackTrace();
+ }
+ SignatureException se = new SignatureException(we.getErrorCode(), we);
+ throw se;
+ }
+
+ if (!response_string.equals(""))
+ {
+ Pattern erc_p_s = Pattern.compile("<[\\w]*:?ErrorCode>");
+ Pattern erc_p_e = Pattern.compile("</[\\w]*:?ErrorCode>");
+ Matcher erc_m_s = erc_p_s.matcher(response_string);
+ Matcher erc_m_e = erc_p_e.matcher(response_string);
+
+ if (erc_m_s.find() && erc_m_e.find())
+ {
+ if (logger_.isEnabledFor(Level.ERROR))
+ {
+ //logger_.debug(response_string);
+ // FileHelper.writeToFile(verify_request + "_response.xml",
+ // response_string);
+ logger_.error("Write error response to file:" + verify_request + "_response.xml");
+ }
+ Pattern erm_p_s = Pattern.compile("<[\\w]*:?Info>");
+ Pattern erm_p_e = Pattern.compile("</[\\w]*:?Info>");
+ Matcher erm_m_s = erm_p_s.matcher(response_string);
+ Matcher erm_m_e = erm_p_e.matcher(response_string);
+ String error_code = response_string.substring(erc_m_s.end(), erc_m_e.start());
+ String error_mess = null;
+ if (erm_m_s.find() && erm_m_e.find())
+ {
+ error_mess = response_string.substring(erm_m_s.end(), erm_m_e.start());
+ }
+ throw new SignatureException(new ExternalErrorException(error_code, error_mess));
+ }
+ else
+ {
+ if (logger_.isDebugEnabled())
+ {
+ //logger_.debug(verify_request + "_response.xml " + response_string);
+ }
+ return parseVerifyXMLResponse(response_string);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * This method parses the verify response string and return a
+ * SignatureResponse object. The SignatureResponse object is filled out by the
+ * response values from the BKU-response.
+ *
+ * @param xmlResponse
+ * the response values from the MOA-verify request
+ * @return SignatureResponse object
+ * @see SignatureResponse
+ */
+ private SignatureResponse parseVerifyXMLResponse(String xmlResponse)
+ {
+ if (logger_.isInfoEnabled())
+ {
+ logger_.info("Try parsing the verify response");
+ }
+ Pattern sub_nam_p_s = Pattern.compile("<dsig:X509SubjectName>");
+ Pattern sub_nam_p_e = Pattern.compile("</dsig:X509SubjectName>");
+ Pattern iss_nam_p_s = Pattern.compile("<dsig:X509IssuerName>");
+ Pattern iss_nam_p_e = Pattern.compile("</dsig:X509IssuerName>");
+ Pattern ser_num_p_s = Pattern.compile("<dsig:X509SerialNumber>");
+ Pattern ser_num_p_e = Pattern.compile("</dsig:X509SerialNumber>");
+
+ // [tknall] start qualified certificate
+ Pattern cert_qualified_p = Pattern.compile("<QualifiedCertificate/>");
+ Matcher cert_qualified_m = cert_qualified_p.matcher(xmlResponse);
+ // [tknall] stop qualified certificate
+
+ Pattern sig_chk_p_s = Pattern.compile("<SignatureCheck>");
+ Pattern sig_chk_p_e = Pattern.compile("</SignatureCheck>");
+ Pattern man_chk_p_s = Pattern.compile("<SignatureManifestCheck>");
+ Pattern man_chk_p_e = Pattern.compile("</SignatureManifestCheck>");
+ Pattern cer_chk_p_s = Pattern.compile("<CertificateCheck>");
+ Pattern cer_chk_p_e = Pattern.compile("</CertificateCheck>");
+
+ Pattern code_p_s = Pattern.compile("<Code>");
+ Pattern code_p_e = Pattern.compile("</Code>");
+
+ Pattern cert_p_s = Pattern.compile("<dsig:X509Certificate>");
+ Pattern cert_p_e = Pattern.compile("</dsig:X509Certificate>");
+
+ Matcher sub_nam_m_s = sub_nam_p_s.matcher(xmlResponse);
+ Matcher sub_nam_m_e = sub_nam_p_e.matcher(xmlResponse);
+ Matcher iss_nam_m_s = iss_nam_p_s.matcher(xmlResponse);
+ Matcher iss_nam_m_e = iss_nam_p_e.matcher(xmlResponse);
+ Matcher ser_num_m_s = ser_num_p_s.matcher(xmlResponse);
+ Matcher ser_num_m_e = ser_num_p_e.matcher(xmlResponse);
+
+ Matcher sig_chk_m_s = sig_chk_p_s.matcher(xmlResponse);
+ Matcher sig_chk_m_e = sig_chk_p_e.matcher(xmlResponse);
+ Matcher man_chk_m_s = man_chk_p_s.matcher(xmlResponse);
+ Matcher man_chk_m_e = man_chk_p_e.matcher(xmlResponse);
+ Matcher cer_chk_m_s = cer_chk_p_s.matcher(xmlResponse);
+ Matcher cer_chk_m_e = cer_chk_p_e.matcher(xmlResponse);
+
+ Matcher cert_m_s = cert_p_s.matcher(xmlResponse);
+ Matcher cert_m_e = cert_p_e.matcher(xmlResponse);
+
+ SignatureResponse sig_res = new SignatureResponse();
+
+ // [tknall] start qualified certificate
+ sig_res.setQualifiedCertificate(cert_qualified_m.find());
+ // [tknall] stop qualified certificate
+
+ // public authority
+ Pattern publicAuthority_p = Pattern.compile("<PublicAuthority/>");
+ Matcher publicAuthority_m = publicAuthority_p.matcher(xmlResponse);
+ sig_res.setPublicAuthority(false);
+ sig_res.setPublicAuthorityCode(null);
+ if (publicAuthority_m.find()) {
+ sig_res.setPublicAuthority(true);
+ } else {
+ Matcher publicAuthority_m_s = Pattern.compile("<PublicAuthority>").matcher(xmlResponse);
+ Matcher publicAuthority_m_e = Pattern.compile("</PublicAuthority>").matcher(xmlResponse);
+ if (publicAuthority_m_s.find() && publicAuthority_m_e.find()) {
+ sig_res.setPublicAuthority(true);
+ String codePart = xmlResponse.substring(publicAuthority_m_s.end(), publicAuthority_m_e.start());
+ Matcher code_m_s = code_p_s.matcher(codePart);
+ Matcher code_m_e = code_p_e.matcher(codePart);
+ if (code_m_s.find() && code_m_e.find()) {
+ String code = codePart.substring(code_m_s.end(), code_m_e.start());
+ sig_res.setPublicAuthorityCode(code);
+ }
+ }
+ }
+
+ if (sub_nam_m_s.find() && sub_nam_m_e.find())
+ {
+ String sub_nam = xmlResponse.substring(sub_nam_m_s.end(), sub_nam_m_e.start());
+ sig_res.setX509SubjectName(sub_nam);
+ }
+ if (iss_nam_m_s.find() && iss_nam_m_e.find())
+ {
+ String iss_nam = xmlResponse.substring(iss_nam_m_s.end(), iss_nam_m_e.start());
+ sig_res.setX509IssuerName(iss_nam);
+ }
+ if (ser_num_m_s.find() && ser_num_m_e.find())
+ {
+ String ser_num = xmlResponse.substring(ser_num_m_s.end(), ser_num_m_e.start());
+ sig_res.setX509SerialNumber(ser_num);
+ }
+ if (sig_chk_m_s.find() && sig_chk_m_e.find())
+ {
+ String sig_chk = xmlResponse.substring(sig_chk_m_s.end(), sig_chk_m_e.start());
+ Matcher code_m_s = code_p_s.matcher(sig_chk);
+ Matcher code_m_e = code_p_e.matcher(sig_chk);
+ if (code_m_s.find() && code_m_e.find())
+ {
+ String code = sig_chk.substring(code_m_s.end(), code_m_e.start());
+ sig_res.setSignatureCheckCode(code);
+ }
+ }
+ if (man_chk_m_s.find() && man_chk_m_e.find())
+ {
+ String man_chk = xmlResponse.substring(man_chk_m_s.end(), man_chk_m_e.start());
+ Matcher code_m_s = code_p_s.matcher(man_chk);
+ Matcher code_m_e = code_p_e.matcher(man_chk);
+ if (code_m_s.find() && code_m_e.find())
+ {
+ String code = man_chk.substring(code_m_s.end(), code_m_e.start());
+ sig_res.setSignatureManifestCheckCode(code);
+ }
+ }
+ if (cer_chk_m_s.find() && cer_chk_m_e.find())
+ {
+ String cer_chk = xmlResponse.substring(cer_chk_m_s.end(), cer_chk_m_e.start());
+ Matcher code_m_s = code_p_s.matcher(cer_chk);
+ Matcher code_m_e = code_p_e.matcher(cer_chk);
+ if (code_m_s.find() && code_m_e.find())
+ {
+ String code = cer_chk.substring(code_m_s.end(), code_m_e.start());
+ sig_res.setCertificateCheckCode(code);
+ }
+ }
+ if (cert_m_s.find() && cert_m_e.find())
+ {
+ String cert_string = xmlResponse.substring(cert_m_s.end(), cert_m_e.start());
+
+ X509Cert resp_cert = X509Cert.initByString(cert_string);
+ sig_res.setCertificate(resp_cert);
+ }
+
+ return sig_res;
+ }
+
+ protected String getConnectorValueFromProfile(String profile, String key)
+ {
+ String value = settings_.getValueFromKey("sig_obj." + profile + "." + key);
+ if (value == null)
+ {
+ value = settings_.getValueFromKey(key);
+ }
+ return value;
+ }
+
+ public String getSignURL(String profile)
+ {
+ final String key = TYPE + "." + ConnectorConfigurationKeys.VALUE_MODE_SIGN + ".url";
+ return getConnectorValueFromProfile(profile, key);
+ }
+
+ protected String getSignRequestTemplateFileName(String profile)
+ {
+ String key = TYPE + "." + ConnectorConfigurationKeys.VALUE_MODE_SIGN + ".request";
+ return getConnectorValueFromProfile(profile, key);
+ }
+
+ protected String getSignKeyIdentifier(String profile)
+ {
+ String key = TYPE + "." + ConnectorConfigurationKeys.VALUE_MODE_SIGN + ".KeyIdentifier";
+ return getConnectorValueFromProfile(profile, key);
+ }
+
+ public String getVerifyURL(String profile)
+ {
+ String key = TYPE + "." + ConnectorConfigurationKeys.VALUE_MODE_VERIFY + ".url";
+ return getConnectorValueFromProfile(profile, key);
+ }
+
+ protected String getVerifyRequestTemplateFileName(String profile)
+ {
+ String key = TYPE + "." + ConnectorConfigurationKeys.VALUE_MODE_VERIFY + ".request";
+ return getConnectorValueFromProfile(profile, key);
+ }
+
+ protected String getVerifyTemplateFileName(String profile)
+ {
+ String key = TYPE + "." + ConnectorConfigurationKeys.VALUE_MODE_VERIFY + ".template";
+ return getConnectorValueFromProfile(profile, key);
+ }
+
+ protected String getSigPropFileName(String profile)
+ {
+ String key = TYPE + "." + ConnectorConfigurationKeys.VALUE_MODE_VERIFY + ".template.SP";
+ return getConnectorValueFromProfile(profile, key);
+ }
+
+ protected String getVerifyTrustProfileID(String profile)
+ {
+ String key = TYPE + "." + ConnectorConfigurationKeys.VALUE_MODE_VERIFY + ".TrustProfileID";
+ return getConnectorValueFromProfile(profile, key);
+ }
+
+ /**
+ * This method connects the moa server getting the requestString, the given
+ * serviseMode and the endpointUrl. The requestString is the envelope of the
+ * SOAP Message send and recieve by the AXIS module. The Response SOAP message
+ * of the MOA server is parsed by AXIS and the message envelope is send back
+ * to the calling method.
+ *
+ * @param requestString
+ * the request string (XML) to send.
+ * @param serviceMode
+ * the mode which connect to MOA
+ * @param endpointURL
+ * the URL which the MOA server is running
+ * @return the response string (XML) of the MOA server
+ * @throws WebException
+ */
+ public static String connectMOA(String requestString, String serviceMode,
+ String endpointURL) throws WebException
+ {
+ try
+ {
+ if (logger_.isInfoEnabled())
+ {
+ logger_.info(serviceMode);
+ logger_.info(endpointURL);
+ }
+ // Parser/DOMBuilder instanzieren
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setNamespaceAware(true);
+ DocumentBuilder builder = factory.newDocumentBuilder();
+
+ // XML Datei in einen DOM-Baum umwandeln
+ ByteArrayInputStream bais = new ByteArrayInputStream(requestString.getBytes("UTF-8"));
+ Document xmlRequest = builder.parse(bais);
+
+ // Call oeffnen
+ Call call = null;
+
+ // Neues BodyElement anlegen und mit dem DOM-Baum fuellen
+ SOAPBodyElement body = new SOAPBodyElement(xmlRequest.getDocumentElement());
+ SOAPBodyElement[] params = new SOAPBodyElement[] { body };
+
+ // AXIS-Server instanzieren
+ Service service = ServiceFactory.newInstance().createService(new QName(serviceMode));
+ call = service.createCall();
+ call.setTargetEndpointAddress(endpointURL);
+
+ // Call ausloesen und die Antworten speichern
+ if (logger_.isInfoEnabled())
+ {
+ logger_.info("Calling MOA:" + endpointURL);
+ }
+ Vector responses = (Vector) call.invoke(params);
+
+ // Erstes Body Element auslesen
+ SOAPBodyElement response = (SOAPBodyElement) responses.get(0);
+
+ // Aus der Response den DOM-Baum lesen
+ Document root_response = response.getAsDocument();
+ if (logger_.isInfoEnabled())
+ {
+ logger_.info("Return from MOA:" + serviceMode);
+ }
+
+ // XML-Formatierung konfiguieren
+ OutputFormat format = new OutputFormat((Document) root_response);
+ format.setLineSeparator("\n");
+ format.setIndenting(false);
+ format.setPreserveSpace(true);
+ format.setOmitXMLDeclaration(false);
+ format.setEncoding("UTF-8");
+
+ // Ausgabe der Webservice-Antwort auf die Konsole
+ // XMLSerializer conSerializer = new XMLSerializer(System.out, format);
+ // conSerializer.serialize(root_response);
+
+ // Ausgabe der Webservice-Antwort in Datei
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ XMLSerializer response_serializer = new XMLSerializer(baos, format);
+ response_serializer.serialize(root_response);
+ return baos.toString("UTF-8");
+ }
+ catch (Exception e)
+ {
+ throw new WebException(e);
+ }
+ // serialize signature only
+
+ // if
+ // (root_response.getDocumentElement().getLocalName().equals("CreateXMLSignatureResponse"))
+ // {
+ // Element signature = (Element)
+ // root_response.getElementsByTagNameNS("http://www.w3.org/2000/09/xmldsig#",
+ // "Signature").item(0);
+ // String signatureFile = getProperty(mode + "Request").substring(0,
+ // getProperty(mode +
+ // "Request").lastIndexOf('.')) + ".Signature.xml";
+ // fileSerializer = new XMLSerializer(new FileOutputStream(signatureFile),
+ // format);
+ // fileSerializer.serialize(signature);
+ // }
+
+ }
+} \ No newline at end of file
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/TemplateReplaces.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/TemplateReplaces.java
new file mode 100644
index 0000000..7caf422
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/TemplateReplaces.java
@@ -0,0 +1,172 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors;
+
+/**
+ * This class contains String constants that are frequently used in various
+ * connector templates to fill in the data into the templates.
+ *
+ * @author wprinz
+ */
+public final class TemplateReplaces
+{
+ /**
+ * The placeholder text in the template to be replaced by the keybox
+ * identifier.
+ */
+ public static final String KEYBOX_IDENTIFIER_REPLACE = "KeyboxIdentifierReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the mime type.
+ */
+ public static final String MIME_TYPE_REPLACE = "MimeTypeReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the XML content of
+ * another template.
+ */
+ public static final String XML_CONTENT_REPLACE = "XMLContentReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the cert alg.
+ */
+ public static final String CERT_ALG_REPLACE = "CertAlgReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the digest value of
+ * the signed data.
+ */
+ public static final String DIGEST_VALUE_SIGNED_DATA_REPLACE = "DigestValueSignedDataReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the signature value.
+ */
+ public static final String SIGNATURE_VALUE_REPLACE = "SignatureValueReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the X.509
+ * certificate.
+ */
+ public static final String X509_CERTIFICATE_REPLACE = "X509CertificateReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the signing time.
+ */
+ public static final String SIGNING_TIME_REPLACE = "SigningTimeReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the certificate
+ * digest.
+ */
+ public static final String DIGEST_VALUE_CERTIFICATE_REPLACE = "DigestValueX509CertificateReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the issuer name.
+ */
+ public static final String X509_ISSUER_NAME_REPLACE = "X509IssuerNameReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the serial number.
+ */
+ public static final String X509_SERIAL_NUMBER_REPLACE = "X509SerialNumberReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the signed
+ * properties digest.
+ */
+ public static final String DIGEST_VALUE_SIGNED_PROPERTIES_REPLACE = "DigestValueSignedPropertiesReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the SigDataRef.
+ */
+ public static final String SIG_DATA_REF_REPLACE = "SigDataRefReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the EtsiDataRef.
+ */
+ public static final String ETSI_DATA_REF_REPLACE = "EtsiDataRefReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the SigDataObjURI.
+ */
+ public static final String SIG_DATA_OBJ_URI_REPLACE = "SigDataObjURIReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the EtsiDataObjURI.
+ */
+ public static final String ETSI_DATA_OBJ_URI_REPLACE = "EtsiDataObjURIReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the SigId.
+ */
+ public static final String SIG_ID_REPLACE = "SigIdReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the key identifier.
+ */
+ public static final String KEY_IDENTIFIER_REPLACE = "KeyIdentifierReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the LocRefContent
+ * URL.
+ */
+ public static final String LOC_REF_CONTENT_REPLACE = "LocRefContentReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the trust profile ID.
+ */
+ public static final String TRUST_PROFILE_ID_REPLACE = "TrustProfileIDReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the return hash input data element.
+ */
+ public static final String RETURN_HASH_INPUT_DATA_REPLACE = "ReturnHashInputDataReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the dateTime element.
+ */
+ public static final String DATE_TIME_REPLACE = "DateTimeReplace"; // $NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the Base64 content.
+ */
+ public static final String BASE64_CONTENT_REPLACE = "Base64ContentReplace"; //$NON-NLS-1$
+
+//dferbas
+ /**
+ * The placeholder text in the template to be replaced by the digest method for data.
+ */
+ public static final String DATA_DIGEST_REPLACE = "DataDigestReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the digest method for properties.
+ */
+ public static final String PROPERTIES_DIGEST_REPLACE = "PropertiesDigestReplace"; //$NON-NLS-1$
+
+ /**
+ * The placeholder text in the template to be replaced by the digest method for cert.
+ */
+ public static final String CERT_DIGEST_REPLACE = "CertDigestReplace"; //$NON-NLS-1$
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUHelper.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUHelper.java
new file mode 100644
index 0000000..64306ab
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUHelper.java
@@ -0,0 +1,695 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors.bku;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Properties;
+import java.util.TimeZone;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmMapper;
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteObject;
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteUtil;
+import at.gv.egiz.pdfas.api.commons.Constants;
+import at.gv.egiz.pdfas.api.internal.LocalBKUParams;
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.gv.egiz.pdfas.exceptions.external.ExternalErrorException;
+import at.gv.egiz.pdfas.impl.input.helper.DataSourceHelper;
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
+import at.knowcenter.wag.egov.egiz.sig.SignatureData;
+import at.knowcenter.wag.egov.egiz.sig.SignatureObject;
+import at.knowcenter.wag.egov.egiz.sig.SignatureResponse;
+import at.knowcenter.wag.egov.egiz.sig.X509Cert;
+import at.knowcenter.wag.egov.egiz.sig.connectors.ConnectorEnvironment;
+import at.knowcenter.wag.egov.egiz.sig.sigid.IdFormatter;
+import at.knowcenter.wag.egov.egiz.tools.CodingHelper;
+
+/**
+ * Contains static helper methods used by the BKU Connectors.
+ *
+ * @author wprinz
+ */
+public final class BKUHelper
+{
+
+ private static final Pattern ALLOWED_SL_RESPONSE_PATTERN = Pattern.compile("^.*<[\\w]*:?(CreateXMLSignatureResponse|VerifyXMLSignatureResponse)[^>]*>(.*)</[\\w]*:?(CreateXMLSignatureResponse|VerifyXMLSignatureResponse)>.*$", Pattern.DOTALL);
+
+ /**
+ * The log.
+ */
+ private static Log log = LogFactory.getLog(BKUHelper.class);
+
+ /**
+ * Encodes the given SignatureData to a valid Base64Content.
+ *
+ * <p>
+ * The data is Base64 encoded. If the mime-type suggests that the data is
+ * binary, it is Base64 encoded for a second time.
+ * </p>
+ *
+ * @param data
+ * The data to be converted to a valid Base64 content.
+ * @return Returns the Base64 content.
+ */
+ public static String prepareBase64Content(SignatureData data)
+ {
+ // PERF: base64 encoding needs byte array
+ byte [] d = DataSourceHelper.convertDataSourceToByteArray(data.getDataSource());
+
+ String base64 = CodingHelper.encodeBase64(d);
+ if (data.getMimeType().equals("application/pdf")) //$NON-NLS-1$
+ {
+ log.debug("The data is application/pdf - so the binary data is Base64 encoded."); //$NON-NLS-1$
+ base64 = CodingHelper.encodeUTF8AsBase64(base64);
+ }
+ return base64;
+
+ }
+
+ /**
+ * Prepares the enveloping data.
+ * <p>
+ * This is useful for building the hash.
+ * </p>
+ *
+ * @param data
+ * The data to be prepared.
+ * @return Returns the prepared data.
+ */
+ public static byte[] prepareEnvelopingData(SignatureData data)
+ {
+ // PERF: prepareEnvelopingData needs byte array
+ byte[] enc = DataSourceHelper.convertDataSourceToByteArray(data.getDataSource());
+
+ if (data.getMimeType().equals("application/pdf")) //$NON-NLS-1$
+ {
+ log.debug("The data is application/pdf - so the binary data is Base64 encoded."); //$NON-NLS-1$
+ String base64 = CodingHelper.encodeBase64(enc);
+ try
+ {
+ enc = base64.getBytes("US-ASCII"); //$NON-NLS-1$
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ e.printStackTrace();
+ throw new RuntimeException("Very Strange: US-ASCII encoding not supported???", e); //$NON-NLS-1$
+ }
+ }
+ return enc;
+ }
+
+ /**
+ * Checks the response xml for an error description and if found throws an
+ * appropriate exception.
+ *
+ * @param response_string
+ * The response xml.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public static void checkResponseForError(String response_string) throws ConnectorException
+ {
+ if (StringUtils.isEmpty(response_string)) {
+ throw new ConnectorException(ErrorCode.UNABLE_TO_RECEIVE_SUITABLE_RESPONSE, "No suitable response received.");
+ }
+ log.debug("Checking response for error: " + response_string);
+ Pattern erc_p_s = Pattern.compile("<[\\w]*:?ErrorCode>"); //$NON-NLS-1$
+ Pattern erc_p_e = Pattern.compile("</[\\w]*:?ErrorCode>"); //$NON-NLS-1$
+ Matcher erc_m_s = erc_p_s.matcher(response_string);
+ Matcher erc_m_e = erc_p_e.matcher(response_string);
+
+ if (erc_m_s.find() && erc_m_e.find())
+ {
+ log.error("Found error in response: " + response_string); //$NON-NLS-1$
+
+ Pattern erm_p_s = Pattern.compile("<[\\w]*:?Info>"); //$NON-NLS-1$
+ Pattern erm_p_e = Pattern.compile("</[\\w]*:?Info>"); //$NON-NLS-1$
+ Matcher erm_m_s = erm_p_s.matcher(response_string);
+ Matcher erm_m_e = erm_p_e.matcher(response_string);
+ String error_code = response_string.substring(erc_m_s.end(), erc_m_e.start());
+ String error_mess = null;
+ if (erm_m_s.find() && erm_m_e.find())
+ {
+ error_mess = response_string.substring(erm_m_s.end(), erm_m_e.start());
+ }
+ throw new ExternalErrorException(error_code, error_mess);
+ }
+ log.debug("No error found. Assuring that CreateXMLSignatureResponse or VerifyXMLSignatureResponse elements are available.");
+
+ // assure that a CreateXMLSignatureResponse or a VerifyXMLSignatureResponse is available
+ Matcher slMatcher = ALLOWED_SL_RESPONSE_PATTERN.matcher(response_string);
+ if (!slMatcher.matches()) {
+ throw new ConnectorException(ErrorCode.UNABLE_TO_RECEIVE_SUITABLE_RESPONSE, "No suitable response received: " + response_string);
+ }
+
+ }
+
+ /**
+ * This method parses the BKU-Response string.
+ *
+ * <p>
+ * It separates the SignatureValue, X509IssuerName, SigningTime,
+ * X509SerialNumber, X509Certificate, CertDigest, DigestValue and the
+ * signation id-s. If the X509Certificate is extracted it would be stored in
+ * the certificates directory.
+ * </p>
+ *
+ * @param xmlResponse
+ * The response string.
+ * @return Returns the parsed signature object holding the data.
+ *
+ * @throws ConnectorException
+ * ErrorCode (303, 304)
+ * @see SignatureObject
+ * @see CodingHelper
+ * @see X509Cert
+ */
+ public static SignSignatureObject parseCreateXMLResponse(String xmlResponse,
+ IdFormatter id_formatter, ConnectorEnvironment environment) throws ConnectorException
+ {
+ if (log.isDebugEnabled()) {
+ log.debug("xmlResponse = " + xmlResponse);
+ }
+ Pattern sig_val_p_s = Pattern.compile("<[\\w]*:?SignatureValue>"); //$NON-NLS-1$
+ Pattern sig_val_p_e = Pattern.compile("</[\\w]*:?SignatureValue>"); //$NON-NLS-1$
+ Pattern iss_nam_p_s = Pattern.compile("<[\\w]*:?X509IssuerName>"); //$NON-NLS-1$
+ Pattern iss_nam_p_e = Pattern.compile("</[\\w]*:?X509IssuerName>"); //$NON-NLS-1$
+ Pattern sig_tim_p_s = Pattern.compile("<[\\w]*:?SigningTime>"); //$NON-NLS-1$
+ Pattern sig_tim_p_e = Pattern.compile("</[\\w]*:?SigningTime>"); //$NON-NLS-1$
+ Pattern ser_num_p_s = Pattern.compile("<[\\w]*:?X509SerialNumber>"); //$NON-NLS-1$
+ Pattern ser_num_p_e = Pattern.compile("</[\\w]*:?X509SerialNumber>"); //$NON-NLS-1$
+ Pattern sig_cer_p_s = Pattern.compile("<[\\w]*:?X509Certificate>"); //$NON-NLS-1$
+ Pattern sig_cer_p_e = Pattern.compile("</[\\w]*:?X509Certificate>"); //$NON-NLS-1$
+
+ // Pattern sig_cer_d_p_s = Pattern.compile("<[\\w]*:?CertDigest>");
+ // //$NON-NLS-1$
+ // Pattern sig_cer_d_p_e = Pattern.compile("</[\\w]*:?CertDigest>");
+ // //$NON-NLS-1$
+ // Pattern dig_val_p_s = Pattern.compile("<[\\w]*:?DigestValue>");
+ // //$NON-NLS-1$
+ // Pattern dig_val_p_e = Pattern.compile("</[\\w]*:?DigestValue>");
+ // //$NON-NLS-1$
+
+ Matcher sig_val_m_s = sig_val_p_s.matcher(xmlResponse);
+ Matcher sig_val_m_e = sig_val_p_e.matcher(xmlResponse);
+ Matcher iss_nam_m_s = iss_nam_p_s.matcher(xmlResponse);
+ Matcher iss_nam_m_e = iss_nam_p_e.matcher(xmlResponse);
+ Matcher sig_tim_m_s = sig_tim_p_s.matcher(xmlResponse);
+ Matcher sig_tim_m_e = sig_tim_p_e.matcher(xmlResponse);
+ Matcher ser_num_m_s = ser_num_p_s.matcher(xmlResponse);
+ Matcher ser_num_m_e = ser_num_p_e.matcher(xmlResponse);
+ Matcher sig_cer_m_s = sig_cer_p_s.matcher(xmlResponse);
+ Matcher sig_cer_m_e = sig_cer_p_e.matcher(xmlResponse);
+
+ // Matcher sig_cer_d_m_s = sig_cer_d_p_s.matcher(xmlResponse);
+ // Matcher sig_cer_d_m_e = sig_cer_d_p_e.matcher(xmlResponse);
+ // Matcher dig_val_m_s = dig_val_p_s.matcher(xmlResponse);
+ // Matcher dig_val_m_e = dig_val_p_e.matcher(xmlResponse);
+
+ // SignatureValue
+ String sig_val = null;
+ if (sig_val_m_s.find() && sig_val_m_e.find())
+ {
+ sig_val = removeAllWhitespace(xmlResponse.substring(sig_val_m_s.end(), sig_val_m_e.start()));
+ }
+ log.debug("sig_val = " + sig_val); //$NON-NLS-1$
+
+ // X509IssuerName
+ String iss_nam = null;
+ if (iss_nam_m_s.find() && iss_nam_m_e.find())
+ {
+ iss_nam = xmlResponse.substring(iss_nam_m_s.end(), iss_nam_m_e.start());
+ }
+ log.debug("iss_nam = " + iss_nam); //$NON-NLS-1$
+
+ // X509SerialNumber
+ String ser_num = null;
+ if (ser_num_m_s.find() && ser_num_m_e.find())
+ {
+ ser_num = removeAllWhitespace(xmlResponse.substring(ser_num_m_s.end(), ser_num_m_e.start()));
+ }
+ log.debug("ser_num = " + ser_num); //$NON-NLS-1$
+
+ // SigningTime
+ String sig_tim = null;
+ if (sig_tim_m_s.find() && sig_tim_m_e.find())
+ {
+ sig_tim = xmlResponse.substring(sig_tim_m_s.end(), sig_tim_m_e.start());
+ }
+ log.debug("sig_tim = " + sig_tim); //$NON-NLS-1$
+
+ // CertDigest
+ // if (sig_cer_d_m_s.find() && sig_cer_d_m_e.find())
+ // {
+ // String cert_digest = xmlResponse.substring(sig_cer_d_m_s.end(),
+ // sig_cer_d_m_e.start());
+ // if (dig_val_m_s.find() && dig_val_m_e.find())
+ // {
+ // sig_dig = cert_digest.substring(dig_val_m_s.end(), dig_val_m_e.start());
+ // //sigObj.setX509CertificateDigest(sig_dig);
+ // }
+ // }
+
+ // X509Certificate
+ X509Certificate cert = null;
+ if (sig_cer_m_s.find() && sig_cer_m_e.find())
+ {
+ String sig_cer = removeAllWhitespace(xmlResponse.substring(sig_cer_m_s.end(), sig_cer_m_e.start()));
+
+ try
+ {
+ byte[] der = CodingHelper.decodeBase64(sig_cer);
+ ByteArrayInputStream bais = new ByteArrayInputStream(der);
+ CertificateFactory cf = CertificateFactory.getInstance("X.509"); //$NON-NLS-1$
+ cert = (X509Certificate) cf.generateCertificate(bais);
+ bais.close();
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ log.error(e);
+ throw new ConnectorException(300, e);
+ }
+ catch (CertificateException e)
+ {
+ log.error(e);
+ throw new ConnectorException(300, e);
+ }
+ catch (IOException e)
+ {
+ log.error(e);
+ throw new ConnectorException(300, e);
+ }
+ }
+ log.debug("X509Certificate = " + cert); //$NON-NLS-1$
+
+ if (log.isDebugEnabled())
+ {
+
+ String cert_iss = cert.getIssuerDN().getName();
+ log.debug("certificate's issuer = " + cert_iss); //$NON-NLS-1$
+ log.debug("response's issuer = " + iss_nam); //$NON-NLS-1$
+ log.debug("issuer matches = " + cert_iss.equals(iss_nam)); //$NON-NLS-1$
+ log.debug("ser number matches = " + cert.getSerialNumber().toString().equals(ser_num)); //$NON-NLS-1$
+ }
+
+ // extract Subject Name from X509Certificate
+ // if (sig_cer_m_s.find() && sig_cer_m_e.find())
+ // {
+ // sig_cer = xmlResponse.substring(sig_cer_m_s.end(), sig_cer_m_e.start());
+ // sig_cer = sig_cer.replaceAll("\\s", "");
+ // //sigObj.setX509Certificate(sig_cer);
+ // X509Cert cert = X509Cert.initByString(sig_cer);
+ // if (cert.isX509Cert())
+ // {
+ // //sigObj.setX509Certificate(cert.getCertString());
+ // String serial_num = cert.getSerialNumber();
+ // String subject_name = cert.getSubjectName();
+ // if (!ser_num.equals(serial_num))
+ // {
+ // ConnectorException se = new ConnectorException(303, "Serialnumber of
+ // certificate and tag X509SerialNumber differs!");
+ // throw se;
+ // }
+ // //sigObj.setSignationName(subject_name);
+ // }
+ // }
+
+ // extract Signature Id's
+ String[] ids = new String[5];
+ ids[0] = extractId(xmlResponse, "signature-"); //$NON-NLS-1$
+ ids[1] = extractId(xmlResponse, "signed-data-reference-"); //$NON-NLS-1$
+ ids[2] = extractId(xmlResponse, "signed-data-object-"); //$NON-NLS-1$
+ ids[3] = extractId(xmlResponse, "etsi-data-reference-"); //$NON-NLS-1$
+ ids[4] = extractId(xmlResponse, "etsi-data-object-"); //$NON-NLS-1$
+
+ String algs = AlgorithmSuiteUtil.extractAlgorithmSuiteString(xmlResponse);
+
+ SignSignatureObject so = new SignSignatureObject();
+ so.date = sig_tim;
+ so.issuer = iss_nam;
+ so.signatureValue = sig_val;
+ so.x509Certificate = cert;
+
+ AlgorithmSuiteObject suite = new AlgorithmSuiteObject(algs, false);
+ so.sigAlgorithm = AlgorithmMapper.getUri(suite.getSignatureMethod());
+
+ String defaultCertAlg = environment.getDefaultAlgForCert(cert);
+
+ if (AlgorithmSuiteUtil.isDefaultCertAlg(algs, defaultCertAlg)) {
+ // do not embed default alg
+ algs = null;
+ }
+
+ String final_ids = id_formatter.formatIds(ids, algs);
+ so.id = final_ids;
+
+ return so;
+ }
+
+ /**
+ * Removes all whitespaces ("\\s") from the String.
+ *
+ * @param str
+ * The String.
+ * @return The String with all whitespaces removed.
+ */
+ public static String removeAllWhitespace(String str)
+ {
+ return str.replaceAll("\\s", ""); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ /**
+ * This emthod extracts id-values from a text. The id is given by the name.
+ *
+ * @param text
+ * the id-value that should extract from
+ * @param name
+ * the id-key
+ * @return the value of the given key in the text
+ */
+ private static String extractId(String text, String name)
+ {
+ String id = null;
+ // fatal bug; fixed by tknall (start)
+ int startOfName = text.indexOf(name);
+ if (startOfName == -1) {
+ log.debug("No id for name \"" + name + "\" extracted. Probably detached signature. Returning empty id: \"\""); //$NON-NLS-1$
+ return "";
+ }
+ // stop
+
+ int start_idx = startOfName + name.length();
+ int end_idx = text.indexOf("\"", start_idx); //$NON-NLS-1$
+
+ final int quot_end_idx = end_idx;
+ final int squot_end_idx = text.indexOf("'", start_idx); //$NON-NLS-1$
+ end_idx = Math.min(quot_end_idx, squot_end_idx);
+ id = text.substring(start_idx, end_idx);
+ if (log.isDebugEnabled())
+ {
+ log.debug("extract id:" + name + id); //$NON-NLS-1$
+ }
+ return id;
+ }
+
+ /**
+ * This method parses the verify response string and return a
+ * SignatureResponse object. The SignatureResponse object is filled out by the
+ * response values from the BKU-response.
+ *
+ * @param xmlResponse
+ * the response values from the BKU-verify request
+ * @return SignatureResponse object
+ * @see SignatureResponse
+ */
+ public static SignatureResponse parseVerifyXMLResponse(String xmlResponse)
+ {
+ log.debug("parseVerifyXMLResponse:"); //$NON-NLS-1$
+
+ Pattern sub_nam_p_s = Pattern.compile("<dsig:X509SubjectName>"); //$NON-NLS-1$
+ Pattern sub_nam_p_e = Pattern.compile("</dsig:X509SubjectName>"); //$NON-NLS-1$
+ Pattern iss_nam_p_s = Pattern.compile("<dsig:X509IssuerName>"); //$NON-NLS-1$
+ Pattern iss_nam_p_e = Pattern.compile("</dsig:X509IssuerName>"); //$NON-NLS-1$
+ Pattern ser_num_p_s = Pattern.compile("<dsig:X509SerialNumber>"); //$NON-NLS-1$
+ Pattern ser_num_p_e = Pattern.compile("</dsig:X509SerialNumber>"); //$NON-NLS-1$
+
+ Pattern sig_chk_p_s = Pattern.compile("<[\\w]*:?SignatureCheck>"); //$NON-NLS-1$
+ Pattern sig_chk_p_e = Pattern.compile("</[\\w]*:?SignatureCheck>"); //$NON-NLS-1$
+ Pattern man_chk_p_s = Pattern.compile("<[\\w]*:?SignatureManifestCheck>"); //$NON-NLS-1$
+ Pattern man_chk_p_e = Pattern.compile("</[\\w]*:?SignatureManifestCheck>"); //$NON-NLS-1$
+ Pattern cer_chk_p_s = Pattern.compile("<[\\w]*:?CertificateCheck>"); //$NON-NLS-1$
+ Pattern cer_chk_p_e = Pattern.compile("</[\\w]*:?CertificateCheck>"); //$NON-NLS-1$
+
+ // [tknall] start qualified certificate
+ Pattern cert_qualified_p = Pattern.compile("<[\\w]*:?QualifiedCertificate/>"); //$NON-NLS-1$
+ Matcher cert_qualified_m = cert_qualified_p.matcher(xmlResponse);
+ // [tknall] stop qualified certificate
+
+ Pattern code_p_s = Pattern.compile("<[\\w]*:?Code>"); //$NON-NLS-1$
+ Pattern code_p_e = Pattern.compile("</[\\w]*:?Code>"); //$NON-NLS-1$
+ Pattern info_p_s = Pattern.compile("<[\\w]*:?Info>"); //$NON-NLS-1$
+ Pattern info_p_e = Pattern.compile("</[\\w]*:?Info>"); //$NON-NLS-1$
+
+ Pattern cert_p_s = Pattern.compile("<dsig:X509Certificate>"); //$NON-NLS-1$
+ Pattern cert_p_e = Pattern.compile("</dsig:X509Certificate>"); //$NON-NLS-1$
+
+ Matcher sub_nam_m_s = sub_nam_p_s.matcher(xmlResponse);
+ Matcher sub_nam_m_e = sub_nam_p_e.matcher(xmlResponse);
+ Matcher iss_nam_m_s = iss_nam_p_s.matcher(xmlResponse);
+ Matcher iss_nam_m_e = iss_nam_p_e.matcher(xmlResponse);
+ Matcher ser_num_m_s = ser_num_p_s.matcher(xmlResponse);
+ Matcher ser_num_m_e = ser_num_p_e.matcher(xmlResponse);
+
+ Matcher sig_chk_m_s = sig_chk_p_s.matcher(xmlResponse);
+ Matcher sig_chk_m_e = sig_chk_p_e.matcher(xmlResponse);
+ Matcher man_chk_m_s = man_chk_p_s.matcher(xmlResponse);
+ Matcher man_chk_m_e = man_chk_p_e.matcher(xmlResponse);
+ Matcher cer_chk_m_s = cer_chk_p_s.matcher(xmlResponse);
+ Matcher cer_chk_m_e = cer_chk_p_e.matcher(xmlResponse);
+
+ Matcher cert_m_s = cert_p_s.matcher(xmlResponse);
+ Matcher cert_m_e = cert_p_e.matcher(xmlResponse);
+
+ Pattern hash_data_p_s = Pattern.compile("<HashInputData PartOf=\"SignedInfo\">"); //$NON-NLS-1$
+ Pattern hash_data_p_e = Pattern.compile("</HashInputData>"); //$NON-NLS-1$
+ Matcher hash_data_m_s = hash_data_p_s.matcher(xmlResponse);
+ Matcher hash_data_m_e = hash_data_p_e.matcher(xmlResponse);
+
+
+ SignatureResponse sig_res = new SignatureResponse();
+
+ // public authority (tknall)
+ Pattern publicAuthority_p = Pattern.compile("<PublicAuthority/>");
+ Matcher publicAuthority_m = publicAuthority_p.matcher(xmlResponse);
+ sig_res.setPublicAuthority(false);
+ sig_res.setPublicAuthorityCode(null);
+ if (publicAuthority_m.find()) {
+ sig_res.setPublicAuthority(true);
+ } else {
+ Matcher publicAuthority_m_s = Pattern.compile("<PublicAuthority>").matcher(xmlResponse);
+ Matcher publicAuthority_m_e = Pattern.compile("</PublicAuthority>").matcher(xmlResponse);
+ if (publicAuthority_m_s.find() && publicAuthority_m_e.find()) {
+ sig_res.setPublicAuthority(true);
+ String codePart = xmlResponse.substring(publicAuthority_m_s.end(), publicAuthority_m_e.start());
+ Matcher code_m_s = code_p_s.matcher(codePart);
+ Matcher code_m_e = code_p_e.matcher(codePart);
+ if (code_m_s.find() && code_m_e.find()) {
+ String code = codePart.substring(code_m_s.end(), code_m_e.start());
+ sig_res.setPublicAuthorityCode(code);
+ }
+ }
+ }
+
+ // [tknall] start qualified certificate
+ sig_res.setQualifiedCertificate(cert_qualified_m.find());
+ // [tknall] stop qualified certificate
+
+ if (hash_data_m_s.find() && hash_data_m_e.find())
+ {
+ String hashInputData = xmlResponse.substring(hash_data_m_s.end(), hash_data_m_e.start());
+
+ Pattern b64_p_s = Pattern.compile("<Base64Content>"); //$NON-NLS-1$
+ Pattern b64_p_e = Pattern.compile("</Base64Content>"); //$NON-NLS-1$
+ Matcher b64_m_s = b64_p_s.matcher(hashInputData);
+ Matcher b64_m_e = b64_p_e.matcher(hashInputData);
+
+ boolean hashInputDataFound = b64_m_s.find() && b64_m_e.find();
+
+ String b64 = hashInputDataFound ? hashInputData.substring(b64_m_s.end(), b64_m_e.start()) : "";
+
+ sig_res.setHashInputData(b64);
+ }
+
+ if (sub_nam_m_s.find() && sub_nam_m_e.find())
+ {
+ String sub_nam = xmlResponse.substring(sub_nam_m_s.end(), sub_nam_m_e.start());
+ sig_res.setX509SubjectName(sub_nam);
+ }
+ if (iss_nam_m_s.find() && iss_nam_m_e.find())
+ {
+ String iss_nam = xmlResponse.substring(iss_nam_m_s.end(), iss_nam_m_e.start());
+ sig_res.setX509IssuerName(iss_nam);
+ }
+ if (ser_num_m_s.find() && ser_num_m_e.find())
+ {
+ String ser_num = xmlResponse.substring(ser_num_m_s.end(), ser_num_m_e.start());
+ sig_res.setX509SerialNumber(ser_num);
+ }
+ if (sig_chk_m_s.find() && sig_chk_m_e.find())
+ {
+ String sig_chk = xmlResponse.substring(sig_chk_m_s.end(), sig_chk_m_e.start());
+ Matcher code_m_s = code_p_s.matcher(sig_chk);
+ Matcher code_m_e = code_p_e.matcher(sig_chk);
+ Matcher info_m_s = info_p_s.matcher(sig_chk);
+ Matcher info_m_e = info_p_e.matcher(sig_chk);
+ if (code_m_s.find() && code_m_e.find())
+ {
+ String code = sig_chk.substring(code_m_s.end(), code_m_e.start());
+ sig_res.setSignatureCheckCode(code);
+ }
+ if (info_m_s.find() && info_m_e.find())
+ {
+ String info = sig_chk.substring(info_m_s.end(), info_m_e.start());
+ sig_res.setSignatureCheckInfo(info);
+ }
+ }
+ if (man_chk_m_s.find() && man_chk_m_e.find())
+ {
+ String man_chk = xmlResponse.substring(man_chk_m_s.end(), man_chk_m_e.start());
+ Matcher code_m_s = code_p_s.matcher(man_chk);
+ Matcher code_m_e = code_p_e.matcher(man_chk);
+ Matcher info_m_s = info_p_s.matcher(man_chk);
+ Matcher info_m_e = info_p_e.matcher(man_chk);
+ if (code_m_s.find() && code_m_e.find())
+ {
+ String code = man_chk.substring(code_m_s.end(), code_m_e.start());
+ sig_res.setSignatureManifestCheckCode(code);
+ }
+ if (info_m_s.find() && info_m_e.find())
+ {
+ String info = man_chk.substring(info_m_s.end(), info_m_e.start());
+ sig_res.setSignatureManifestCheckInfo(info);
+ }
+ }
+ if (cer_chk_m_s.find() && cer_chk_m_e.find())
+ {
+ String cer_chk = xmlResponse.substring(cer_chk_m_s.end(), cer_chk_m_e.start());
+ Matcher code_m_s = code_p_s.matcher(cer_chk);
+ Matcher code_m_e = code_p_e.matcher(cer_chk);
+ Matcher info_m_s = info_p_s.matcher(cer_chk);
+ Matcher info_m_e = info_p_e.matcher(cer_chk);
+ if (code_m_s.find() && code_m_e.find())
+ {
+ String code = cer_chk.substring(code_m_s.end(), code_m_e.start());
+ sig_res.setCertificateCheckCode(code);
+ }
+ if (info_m_s.find() && info_m_e.find())
+ {
+ String info = cer_chk.substring(info_m_s.end(), info_m_e.start());
+ sig_res.setCertificateCheckInfo(info);
+ }
+ }
+ if (cert_m_s.find() && cert_m_e.find())
+ {
+ String cert_string = xmlResponse.substring(cert_m_s.end(), cert_m_e.start());
+
+ X509Cert resp_cert = X509Cert.initByString(cert_string);
+ sig_res.setCertificate(resp_cert);
+ }
+
+ log.debug("parseVerifyXMLResponse finished."); //$NON-NLS-1$
+ return sig_res;
+ }
+
+ public static String formDateTimeElement(Date verificationTime)
+ {
+ return formDateTimeElement(verificationTime, null);
+ }
+
+ public static String formDateTimeElement(Date verificationTime, String namespace)
+ {
+ String nsPrefix = StringUtils.isBlank(namespace) ? "" : (namespace + ":");
+
+ String dateTimeElement = "";
+ if (verificationTime != null)
+ {
+ log.debug("VerificationTime = " + verificationTime);
+
+ DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
+ df.setTimeZone(TimeZone.getTimeZone("UTC"));
+ String dateTime = df.format(verificationTime) + "Z";
+ log.debug("DateTime (VerificationTime in UTC) = " + dateTime);
+
+ dateTimeElement = "<" + nsPrefix + "DateTime>" + dateTime + "</" + nsPrefix + "DateTime>";
+ };
+ return dateTimeElement;
+ }
+
+ public static String getBKUIdentifier(Properties parsedResponseProperties) {
+
+ // http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung.response.browser
+ String bkuServerHeader = parsedResponseProperties.getProperty(BKUPostConnection.BKU_SERVER_HEADER_KEY);
+
+ // http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung.response.dataurl
+ String bkuUserAgentHeader = parsedResponseProperties.getProperty(BKUPostConnection.BKU_USER_AGENT_HEADER_KEY);
+
+ String bkuSignatureLayout = parsedResponseProperties.getProperty(BKUPostConnection.BKU_SIGNATURE_LAYOUT_HEADER_KEY);
+
+ return getBKUIdentifier(bkuServerHeader, bkuUserAgentHeader, bkuSignatureLayout);
+ }
+
+ public static String getBKUIdentifier(String bkuServerHeader, String bkuUserAgentHeader, String bkuSignatureLayout) {
+
+ log.debug("BKU response header \"user-agent\": " + bkuUserAgentHeader);
+ log.debug("BKU response header \"server\": " + bkuServerHeader);
+ log.trace("BKU response header \"" + Constants.BKU_HEADER_SIGNATURE_LAYOUT + "\": " + bkuSignatureLayout);
+
+ String result = null;
+
+ if (bkuServerHeader != null) {
+ result = bkuServerHeader;
+ } else if (bkuUserAgentHeader != null) {
+ result = bkuUserAgentHeader;
+ } else {
+ log.warn("Unable to find any BKU identifier (neither header value \"user-agent\" nor \"server\".)");
+ }
+
+ if (bkuSignatureLayout != null && result != null) {
+ log.debug("BKU response header \"" + Constants.BKU_HEADER_SIGNATURE_LAYOUT + "\" found.");
+ String signatureLayoutData = " " + Constants.BKU_HEADER_SIGNATURE_LAYOUT + "/" + bkuSignatureLayout;
+ if (!result.endsWith(signatureLayoutData)) {
+ log.debug("Appending signature layout value \"" + bkuSignatureLayout + "\" to bku identifier.");
+ result += signatureLayoutData;
+ } else {
+ log.debug("Signature layout already encoded in server/user-agent header.");
+ }
+ }
+
+ if (result != null) {
+ log.debug("Returning BKU identifier \"" + result + "\"");
+ } else {
+ log.debug("Returning null BKU identifier.");
+ }
+
+ return result;
+ }
+
+ public static String getBKUIdentifier(LocalBKUParams bkuParams) {
+ return getBKUIdentifier(bkuParams.getServer(), bkuParams.getUserAgent(), bkuParams.getSignatureLayout());
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUPostConnection.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUPostConnection.java
new file mode 100644
index 0000000..04b817f
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUPostConnection.java
@@ -0,0 +1,179 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors.bku;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+import org.apache.commons.httpclient.Header;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpException;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.methods.multipart.FilePart;
+import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
+import org.apache.commons.httpclient.methods.multipart.Part;
+import org.apache.commons.httpclient.methods.multipart.PartSource;
+import org.apache.commons.httpclient.methods.multipart.StringPart;
+import org.apache.commons.httpclient.params.HttpMethodParams;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import at.gv.egiz.pdfas.api.commons.Constants;
+import at.knowcenter.wag.egov.egiz.sig.SignatureData;
+
+/**
+ * Helper class with methods that use the Apache Https Client to send HTTP
+ * requests.
+ *
+ * @author wprinz
+ */
+public final class BKUPostConnection
+{
+ /**
+ * The response Properties key that identifies the response string.
+ */
+ public static final String RESPONSE_STRING_KEY = "response_string"; //$NON-NLS-1$
+
+ /**
+ * The response Properties key that identifies the BKU Server header.
+ */
+ public static final String BKU_SERVER_HEADER_KEY = "BKU-Server-Header"; //$NON-NLS-1$
+
+ /**
+ * The response property that declares the signature layout being applied.
+ */
+ public static final String BKU_SIGNATURE_LAYOUT_HEADER_KEY = "BKU-Signature-Layout"; //$NON-NLS-1$
+
+ /**
+ * The response Properties key that identifies the BKU User-Agent header.
+ */
+ public static final String BKU_USER_AGENT_HEADER_KEY = "BKU-User-Agent-Header"; //$NON-NLS-1$
+
+ /**
+ * The log.
+ */
+ private static Log log = LogFactory.getLog(BKUPostConnection.class);
+
+ /**
+ * Sends a multipart/form-data HTTP Post request to the given URL.
+ *
+ * @param url The url the request is directed to.
+ * @param request The request XML, which will be the UTF-8 text/xml first part of the message.
+ * @param data The binary second part of the message.
+ * @return Returns the response properties which, among others, contain the response String.
+ * @throws HttpException
+ * @throws IOException
+ */
+ public static Properties doPostRequestMultipart(String url, String request,
+ final SignatureData data) throws HttpException, IOException
+ {
+ log.debug("doPostRequestMultipart:"); //$NON-NLS-1$
+
+ StringPart xmlpart = new StringPart("XMLRequest", request, "UTF-8"); //$NON-NLS-1$//$NON-NLS-2$
+
+ // TODO this is a BUG in BKU that doesn't allow the Content-Type header
+ xmlpart.setContentType(null);
+ xmlpart.setTransferEncoding(null);
+ // BKU 2.7.4 can't handle the Content-Type Header for the XML
+ // xmlpart.setContentType("text/xml");
+ // xmlpart.setTransferEncoding(null);
+
+ final String filename = data.getMimeType().equals("application/pdf") ? "myfile.pdf" : "myfile.txt"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ PartSource ps = new PartSource() {
+ public InputStream createInputStream() throws IOException
+ {
+ return data.getDataSource().createInputStream();
+ }
+
+ public String getFileName()
+ {
+ return filename;
+ }
+
+ public long getLength()
+ {
+ return data.getDataSource().getLength();
+ }
+ };
+ //ByteArrayPartSource baps = new ByteArrayPartSource(filename, data.getData());
+ FilePart filepart = new FilePart("fileupload", ps); //$NON-NLS-1$
+ filepart.setContentType(data.getMimeType());
+
+ // not really needed since external referenced data has to be taken "as-is" (binary stream) for
+ // digest calculation, so neither content type nor charset is relevant
+ filepart.setCharSet(data.getCharacterEncoding());
+
+ Part[] parts = { xmlpart, filepart };
+
+ HttpMethodParams method_params = new HttpMethodParams();
+ method_params.setContentCharset("UTF-8"); //$NON-NLS-1$
+
+ PostMethod post_method = new PostMethod(url);
+ post_method.setParams(method_params);
+
+ MultipartRequestEntity mprqe = new MultipartRequestEntity(parts, post_method.getParams());
+ post_method.setRequestEntity(mprqe);
+
+ HttpClient http_client = new HttpClient();
+
+ int method_response = http_client.executeMethod(post_method);
+ log.debug("method_response = " + method_response); //$NON-NLS-1$
+
+ Properties response_properties = new Properties();
+
+ if (log.isDebugEnabled())
+ {
+ Header[] response_headers = post_method.getResponseHeaders();
+ for (int i = 0; i < response_headers.length; i++)
+ {
+ log.debug(" response_header[" + i + "]: name = " + response_headers[i].getName() + ", value = " + response_headers[i].getValue()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+ }
+ Header server_header = post_method.getResponseHeader("Server"); //$NON-NLS-1$
+ if (server_header != null) {
+ response_properties.setProperty(BKU_SERVER_HEADER_KEY, server_header.getValue());
+ } else {
+ log.warn("BKU response header \"Server\" is empty.");
+ }
+
+ Header signatureLayoutHeader = post_method.getResponseHeader(Constants.BKU_HEADER_SIGNATURE_LAYOUT); //$NON-NLS-1$
+ if (signatureLayoutHeader != null) {
+ response_properties.setProperty(BKU_SIGNATURE_LAYOUT_HEADER_KEY, signatureLayoutHeader.getValue());
+ }
+
+ String responseCharSet = post_method.getResponseCharSet();
+ if (!"UTF8".equalsIgnoreCase(responseCharSet) && !"UTF-8".equalsIgnoreCase(responseCharSet)) {
+ log.warn("BKU response charset is not UTF-8!"); //$NON-NLS-1$
+ }
+ String response_string = post_method.getResponseBodyAsString();
+
+ response_properties.setProperty(RESPONSE_STRING_KEY, response_string);
+
+ log.debug("doPostRequestMultipart finished."); //$NON-NLS-1$
+
+ return response_properties;
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/DetachedBKUConnector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/DetachedBKUConnector.java
new file mode 100644
index 0000000..a8de41e
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/DetachedBKUConnector.java
@@ -0,0 +1,823 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors.bku;
+
+import java.security.cert.X509Certificate;
+import java.util.Properties;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteObject;
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteUtil;
+import at.gv.egiz.pdfas.api.xmldsig.XMLDsigData;
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.gv.egiz.pdfas.framework.ConnectorParameters;
+import at.knowcenter.wag.egov.egiz.PdfAS;
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
+import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
+import at.knowcenter.wag.egov.egiz.sig.SignatureData;
+import at.knowcenter.wag.egov.egiz.sig.SignatureObject;
+import at.knowcenter.wag.egov.egiz.sig.SignatureResponse;
+import at.knowcenter.wag.egov.egiz.sig.connectors.Connector;
+import at.knowcenter.wag.egov.egiz.sig.connectors.ConnectorEnvironment;
+import at.knowcenter.wag.egov.egiz.sig.connectors.LocalConnector;
+import at.knowcenter.wag.egov.egiz.sig.connectors.TemplateReplaces;
+import at.knowcenter.wag.egov.egiz.sig.connectors.moa.DetachedLocRefMOAConnector;
+import at.knowcenter.wag.egov.egiz.sig.connectors.moa.MOASoapWithAttachmentConnector;
+import at.knowcenter.wag.egov.egiz.sig.connectors.mocca.LocRefDetachedMOCCAConnector;
+import at.knowcenter.wag.egov.egiz.sig.sigkz.SigKZIDHelper;
+import at.knowcenter.wag.egov.egiz.sig.signaturelayout.SignatureLayoutHandler;
+import at.knowcenter.wag.egov.egiz.sig.signaturelayout.SignatureLayoutHandlerFactory;
+import at.knowcenter.wag.egov.egiz.tools.CodingHelper;
+
+/**
+ * Connects to the BKU using the detached multipart/formdata requests.
+ *
+ * <p>
+ * This feature is available since BKU version 2.7.4.
+ * </p>
+ *
+ * @author wprinz
+ */
+public class DetachedBKUConnector implements Connector, LocalConnector
+{
+//23.11.2010 changed by exthex - added reconstructXMLDsig method and moved xmldsig creation to chooseAndCreateXMLDsig method
+
+ /**
+ * The log.
+ */
+ private static Log log = LogFactory.getLog(DetachedBKUConnector.class);
+
+ /**
+ * The connector parameters.
+ */
+ protected ConnectorParameters params = null;
+
+ /**
+ * The environemnt configuration of this connector containing templates and
+ * other configurable elements.
+ */
+ protected Environment environment = null;
+
+ /**
+ * Constructor that builds the configuration environment for this connector
+ * according to the given profile.
+ *
+ * <p>
+ * If confuguration parameters are not defined on that profile, the default
+ * parameters defined in the configuration are used.
+ * </p>
+ *
+ * @param connectorParameters
+ * The connectot parameters.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public DetachedBKUConnector(ConnectorParameters connectorParameters, String loc_ref_content) throws ConnectorException
+ {
+ this.params = connectorParameters;
+ this.environment = new Environment(this.params.getProfileId(), loc_ref_content);
+ }
+
+ /**
+ * Prepares the sign request xml to be sent using the sign request template.
+ *
+ * @param data
+ * The SignatureData.
+ * @return Returns the sign request xml to be sent.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public String prepareSignRequest(SignatureData data) throws ConnectorException
+ {
+ log.debug("prepareSignRequestDetached:"); //$NON-NLS-1$
+
+ String sign_request_template = this.environment.getSignRequestTemplate();
+
+ String sign_keybox_identifier = this.environment.getSignKeyboxIdentifier();
+ String mime_type = data.getMimeType();
+ String loc_ref_content = this.environment.getLocRefContent();
+
+ if (log.isDebugEnabled())
+ {
+ log.debug("sign keybox identifier = " + sign_keybox_identifier); //$NON-NLS-1$
+ log.debug("mime type = " + mime_type); //$NON-NLS-1$
+ log.debug("loc_ref_content = " + loc_ref_content); //$NON-NLS-1$
+ }
+
+ String sign_request_xml = sign_request_template.replaceFirst(TemplateReplaces.KEYBOX_IDENTIFIER_REPLACE, sign_keybox_identifier);
+ sign_request_xml = sign_request_xml.replaceFirst(TemplateReplaces.MIME_TYPE_REPLACE, mime_type);
+ sign_request_xml = sign_request_xml.replaceFirst(TemplateReplaces.LOC_REF_CONTENT_REPLACE, loc_ref_content);
+
+ log.debug("sign_request_xml = " + sign_request_xml);
+ log.debug("prepareSignRequestDetached finished."); //$NON-NLS-1$
+ return sign_request_xml;
+ }
+
+ /**
+ * Analyzes the sign response xml and extracts the signature data.
+ *
+ * @param response_properties
+ * The response properties containing the response String and
+ * transport related information.
+ * @return Returns the extracted data encapsulated in a SignatureObject.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public SignSignatureObject analyzeSignResponse(Properties response_properties) throws ConnectorException
+ {
+ log.debug("analyzeSignResponse:"); //$NON-NLS-1$
+
+ String response_string = response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY);
+
+ String bkuIdentifier = BKUHelper.getBKUIdentifier(response_properties);
+ log.debug("BKU identifier: " + (bkuIdentifier != null ? ("\"" + bkuIdentifier + "\"") : "n/a"));
+
+ SignatureLayoutHandler sigLayout;
+ try {
+ sigLayout = SignatureLayoutHandlerFactory.getSignatureLayoutHandlerInstance(bkuIdentifier);
+ } catch (SettingsException e) {
+ throw new ConnectorException(e.getErrorCode(), e.getMessage());
+ }
+
+ BKUHelper.checkResponseForError(response_string);
+
+ SignSignatureObject so = sigLayout.parseCreateXMLSignatureResponse(response_string, this.environment);
+
+ so.response_properties = response_properties;
+
+ log.debug("analyzeSignResponse finished."); //$NON-NLS-1$
+ return so;
+ }
+
+ public static String[] parseSigIds(String sig_ids)
+ {
+ if (sig_ids == null || sig_ids.length() == 0)
+ {
+ return null;
+ }
+
+ // int index = sig_ids.indexOf(PdfAS.IDS);
+ // if (index < 0)
+ // {
+ // return null;
+ // }
+ // sig_ids = sig_ids.substring(index + PdfAS.IDS.length());
+ //
+ // if (sig_ids == null || sig_ids.length() == 0)
+ // {
+ // return null;
+ // }
+
+ String[] ids_str = sig_ids.split("@");
+
+ String etsi_string = null;
+ if (ids_str.length == 3)
+ {
+ etsi_string = ids_str[0];
+ String[] rest_ids = new String[] { ids_str[1], ids_str[2] };
+ ids_str = rest_ids;
+ }
+
+ String base = ids_str[0];
+ String[] ids = ids_str[1].split("-");
+ String[] real_ids = new String[6]; // the last one contains the etsi string
+ real_ids[0] = base + "-" + ids[0];
+ real_ids[1] = "0-" + base + "-" + ids[1];
+ real_ids[2] = "0-" + base + "-" + ids[2];
+ real_ids[3] = "0-" + base + "-" + ids[3];
+ real_ids[4] = "0-" + base + "-" + ids[4];
+ real_ids[5] = etsi_string;
+
+ if (log.isDebugEnabled())
+ {
+ for (int id_idx = 0; id_idx < real_ids.length; id_idx++)
+ {
+ log.debug("real_ids[" + id_idx + "] = " + real_ids[id_idx]);
+ }
+ }
+
+ return real_ids;
+ }
+
+ /**
+ * Sends the request and data to the given URL.
+ *
+ * <p>
+ * This method mainly handles communication exceptions. The actual send work
+ * is done by doPostRequestMultipart.
+ * </p>
+ *
+ * @see BKUPostConnection#doPostRequestMultipart(String, String,
+ * SignatureData)
+ *
+ * @param url
+ * The URL to send the request to.
+ * @param request_string
+ * The request XML.
+ * @param data
+ * The data.
+ * @return Returns the response properties containing among others the
+ * response XML.
+ * @throws ConnectorException
+ * f.e.
+ */
+ protected Properties sendRequest(String url, String request_string,
+ SignatureData data) throws ConnectorException
+ {
+ try
+ {
+ Properties response_properties = BKUPostConnection.doPostRequestMultipart(url, request_string, data);
+ return response_properties;
+ }
+ catch (Exception e)
+ {
+ ConnectorException se = new ConnectorException(320, e);
+ throw se;
+ }
+ }
+
+ /**
+ * Performs a sign.
+ *
+ * @param data
+ * The data to be signed.
+ * @return Returns the signature object containing the signature data.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public SignSignatureObject doSign(SignatureData data) throws ConnectorException
+ {
+ log.debug("doSign:"); //$NON-NLS-1$
+
+ String sign_request_xml = prepareSignRequest(data);
+ log.debug("sign_request_xml = " + sign_request_xml); //$NON-NLS-1$
+
+ String url = this.environment.getSignURL();
+ Properties response_properties = sendRequest(url, sign_request_xml, data);
+
+ SignSignatureObject sso = analyzeSignResponse(response_properties);
+
+ sso.response_properties = response_properties;
+
+ log.debug("doSign finished."); //$NON-NLS-1$
+ return sso;
+ }
+
+ /**
+ * Performs a verification.
+ *
+ * @param data
+ * The data to be verified.
+ * @param so
+ * The signature object with the signature information.
+ * @return Returns the SignatureResponse with the result of the verification.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public SignatureResponse doVerify(SignatureData data, SignSignatureObject so, XMLDsigData dsig) throws ConnectorException
+ {
+ log.debug("doVerify:"); //$NON-NLS-1$
+
+ String verify_request_xml = prepareVerifyRequest(data, so, dsig);
+ log.debug("verify_request_xml = " + verify_request_xml); //$NON-NLS-1$
+
+ // TODO debug - remove
+ // try
+ // {
+ // FileOutputStream fos = new
+ // FileOutputStream("C:\\wprinz\\Filer\\egiz2\\verify_request.utf8.xml");
+ // //$NON-NLS-1$
+ // fos.write(verify_request_xml.getBytes("UTF-8")); //$NON-NLS-1$
+ // fos.close();
+ // }
+ // catch (Exception e)
+ // {
+ // log.error(e);
+ // }
+
+ String url = this.environment.getVerifyURL();
+ Properties response_properties = sendRequest(url, verify_request_xml, data);
+
+ SignatureResponse signature_response = analyzeVerifyResponse(response_properties);
+
+ log.debug("doVerify finished."); //$NON-NLS-1$
+ return signature_response;
+ }
+
+ /**
+ * Prepares the verify request xml to be sent using the verify request
+ * template.
+ *
+ * @param data
+ * The SignatureData.
+ * @param so
+ * The signature information object.
+ * @return Returns the verify request xml to be sent.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public String prepareVerifyRequest(SignatureData data, SignSignatureObject so, XMLDsigData dsigData) throws ConnectorException
+ {
+ String verify_request_template = this.environment.getVerifyRequestTemplate();
+
+ String xml_content = null;
+
+ if (dsigData != null && dsigData.getXmlDsig() != null)
+ {
+ xml_content = dsigData.getXmlDsig();
+ }
+ else
+ {
+ xml_content = chooseAndCreateXMLDsig(data, so);
+ }
+
+
+
+ String verify_request_xml = verify_request_template.replaceFirst(TemplateReplaces.XML_CONTENT_REPLACE, xml_content);
+ verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.LOC_REF_CONTENT_REPLACE, this.environment.getLocRefContent());
+ verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.DATE_TIME_REPLACE, BKUHelper.formDateTimeElement(this.params.getVerificationTime(), "sl"));
+
+ return verify_request_xml;
+ }
+
+ private String chooseAndCreateXMLDsig(SignatureData data, SignSignatureObject so) throws ConnectorException {
+ // MOA
+ if (SigKZIDHelper.isMOASigned(so))
+ {
+ log.debug("The signature is MOA signed -> getting XML content from DetachedLocRefMOA connector.");
+ DetachedLocRefMOAConnector moa_conn = new DetachedLocRefMOAConnector(this.environment.getProfile(), "loc ref not needed here");
+ return moa_conn.prepareXMLContent(data, so);
+
+ // MOCCA
+ } else if (SigKZIDHelper.isMOCCASigned(so)) {
+ log.debug("MOCCA signature detected.");
+ String algorithmId = SigKZIDHelper.parseAlgorithmId(so.id);
+ log.debug("Algorithm = " + algorithmId);
+ LocRefDetachedMOCCAConnector mocca_connector = new LocRefDetachedMOCCAConnector(this.params, "not needed here", algorithmId);
+ return mocca_connector.prepareXMLContent(data, so);
+
+ // ATRUST
+ } else if (SigKZIDHelper.isATrustSigned(so)) {
+ log.debug("ATrust signature detected");
+ MOASoapWithAttachmentConnector moaConn = new MOASoapWithAttachmentConnector(this.params);
+ moaConn.reInitVerifyTemplate(MOASoapWithAttachmentConnector.ATRUST_VERIFY_TEMPLATE_KEY);
+ return moaConn.prepareXMLContent(data, so);
+ }
+ // TD
+ else if (SigKZIDHelper.isBKUSigned(so)) {
+ log.debug("TD signature signature detected.");
+ return prepareXMLContent(data, so);
+ }
+ // unknown
+ else {
+ throw new ConnectorException(ErrorCode.UNSUPPORTED_SIGNATURE, "Unsupported signature (" + so.id + ", " +so.kz + "). Please get a new version of PDF-AS. Your version is: " + PdfAS.PDFAS_VERSION);
+ }
+ }
+
+ /**
+ * Prepares the XML content the holds the actual signature data.
+ *
+ * <p>
+ * This strongly rebuilds the XML content as retuned from a sign request.
+ * </p>
+ *
+ * @param data
+ * The data.
+ * @param so
+ * The signature object containing the signature information.
+ * @return Returns the XML content.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public String prepareXMLContent(SignatureData data, SignSignatureObject so) throws ConnectorException
+ {
+ log.debug("prepareXMLContent:"); //$NON-NLS-1$
+ try
+ {
+
+ String ids_string = so.getSigID();
+ String[] ids = SignatureObject.parseSigIds(ids_string);
+
+ X509Certificate cert = so.getX509Certificate();
+
+ // dferbas
+ AlgorithmSuiteObject algSuite = new AlgorithmSuiteObject();
+ String verify_xml = AlgorithmSuiteUtil.evaluateReplaceAlgs(algSuite, this.environment, so);
+
+ // data digest replace
+ {
+// byte[] data_value = data.getData();
+// byte[] data_value_hash = CodingHelper.buildDigest(data_value);
+ byte[] data_value_hash = CodingHelper.buildDigest(data.getDataSource(), algSuite.getDataDigestMethod());
+ String object_data_hash = CodingHelper.encodeBase64(data_value_hash);
+
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_SIGNED_DATA_REPLACE, object_data_hash);
+ }
+
+ // SIG id replaces
+ verify_xml = verify_xml.replaceAll(TemplateReplaces.SIG_DATA_REF_REPLACE, ids[1]);
+ verify_xml = verify_xml.replaceAll(TemplateReplaces.ETSI_DATA_REF_REPLACE, ids[3]);
+ verify_xml = verify_xml.replaceAll(TemplateReplaces.SIG_DATA_OBJ_URI_REPLACE, ids[2]);
+
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.SIGNATURE_VALUE_REPLACE, so.getSignatureValue());
+
+ // X.509 Certificate replace
+ byte[] der = cert.getEncoded();
+ byte[] cert_hash = CodingHelper.buildDigest(der, algSuite.getCertDigestMethod());
+ String certDigest = CodingHelper.encodeBase64(cert_hash);
+ String x509_cert_string = CodingHelper.encodeBase64(der);
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_CERTIFICATE_REPLACE, x509_cert_string);
+
+ // Qualified Properties replaces
+ verify_xml = verify_xml.replaceAll(TemplateReplaces.ETSI_DATA_OBJ_URI_REPLACE, ids[4]);
+ verify_xml = verify_xml.replaceAll(TemplateReplaces.SIG_ID_REPLACE, ids[0]);
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.SIGNING_TIME_REPLACE, so.getDate());
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_CERTIFICATE_REPLACE, certDigest);
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_ISSUER_NAME_REPLACE, so.getIssuer());
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_SERIAL_NUMBER_REPLACE, so.getSerialNumber());
+ // SigDataRefReplace already done above
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.MIME_TYPE_REPLACE, data.getMimeType());
+
+ // Signed Properties hash
+ {
+ final String ETSI_SIGNED_PROPERTIES_START_TAG = "<etsi:SignedProperties"; //$NON-NLS-1$
+ final String ETSI_SIGNED_PROPERTIES_END_TAG = "</etsi:SignedProperties>"; //$NON-NLS-1$
+
+ final int hash_start = verify_xml.indexOf(ETSI_SIGNED_PROPERTIES_START_TAG);
+ assert hash_start >= 0;
+ final int hash_end = verify_xml.indexOf(ETSI_SIGNED_PROPERTIES_END_TAG, hash_start) + ETSI_SIGNED_PROPERTIES_END_TAG.length();
+ assert hash_end - ETSI_SIGNED_PROPERTIES_END_TAG.length() >= 0;
+ assert hash_end > hash_start;
+
+ final String string_to_be_hashed = verify_xml.substring(hash_start, hash_end);
+ log.debug("etsi:SignedProperties string to be hashed: " + string_to_be_hashed); //$NON-NLS-1$
+
+ final byte[] bytes_to_be_hashed = string_to_be_hashed.getBytes("UTF-8"); //$NON-NLS-1$
+ byte[] sig_prop_code = CodingHelper.buildDigest(bytes_to_be_hashed, algSuite.getPropertiesDigestMethod());
+ String sig_prop_hash = CodingHelper.encodeBase64(sig_prop_code);
+
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_SIGNED_PROPERTIES_REPLACE, sig_prop_hash);
+ }
+
+ log.debug("prepareXMLContent finished."); //$NON-NLS-1$
+ return verify_xml;
+ }
+ catch (Exception e)
+ {
+ log.debug(e);
+ throw new ConnectorException(310, e);
+ }
+ }
+
+ /**
+ * Analyzes the verify response string.
+ *
+ * @param response_properties
+ * The response properties containing the response XML.
+ * @return Returns the SignatureResponse containing the verification result.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public SignatureResponse analyzeVerifyResponse(Properties response_properties) throws ConnectorException
+ {
+ log.debug("analyzeVerifyResponse:"); //$NON-NLS-1$
+
+ String response_string = response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY);
+
+ BKUHelper.checkResponseForError(response_string);
+
+ SignatureResponse signature_response = BKUHelper.parseVerifyXMLResponse(response_string);
+
+ log.debug("analyzeVerifyResponse finished."); //$NON-NLS-1$
+ return signature_response;
+ }
+
+ /**
+ * Holds environment configuration information like templates.
+ *
+ * @author wprinz
+ */
+ public static class Environment extends ConnectorEnvironment
+ {
+ /**
+ * The configuration key of the sign keybox identifier.
+ */
+ protected static final String SIGN_KEYBOX_IDENTIFIER_KEY = "bku.sign.KeyboxIdentifier"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the sign request template.
+ */
+ protected static final String SIGN_REQUEST_TEMPLATE_KEY = "bku.sign.request.detached"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the sign URL.
+ */
+ protected static final String SIGN_URL_KEY = "bku.sign.url"; //$NON-NLS-1$
+
+ /**
+ * BKU template file prefix
+ */
+ protected static final String TEMPLATE_FILE_PREFIX = "/templates/bku.";
+
+ /**
+ * signing file template sufix
+ */
+ protected static final String SIGN_TEMPLATE_FILE_SUFIX = ".sign.xml";
+
+ /**
+ * verifing template file sufix
+ */
+ protected static final String VERIFY_REQUEST_TEMPLATE_FILE_SUFIX = ".verify.request.xml";
+
+ /**
+ * verifing file template key sufix
+ */
+ protected static final String VERIFY_TEMPLATE_SUFIX = ".verify.template.xml";
+
+ /**
+ * The configuration key of the verify request template.
+ */
+ protected static final String VERIFY_REQUEST_TEMPLATE_KEY = "bku.verify.request.detached"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the verify template.
+ */
+ protected static final String VERIFY_TEMPLATE_KEY = "bku.verify.template.detached"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the verify URL.
+ */
+ protected static final String VERIFY_URL_KEY = "bku.verify.url"; //$NON-NLS-1$
+
+ /**
+ * The configuration key for the ECDSA cert alg property.
+ */
+ protected static final String ECDSA_CERT_ALG_KEY = "cert.alg.ecdsa"; //$NON-NLS-1$
+
+ /**
+ * The configuration key for the RSA cert alg property.
+ */
+ protected static final String RSA_CERT_ALG_KEY = "cert.alg.rsa"; //$NON-NLS-1$
+
+ protected String profile = null;
+
+ protected String loc_ref_content = null;
+
+ protected String sign_keybox_identifier = null;
+
+ protected String sign_request_template = null;
+
+ protected String sign_url = null;
+
+ protected String verify_request_template = null;
+
+ protected String verify_template = null;
+
+ protected String verify_url = null;
+
+ protected String cert_alg_ecdsa = null;
+
+ protected String cert_alg_rsa = null;
+
+ /**
+ * Initializes the environment with a given profile.
+ *
+ * @param profile
+ * The configuration profile.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public Environment(String profile, String loc_ref_content) throws ConnectorException
+ {
+ this.profile = profile;
+
+ this.loc_ref_content = loc_ref_content;
+
+ SettingsReader settings = null;
+ try
+ {
+ settings = SettingsReader.getInstance();
+ }
+ catch (SettingsException e)
+ {
+ throw new ConnectorException(300, e);
+ }
+
+ this.sign_keybox_identifier = getConnectorValueFromProfile(settings, profile, SIGN_KEYBOX_IDENTIFIER_KEY);
+
+ String sign_request_filename = TEMPLATE_FILE_PREFIX + settings.getValueFromKey("default.bku.algorithm.id") + SIGN_TEMPLATE_FILE_SUFIX;
+
+ // try to load template from file
+ //this.sign_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename));
+ this.sign_request_template = settings.readInternalResourceAsString(sign_request_filename);
+
+ // when first load failed (the template file does'nt exist), load it from default template file
+ if(this.sign_request_template == null)
+ {
+ sign_request_filename = getConnectorValueFromProfile(settings, profile, SIGN_REQUEST_TEMPLATE_KEY);
+ //this.sign_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename));
+ this.sign_request_template = settings.readInternalResourceAsString(sign_request_filename);
+ }
+
+ if (this.sign_request_template == null)
+ {
+ throw new ConnectorException(300, "Can not read the create xml request template"); //$NON-NLS-1$
+ }
+
+ this.sign_url = getConnectorValueFromProfile(settings, profile, SIGN_URL_KEY);
+
+ // verify
+
+ String verify_request_filename = TEMPLATE_FILE_PREFIX + settings.getValueFromKey("default.bku.algorithm.id") + VERIFY_REQUEST_TEMPLATE_FILE_SUFIX;
+
+ // try to load template file for verifing
+ //this.verify_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_request_filename));
+ this.verify_request_template = settings.readInternalResourceAsString(verify_request_filename);
+
+ if(this.verify_request_template == null)
+ {
+ verify_request_filename = getConnectorValueFromProfile(settings, profile, VERIFY_REQUEST_TEMPLATE_KEY);
+ //this.verify_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_request_filename));
+ this.verify_request_template = settings.readInternalResourceAsString(verify_request_filename);
+ }
+
+ if (this.verify_request_template == null)
+ {
+ throw new ConnectorException(ErrorCode.SETTING_NOT_FOUND, "Can not read the verify xml request template"); //$NON-NLS-1$
+ }
+
+ // load template key file
+ String verify_filename = TEMPLATE_FILE_PREFIX + settings.getValueFromKey("default.bku.algorithm.id") + VERIFY_TEMPLATE_SUFIX;
+ //this.verify_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_filename));
+ this.verify_template = settings.readInternalResourceAsString(verify_filename);
+
+ if(this.verify_template == null)
+ {
+ verify_filename = getConnectorValueFromProfile(settings, profile, VERIFY_TEMPLATE_KEY);
+ //this.verify_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_filename));
+ this.verify_template = settings.readInternalResourceAsString(verify_filename);
+ }
+
+ if (this.verify_template == null)
+ {
+ throw new ConnectorException(ErrorCode.SETTING_NOT_FOUND, "Can not read the verify template"); //$NON-NLS-1$
+ }
+
+ this.verify_url = getConnectorValueFromProfile(settings, profile, VERIFY_URL_KEY);
+
+ this.cert_alg_ecdsa = settings.getValueFromKey(ECDSA_CERT_ALG_KEY);
+
+ this.cert_alg_rsa = settings.getValueFromKey(RSA_CERT_ALG_KEY);
+
+ }
+
+ public String getProfile()
+ {
+ return this.profile;
+ }
+
+ /**
+ * Returns the LocRef content.
+ *
+ * @return Returns the LocRef content.
+ */
+ public String getLocRefContent()
+ {
+ return this.loc_ref_content;
+ }
+
+ /**
+ * Returns the sign keybox identifier.
+ *
+ * @return Returns the sign keybox identifier.
+ */
+ public String getSignKeyboxIdentifier()
+ {
+ return this.sign_keybox_identifier;
+ }
+
+ /**
+ * Returns the sign request template.
+ *
+ * @return Returns the sign request template.
+ */
+ public String getSignRequestTemplate()
+ {
+ return this.sign_request_template;
+ }
+
+ /**
+ * Returns the sign URL.
+ *
+ * @return Returns the sign URL.
+ */
+ public String getSignURL()
+ {
+ return this.sign_url;
+ }
+
+ /**
+ * Returns the verify request template.
+ *
+ * @return Returns the verify request template.
+ */
+ public String getVerifyRequestTemplate()
+ {
+ return this.verify_request_template;
+ }
+
+ /**
+ * Returns the verify template.
+ *
+ * @return Returns the verify template.
+ */
+ public String getVerifyTemplate()
+ {
+ return this.verify_template;
+ }
+
+ /**
+ * Returns the verify URL.
+ *
+ * @return Returns the verify URL.
+ */
+ public String getVerifyURL()
+ {
+ return this.verify_url;
+ }
+
+ /**
+ * Returns the ecdsa cert alg property.
+ *
+ * @return Returns the ecdsa cert alg property.
+ */
+ public String getCertAlgEcdsa()
+ {
+ return this.cert_alg_ecdsa;
+ }
+
+ /**
+ * Returns the rsa cert alg property.
+ *
+ * @return Returns the rsa cert alg property.
+ */
+ public String getCertAlgRsa()
+ {
+ return this.cert_alg_rsa;
+ }
+
+ /**
+ * Reads the configuration entry given by the key, first from the given
+ * profile, if not found from the defaults.
+ *
+ * @param settings
+ * The settings.
+ * @param profile
+ * The profile.
+ * @param key
+ * The configuration key.
+ * @return Returns the configuration entry.
+ */
+ public static String getConnectorValueFromProfile(SettingsReader settings,
+ String profile, String key)
+ {
+ String value = settings.getValueFromKey("sig_obj." + profile + "." + key); //$NON-NLS-1$//$NON-NLS-2$
+ if (value == null)
+ {
+ value = settings.getValueFromKey(key);
+ }
+ return value;
+ }
+ }
+
+
+ public XMLDsigData reconstructXMLDsig(SignatureData data, SignSignatureObject so)
+ throws ConnectorException {
+ String xmldsig = chooseAndCreateXMLDsig(data, so);
+ return new XMLDsigData(xmldsig, true);
+ }
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/EnvelopedBase64BKUConnector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/EnvelopedBase64BKUConnector.java
new file mode 100644
index 0000000..170cc45
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/EnvelopedBase64BKUConnector.java
@@ -0,0 +1,666 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors.bku;
+
+import java.io.UnsupportedEncodingException;
+import java.security.cert.X509Certificate;
+import java.util.Properties;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteObject;
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteUtil;
+import at.gv.egiz.pdfas.api.xmldsig.XMLDsigData;
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.gv.egiz.pdfas.framework.ConnectorParameters;
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
+import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
+import at.knowcenter.wag.egov.egiz.sig.SignatureData;
+import at.knowcenter.wag.egov.egiz.sig.SignatureObject;
+import at.knowcenter.wag.egov.egiz.sig.SignatureResponse;
+import at.knowcenter.wag.egov.egiz.sig.connectors.Connector;
+import at.knowcenter.wag.egov.egiz.sig.connectors.ConnectorEnvironment;
+import at.knowcenter.wag.egov.egiz.sig.connectors.LocalConnector;
+import at.knowcenter.wag.egov.egiz.sig.connectors.TemplateReplaces;
+import at.knowcenter.wag.egov.egiz.sig.connectors.moa.EnvelopingBase64MOAConnector;
+import at.knowcenter.wag.egov.egiz.sig.sigid.HotfixIdFormatter;
+import at.knowcenter.wag.egov.egiz.sig.sigkz.SigKZIDHelper;
+import at.knowcenter.wag.egov.egiz.tools.CodingHelper;
+
+/**
+ * @author wprinz
+ *
+ */
+public class EnvelopedBase64BKUConnector implements Connector, LocalConnector
+{
+ //23.11.2010 changed by exthex - added reconstructXMLDsig method and moved xmldsig creation to chooseAndCreateXMLDsig method
+
+ /**
+ * The log.
+ */
+ private static Log log = LogFactory.getLog(EnvelopedBase64BKUConnector.class);
+
+ /**
+ * The environemnt configuration of this connector containing templates and
+ * other configurable elements.
+ */
+ protected Environment environment = null;
+
+ /**
+ * Constructor that builds the configuration environment for this connector
+ * according to the given profile.
+ *
+ * <p>
+ * If confuguration parameters are not defined on that profile, the default
+ * parameters defined in the configuration are used.
+ * </p>
+ *
+ * <p>
+ * This is the new "hotfix" base64 connector.
+ * </p>
+ *
+ * @param profile
+ * The profile from which the Environment should be assembled.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public EnvelopedBase64BKUConnector(String profile) throws ConnectorException
+ {
+ this.environment = new Environment(profile);
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.connectors.Connector#doSign(at.knowcenter.wag.egov.egiz.sig.SignatureData)
+ */
+ public SignSignatureObject doSign(SignatureData data) throws ConnectorException
+ {
+ log.debug("doSign:"); //$NON-NLS-1$
+
+ String sign_request_xml = prepareSignRequest(data);
+// DebugHelper.debugStringToFile(sign_request_xml, "BKU_EnvB64_sign_request.xml"); //$NON-NLS-1$
+
+ String url = this.environment.getSignURL();
+ Properties response_properties = sendRequest(url, sign_request_xml);
+
+// DebugHelper.debugStringToFile(response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY), "BKU_EnvB64_sign_response.xml"); //$NON-NLS-1$
+ SignSignatureObject sso = analyzeSignResponse(response_properties);
+
+ sso.response_properties = response_properties;
+
+ log.debug("doSign finished."); //$NON-NLS-1$
+ return sso;
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.connectors.Connector#doVerify(at.knowcenter.wag.egov.egiz.sig.SignatureData,
+ * at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject)
+ */
+ public SignatureResponse doVerify(SignatureData data, SignSignatureObject so, XMLDsigData dsig) throws ConnectorException
+ {
+ log.debug("doVerify:"); //$NON-NLS-1$
+
+ String verify_request_xml = prepareVerifyRequest(data, so, dsig);
+// DebugHelper.debugStringToFile(verify_request_xml, "BKU_EnvB64_verify_request.xml"); //$NON-NLS-1$
+
+ String url = this.environment.getVerifyURL();
+ Properties response_properties = sendRequest(url, verify_request_xml);
+
+// DebugHelper.debugStringToFile(response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY), "BKU_EnvB64_verify_response.xml"); //$NON-NLS-1$
+ SignatureResponse signature_response = analyzeVerifyResponse(response_properties);
+
+ log.debug("doVerify finished."); //$NON-NLS-1$
+ return signature_response;
+ }
+
+// /**
+// * This emthod extracts id-values from a text. The id is given by the name.
+// *
+// * @param text
+// * the id-value that should extract from
+// * @param name
+// * the id-key
+// * @return the value of the given key in the text
+// */
+// private String extractId(String text, String name)
+// {
+// String id = null;
+// int start_idx = text.indexOf(name) + name.length();
+// int end_idx = text.indexOf("\"", start_idx);
+//
+// // TODO hotfix!
+// final int quot_end_idx = end_idx;
+// final int squot_end_idx = text.indexOf("'", start_idx);
+// end_idx = Math.min(quot_end_idx, squot_end_idx);
+// // TODO hotfix end!
+//
+// id = text.substring(start_idx, end_idx);
+// if (log.isDebugEnabled())
+// {
+// log.debug("extract id:" + name + id);
+// }
+// return id;
+// }
+
+ /**
+ * Prepares the XML content the holds the actual signature data.
+ *
+ * <p>
+ * This strongly rebuilds the XML content as retuned from a sign request.
+ * </p>
+ *
+ * @param data
+ * The data.
+ * @param so
+ * The signature object containing the signature information.
+ * @return Returns the XML content.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public String prepareXMLContent(SignatureData data, SignSignatureObject so) throws ConnectorException
+ {
+ log.debug("prepareXMLContent:"); //$NON-NLS-1$
+ try
+ {
+ String ids_string = so.getSigID();
+ String[] ids = SignatureObject.parseSigIds(ids_string);
+
+ X509Certificate cert = so.getX509Certificate();
+
+ // dferbas
+ AlgorithmSuiteObject algSuite = new AlgorithmSuiteObject();
+ String verify_xml = AlgorithmSuiteUtil.evaluateReplaceAlgs(algSuite, this.environment, so);
+
+ // data digest replace
+ byte[] data_value = BKUHelper.prepareEnvelopingData(data);
+ {
+ byte[] data_value_hash = CodingHelper.buildDigest(data_value, algSuite.getDataDigestMethod());
+ String object_data_hash = CodingHelper.encodeBase64(data_value_hash);
+
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_SIGNED_DATA_REPLACE, object_data_hash);
+ }
+
+ // SIG id replaces
+ verify_xml = verify_xml.replaceAll(TemplateReplaces.SIG_DATA_REF_REPLACE, ids[1]);
+ verify_xml = verify_xml.replaceAll(TemplateReplaces.ETSI_DATA_REF_REPLACE, ids[3]);
+ verify_xml = verify_xml.replaceAll(TemplateReplaces.SIG_DATA_OBJ_URI_REPLACE, ids[2]);
+
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.SIGNATURE_VALUE_REPLACE, so.getSignatureValue());
+
+ // X.509 Certificate replace
+ byte[] der = cert.getEncoded();
+ byte[] cert_hash = CodingHelper.buildDigest(der, algSuite.getCertDigestMethod());
+ String certDigest = CodingHelper.encodeBase64(cert_hash);
+ String x509_cert_string = CodingHelper.encodeBase64(der);
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_CERTIFICATE_REPLACE, x509_cert_string);
+
+ // Base64 content replace
+ String base64 = CodingHelper.encodeBase64(data_value);
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.BASE64_CONTENT_REPLACE, base64);
+
+ // Qualified Properties replaces
+ verify_xml = verify_xml.replaceAll(TemplateReplaces.ETSI_DATA_OBJ_URI_REPLACE, ids[4]);
+ verify_xml = verify_xml.replaceAll(TemplateReplaces.SIG_ID_REPLACE, ids[0]);
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.SIGNING_TIME_REPLACE, so.getDate());
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_CERTIFICATE_REPLACE, certDigest);
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_ISSUER_NAME_REPLACE, so.getIssuer());
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_SERIAL_NUMBER_REPLACE, so.getSerialNumber());
+ // SigDataRefReplace already done above
+
+ // Signed Properties hash
+ {
+ String sig_prop_hash = computeSignedPropertiesReplace(verify_xml, algSuite);
+
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_SIGNED_PROPERTIES_REPLACE, sig_prop_hash);
+ }
+
+ log.debug("prepareXMLContent finished."); //$NON-NLS-1$
+ return verify_xml;
+ }
+ catch (Exception e)
+ {
+ log.debug(e);
+ throw new ConnectorException(310, e);
+ }
+ }
+
+ protected String computeSignedPropertiesReplace(String verify_xml, AlgorithmSuiteObject algSuite)
+ {
+ try
+ {
+ final String ETSI_SIGNED_PROPERTIES_START_TAG = "<etsi:SignedProperties"; //$NON-NLS-1$
+ final String ETSI_SIGNED_PROPERTIES_END_TAG = "</etsi:SignedProperties>"; //$NON-NLS-1$
+
+ final int hash_start = verify_xml.indexOf(ETSI_SIGNED_PROPERTIES_START_TAG);
+ assert hash_start >= 0;
+ final int hash_end = verify_xml.indexOf(ETSI_SIGNED_PROPERTIES_END_TAG, hash_start) + ETSI_SIGNED_PROPERTIES_END_TAG.length();
+ assert hash_end - ETSI_SIGNED_PROPERTIES_END_TAG.length() >= 0;
+ assert hash_end > hash_start;
+
+ final String string_to_be_hashed = verify_xml.substring(hash_start, hash_end);
+ log.debug("etsi:SignedProperties string to be hashed: " + string_to_be_hashed); //$NON-NLS-1$
+
+ final byte[] bytes_to_be_hashed = string_to_be_hashed.getBytes("UTF-8"); //$NON-NLS-1$
+ byte[] sig_prop_code = CodingHelper.buildDigest(bytes_to_be_hashed, algSuite.getPropertiesDigestMethod());
+ String sig_prop_hash = CodingHelper.encodeBase64(sig_prop_code);
+
+ return sig_prop_hash;
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ throw new RuntimeException("Very Strange: UTF-8 character encoding not supported.", e);
+ }
+ }
+
+ /**
+ * Prepares the sign request xml to be sent using the sign request template.
+ *
+ * @param data
+ * The SignatureData.
+ * @return Returns the sign request xml to be sent.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public String prepareSignRequest(SignatureData data) throws ConnectorException
+ {
+ log.debug("prepareSignRequest:"); //$NON-NLS-1$
+
+ String sign_request_template = this.environment.getSignRequestTemplate();
+
+ String sign_keybox_identifier = this.environment.getSignKeyboxIdentifier();
+ String base64 = BKUHelper.prepareBase64Content(data);
+
+ String sign_request_xml = sign_request_template.replaceFirst(TemplateReplaces.KEYBOX_IDENTIFIER_REPLACE, sign_keybox_identifier);
+ sign_request_xml = sign_request_xml.replaceFirst(TemplateReplaces.BASE64_CONTENT_REPLACE, base64);
+
+ log.debug("prepareSignRequest finished."); //$NON-NLS-1$
+ return sign_request_xml;
+ }
+
+ /**
+ * Prepares the verify request xml to be sent using the verify request
+ * template.
+ *
+ * @param data
+ * The SignatureData.
+ * @param so
+ * The signature information object.
+ * @return Returns the verify request xml to be sent.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public String prepareVerifyRequest(SignatureData data, SignSignatureObject so, XMLDsigData dsigData) throws ConnectorException
+ {
+ String verify_request_template = this.environment.getVerifyRequestTemplate();
+
+ String xml_content = null;
+ if (dsigData != null && dsigData.getXmlDsig() != null)
+ {
+ xml_content = dsigData.getXmlDsig();
+ }
+ else
+ {
+ xml_content = chooseAndCreateXMLDsig(data, so);
+ }
+
+ String verify_request_xml = verify_request_template.replaceFirst(TemplateReplaces.XML_CONTENT_REPLACE, xml_content);
+
+// log.debug("\r\n\r\n" + verify_request_xml + "\r\n\r\n");
+
+ return verify_request_xml;
+ }
+
+ private String chooseAndCreateXMLDsig(SignatureData data, SignSignatureObject so) throws ConnectorException {
+ if (SigKZIDHelper.isMOASigned(so))
+ {
+ log.debug("The signature is MOA signed -> getting XML content from Base64MOA connector.");
+ ConnectorParameters cp = new ConnectorParameters();
+ cp.setProfileId(this.environment.getProfile());
+ EnvelopingBase64MOAConnector moa_conn = new EnvelopingBase64MOAConnector(cp);
+ return moa_conn.prepareXMLContent(data, so);
+ }
+ else
+ {
+ return prepareXMLContent(data, so);
+ }
+ }
+
+/**
+ * Sends the request to the given URL.
+ *
+ * @param url
+ * The URL.
+ * @param request_string
+ * The request string.
+ * @return Returns the response string.
+ * @throws ConnectorException
+ * F.e.
+ */
+ protected Properties sendRequest(String url, String request_string) throws ConnectorException
+ {
+ try
+ {
+ Properties response_properties = at.knowcenter.wag.egov.egiz.sig.connectors.BKUPostConnection.doPostRequest(url, request_string);
+ return response_properties;
+ }
+ catch (Exception e)
+ {
+ throw new ConnectorException(320, e);
+ }
+ }
+
+ /**
+ * Analyzes the sign response xml and extracts the signature data.
+ *
+ * @param response_properties
+ * The response properties containing the response String and
+ * transport related information.
+ * @return Returns the extracted data encapsulated in a SignatureObject.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public SignSignatureObject analyzeSignResponse(Properties response_properties) throws ConnectorException
+ {
+ log.debug("analyzeSignResponse:"); //$NON-NLS-1$
+
+ String response_string = response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY);
+
+ BKUHelper.checkResponseForError(response_string);
+
+ String bkuIdentifier = BKUHelper.getBKUIdentifier(response_properties);
+ log.debug("BKU identifier: \"" + bkuIdentifier + "\"");
+
+ SignSignatureObject so = BKUHelper.parseCreateXMLResponse(response_string, new HotfixIdFormatter(), this.environment);
+
+ log.debug("analyzeSignResponse finished."); //$NON-NLS-1$
+ return so;
+ }
+
+ /**
+ * Analyzes the verify response string.
+ *
+ * @param response_properties
+ * The response properties containing the response XML.
+ * @return Returns the SignatureResponse containing the verification result.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public SignatureResponse analyzeVerifyResponse(Properties response_properties) throws ConnectorException
+ {
+ log.debug("analyzeVerifyResponse:"); //$NON-NLS-1$
+
+ String response_string = response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY);
+
+ BKUHelper.checkResponseForError(response_string);
+
+ SignatureResponse signature_response = BKUHelper.parseVerifyXMLResponse(response_string);
+
+ log.debug("analyzeVerifyResponse finished."); //$NON-NLS-1$
+ return signature_response;
+ }
+
+ /**
+ * Holds environment configuration information like templates.
+ *
+ * @author wprinz
+ */
+ public static class Environment extends ConnectorEnvironment
+ {
+ /**
+ * The configuration key of the sign keybox identifier.
+ */
+ protected static final String SIGN_KEYBOX_IDENTIFIER_KEY = "bku.sign.KeyboxIdentifier"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the sign request template.
+ */
+ protected static final String SIGN_REQUEST_TEMPLATE_KEY = "bku.sign.request.base64"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the sign URL.
+ */
+ protected static final String SIGN_URL_KEY = "bku.sign.url"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the verify request template.
+ */
+ protected static final String VERIFY_REQUEST_TEMPLATE_KEY = "bku.verify.request.base64"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the verify template.
+ */
+ protected static final String VERIFY_TEMPLATE_KEY = "bku.verify.template.base64"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the verify URL.
+ */
+ protected static final String VERIFY_URL_KEY = "bku.verify.url"; //$NON-NLS-1$
+
+ /**
+ * The configuration key for the ECDSA cert alg property.
+ */
+ protected static final String ECDSA_CERT_ALG_KEY = "cert.alg.ecdsa"; //$NON-NLS-1$
+
+ /**
+ * The configuration key for the RSA cert alg property.
+ */
+ protected static final String RSA_CERT_ALG_KEY = "cert.alg.rsa"; //$NON-NLS-1$
+
+ protected String profile = null;
+
+ protected String sign_keybox_identifier = null;
+
+ protected String sign_request_template = null;
+
+ protected String sign_url = null;
+
+ protected String verify_request_template = null;
+
+ protected String verify_template = null;
+
+ protected String verify_url = null;
+
+ protected String cert_alg_ecdsa = null;
+
+ protected String cert_alg_rsa = null;
+
+ /**
+ * Initializes the environment with a given profile.
+ *
+ * @param profile
+ * The configuration profile.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public Environment(String profile) throws ConnectorException
+ {
+ this.profile = profile;
+
+ SettingsReader settings = null;
+ try
+ {
+ settings = SettingsReader.getInstance();
+ }
+ catch (SettingsException e)
+ {
+ throw new ConnectorException(300, e);
+ }
+
+ this.sign_keybox_identifier = getConnectorValueFromProfile(settings, profile, SIGN_KEYBOX_IDENTIFIER_KEY);
+
+ String sign_request_filename = getConnectorValueFromProfile(settings, profile, SIGN_REQUEST_TEMPLATE_KEY);
+ //this.sign_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename));
+ this.sign_request_template = settings.readInternalResourceAsString(sign_request_filename);
+ if (this.sign_request_template == null)
+ {
+ throw new ConnectorException(300, "Can not read the create xml request template"); //$NON-NLS-1$
+ }
+
+ this.sign_url = getConnectorValueFromProfile(settings, profile, SIGN_URL_KEY);
+
+ String verify_request_filename = getConnectorValueFromProfile(settings, profile, VERIFY_REQUEST_TEMPLATE_KEY);
+ //this.verify_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_request_filename));
+ this.verify_request_template = settings.readInternalResourceAsString(verify_request_filename);
+ log.debug("Verify request template filename = " + verify_request_filename);
+
+ if (this.verify_request_template == null)
+ {
+ throw new ConnectorException(ErrorCode.SETTING_NOT_FOUND, "Can not read the verify xml request template"); //$NON-NLS-1$
+ }
+
+ log.debug("Verify request template = " + this.verify_request_template);
+
+ String verify_filename = getConnectorValueFromProfile(settings, profile, VERIFY_TEMPLATE_KEY);
+ //this.verify_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_filename));
+ this.verify_template = settings.readInternalResourceAsString(verify_filename);
+ if (this.verify_template == null)
+ {
+ throw new ConnectorException(ErrorCode.SETTING_NOT_FOUND, "Can not read the verify template"); //$NON-NLS-1$
+ }
+
+ this.verify_url = getConnectorValueFromProfile(settings, profile, VERIFY_URL_KEY);
+
+ this.cert_alg_ecdsa = settings.getValueFromKey(ECDSA_CERT_ALG_KEY);
+
+ this.cert_alg_rsa = settings.getValueFromKey(RSA_CERT_ALG_KEY);
+
+ }
+
+ public String getProfile()
+ {
+ return this.profile;
+ }
+
+ /**
+ * Returns the sign keybox identifier.
+ *
+ * @return Returns the sign keybox identifier.
+ */
+ public String getSignKeyboxIdentifier()
+ {
+ return this.sign_keybox_identifier;
+ }
+
+ /**
+ * Returns the sign request template.
+ *
+ * @return Returns the sign request template.
+ */
+ public String getSignRequestTemplate()
+ {
+ return this.sign_request_template;
+ }
+
+ /**
+ * Returns the sign URL.
+ *
+ * @return Returns the sign URL.
+ */
+ public String getSignURL()
+ {
+ return this.sign_url;
+ }
+
+ /**
+ * Returns the verify request template.
+ *
+ * @return Returns the verify request template.
+ */
+ public String getVerifyRequestTemplate()
+ {
+ return this.verify_request_template;
+ }
+
+ /**
+ * Returns the verify template.
+ *
+ * @return Returns the verify template.
+ */
+ public String getVerifyTemplate()
+ {
+ return this.verify_template;
+ }
+
+ /**
+ * Returns the verify URL.
+ *
+ * @return Returns the verify URL.
+ */
+ public String getVerifyURL()
+ {
+ return this.verify_url;
+ }
+
+ /**
+ * Returns the ecdsa cert alg property.
+ *
+ * @return Returns the ecdsa cert alg property.
+ */
+ public String getCertAlgEcdsa()
+ {
+ return this.cert_alg_ecdsa;
+ }
+
+ /**
+ * Returns the rsa cert alg property.
+ *
+ * @return Returns the rsa cert alg property.
+ */
+ public String getCertAlgRsa()
+ {
+ return this.cert_alg_rsa;
+ }
+
+ /**
+ * Reads the configuration entry given by the key, first from the given
+ * profile, if not found from the defaults.
+ *
+ * @param settings
+ * The settings.
+ * @param profile
+ * The profile.
+ * @param key
+ * The configuration key.
+ * @return Returns the configuration entry.
+ */
+ public static String getConnectorValueFromProfile(SettingsReader settings,
+ String profile, String key)
+ {
+ String value = settings.getValueFromKey("sig_obj." + profile + "." + key); //$NON-NLS-1$//$NON-NLS-2$
+ if (value == null)
+ {
+ value = settings.getValueFromKey(key);
+ }
+ return value;
+ }
+ }
+
+
+ public XMLDsigData reconstructXMLDsig(SignatureData data, SignSignatureObject so)
+ throws ConnectorException {
+ String xmldsig = chooseAndCreateXMLDsig(data, so);
+ return new XMLDsigData(xmldsig, false);
+ }
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/LocRefDetachedBKUConnector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/LocRefDetachedBKUConnector.java
new file mode 100644
index 0000000..c5e1513
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/LocRefDetachedBKUConnector.java
@@ -0,0 +1,46 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors.bku;
+
+import at.gv.egiz.pdfas.framework.ConnectorParameters;
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
+
+/**
+ * @author wprinz
+ *
+ */
+public class LocRefDetachedBKUConnector extends DetachedBKUConnector
+{
+
+ /**
+ * @param connectorParameters
+ * @param loc_ref_content
+ * @throws ConnectorException
+ */
+ public LocRefDetachedBKUConnector(ConnectorParameters connectorParameters, String loc_ref_content) throws ConnectorException
+ {
+ super(connectorParameters, loc_ref_content);
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/MultipartDetachedBKUConnector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/MultipartDetachedBKUConnector.java
new file mode 100644
index 0000000..cfaa55d
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/MultipartDetachedBKUConnector.java
@@ -0,0 +1,42 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors.bku;
+
+import at.gv.egiz.pdfas.framework.ConnectorParameters;
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
+
+/**
+ * @author wprinz
+ *
+ */
+public class MultipartDetachedBKUConnector extends DetachedBKUConnector
+{
+ protected static final String MULTIPART_LOC_REF_CONTENT = "formdata:fileupload"; //$NON-NLS-1$
+
+ public MultipartDetachedBKUConnector(ConnectorParameters connectorParameters) throws ConnectorException
+ {
+ super(connectorParameters, MULTIPART_LOC_REF_CONTENT);
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/OldEnvelopingBase64BKUConnector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/OldEnvelopingBase64BKUConnector.java
new file mode 100644
index 0000000..58bdec6
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/OldEnvelopingBase64BKUConnector.java
@@ -0,0 +1,135 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors.bku;
+
+import java.io.UnsupportedEncodingException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteObject;
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
+import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
+import at.knowcenter.wag.egov.egiz.tools.CodingHelper;
+import at.knowcenter.wag.egov.egiz.tools.FileHelper;
+
+/**
+ *
+ * <p>
+ * This is the old base64 connector. The difference is in the way the sign
+ * response is parsed and the verify content_xml.
+ * </p>
+ *
+ * @author wprinz
+ *
+ */
+public class OldEnvelopingBase64BKUConnector extends EnvelopedBase64BKUConnector
+{
+ /**
+ * The log.
+ */
+ private static Log log = LogFactory.getLog(OldEnvelopingBase64BKUConnector.class);
+
+ // TODO implement signing - with old pre 2.7.2 BKUs... not really necessary
+ // though because this connector is only used for verification
+
+ public OldEnvelopingBase64BKUConnector(String profile) throws ConnectorException
+ {
+ super(profile);
+
+ this.environment = new OverriddenEnvironment(profile);
+ }
+
+
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.connectors.bku.EnvelopedBase64BKUConnector#computeSignedPropertiesReplace(java.lang.String)
+ */
+ protected String computeSignedPropertiesReplace(String verify_xml, AlgorithmSuiteObject algSuite)
+ {
+ try
+ {
+ final String ETSI_QUALIFYING_PROPERTIES_START_TAG = "<etsi:QualifyingProperties"; //$NON-NLS-1$
+ final String ETSI_QUALIFYING_PROPERTIES_END_TAG = "</etsi:QualifyingProperties>"; //$NON-NLS-1$
+
+ final int hash_start = verify_xml.indexOf(ETSI_QUALIFYING_PROPERTIES_START_TAG);
+ assert hash_start >= 0;
+ final int hash_end = verify_xml.indexOf(ETSI_QUALIFYING_PROPERTIES_END_TAG, hash_start) + ETSI_QUALIFYING_PROPERTIES_END_TAG.length();
+ assert hash_end - ETSI_QUALIFYING_PROPERTIES_END_TAG.length() >= 0;
+ assert hash_end > hash_start;
+
+ final String string_to_be_hashed = verify_xml.substring(hash_start, hash_end);
+ log.debug("etsi:QualifyingProperties string to be hashed: " + string_to_be_hashed); //$NON-NLS-1$
+
+ final byte[] bytes_to_be_hashed = string_to_be_hashed.getBytes("UTF-8"); //$NON-NLS-1$
+ byte[] sig_prop_code = CodingHelper.buildDigest(bytes_to_be_hashed, algSuite.getPropertiesDigestMethod());
+ String sig_prop_hash = CodingHelper.encodeBase64(sig_prop_code);
+
+ return sig_prop_hash;
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ throw new RuntimeException("Very Strange: UTF-8 character encoding not supported.", e);
+ }
+ }
+
+
+
+ public static class OverriddenEnvironment extends EnvelopedBase64BKUConnector.Environment
+ {
+
+ /**
+ * The configuration key of the verify template.
+ */
+ protected static final String VERIFY_TEMPLATE_KEY = "bku.verify.template.base64old"; //$NON-NLS-1$
+
+ public OverriddenEnvironment(String profile) throws ConnectorException
+ {
+ super(profile);
+
+ SettingsReader settings = null;
+ try
+ {
+ settings = SettingsReader.getInstance();
+ }
+ catch (SettingsException e)
+ {
+ throw new ConnectorException(ErrorCode.SETTING_NOT_FOUND, e);
+ }
+
+ String verify_filename = getConnectorValueFromProfile(settings, profile, VERIFY_TEMPLATE_KEY);
+ //this.verify_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_filename));
+ this.verify_template = settings.readInternalResourceAsString(verify_filename);
+ if (this.verify_template == null)
+ {
+ throw new ConnectorException(ErrorCode.SETTING_NOT_FOUND, "Can not read the verify template"); //$NON-NLS-1$
+ }
+
+ }
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/SignSignatureObject.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/SignSignatureObject.java
new file mode 100644
index 0000000..72f181e
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/SignSignatureObject.java
@@ -0,0 +1,272 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors.bku;
+
+import java.io.Serializable;
+import java.security.cert.X509Certificate;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import at.gv.egiz.pdfas.api.timestamp.TimeStamper;
+import at.knowcenter.wag.egov.egiz.sig.SignatureTypes;
+import at.knowcenter.wag.egov.egiz.sig.signatureobject.AdditionalSignatureInformation;
+import at.knowcenter.wag.egov.egiz.sig.signatureobject.AlgorithmSignatureInformation;
+import at.knowcenter.wag.egov.egiz.sig.signatureobject.ConnectorSignatureInformation;
+import at.knowcenter.wag.egov.egiz.sig.signatureobject.MandatorySignatureInformation;
+
+/**
+ * @author wprinz
+ *
+ */
+public class SignSignatureObject implements Serializable, MandatorySignatureInformation, ConnectorSignatureInformation, AlgorithmSignatureInformation, AdditionalSignatureInformation
+{
+ /**
+ * SVUID.
+ */
+ private static final long serialVersionUID = -2689261480444802213L;
+
+ public String date = null;
+ public String issuer = null;
+ public String signatureValue = null;
+
+ public String id = null;
+ public String kz = null;
+
+ public String sigAlgorithm;
+
+ public String sigTimeStamp;
+
+ /**
+ * This is used to transport the response properties to the Detached signator.
+ */
+ public Properties response_properties = null;
+
+ /**
+ * The X509Certificate.
+ *
+ * <p>
+ * This also provides the serial number and name.
+ * </p>
+ */
+ public X509Certificate x509Certificate = null;
+
+ // dferbas
+ public Map subjectDNMap = new HashMap();
+ public Map issuerDNMap = new HashMap();
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.signatureobject.MandatorySignatureInformation#getDate()
+ */
+ public String getDate()
+ {
+ return this.date;
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.signatureobject.MandatorySignatureInformation#getIssuer()
+ */
+ public String getIssuer()
+ {
+ return this.issuer;
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.signatureobject.MandatorySignatureInformation#getSerialNumber()
+ */
+ public String getSerialNumber()
+ {
+ return this.x509Certificate.getSerialNumber().toString();
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.signatureobject.MandatorySignatureInformation#getSignatureValue()
+ */
+ public String getSignatureValue()
+ {
+ return this.signatureValue;
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.signatureobject.ConnectorSignatureInformation#getSigID()
+ */
+ public String getSigID()
+ {
+ return this.id;
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.signatureobject.AlgorithmSignatureInformation#getSigKZ()
+ */
+ public String getSigKZ()
+ {
+ return this.kz;
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.signatureobject.AdditionalSignatureInformation#getName()
+ */
+ public String getName()
+ {
+ return this.x509Certificate.getSubjectDN().toString();
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.signatureobject.AdditionalSignatureInformation#getX509Certificate()
+ */
+ public X509Certificate getX509Certificate()
+ {
+ return this.x509Certificate;
+ }
+
+ public String getSigAlgorithm() {
+ return this.sigAlgorithm;
+ }
+
+ public String retrieveStringValue(String sigKey)
+ {
+ // mandatory
+ if (sigKey.equals(SignatureTypes.SIG_DATE))
+ {
+ return getDate();
+ }
+ if (sigKey.equals(SignatureTypes.SIG_VALUE))
+ {
+ return getSignatureValue();
+ }
+ if (sigKey.equals(SignatureTypes.SIG_ISSUER))
+ {
+ return getIssuer();
+ }
+ if (sigKey.equals(SignatureTypes.SIG_NUMBER))
+ {
+ return getSerialNumber();
+ }
+
+ // connector
+ if (sigKey.equals(SignatureTypes.SIG_ID))
+ {
+ return getSigID();
+ }
+
+ // algorithm
+ if (sigKey.equals(SignatureTypes.SIG_KZ))
+ {
+ return getSigKZ();
+ }
+
+ // additional
+ if (sigKey.equals(SignatureTypes.SIG_NAME))
+ {
+ return getName();
+ }
+
+ if (sigKey.equals(SignatureTypes.SIG_SUBJECT))
+ {
+ return getName();
+ }
+
+ if (sigKey.equals(SignatureTypes.SIG_ALG)) {
+ return getSigAlgorithm();
+ }
+
+ throw new RuntimeException("The key '" + sigKey + "' is not a recognized SignatorObject member."); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ // dferbas
+
+
+ /**
+ * Get a timestamp if available as b64 string
+ * @see TimeStamper
+ * @return
+ */
+ public String getSigTimeStamp() {
+ return this.sigTimeStamp;
+ }
+
+ public Map getSubjectDNMap() {
+ if (this.subjectDNMap.size() == 0 && this.getX509Certificate() != null) {
+ //rpiazzi workaround
+ //the problem with atrust encoding special characters (Sonderzeichen) wrong
+ //led to this workaround. As special characters are of the form e.g. "&#xxx;"
+ //Example: for "Georg Müller" atrust returns "Georg M&#252;ller"
+ //By calling this.getX509Certificate().getSubjectDN().getName() you get "Georg M&#252\;ller",
+ //After that the down called method fillDNMap replaces the "\" with a "+"
+ //Because of this the workaround in at.gv.egiz.pdfas.impl.signator.binary.BinarySignator_1_0_0.fillReplacesWithValues()
+ //which replaces the wrong codes of atrust with the special chars does not work
+ //------------------------------------------------------------------------------
+ //The workaround here is to call this.getX509Certificate().getSubjectDN.toString()
+ //instead of this.getX509Certificate().getSubjectDN.getName()
+ if (this.getX509Certificate().getSubjectDN().toString().contains(";") ||
+ this.getX509Certificate().getSubjectDN().toString().contains("#") ||
+ this.getX509Certificate().getSubjectDN().toString().contains("&")) {
+ fillDNMap(this.getX509Certificate().getSubjectDN().toString(), this.subjectDNMap);
+ }
+ else {
+ fillDNMap(this.getX509Certificate().getSubjectDN().getName(), this.subjectDNMap);
+ }
+ //end workaround
+ }
+ return this.subjectDNMap;
+ }
+
+ public String certSubjectDNPart(String key) {
+ return (String)this.getSubjectDNMap().get(key);
+ }
+
+ public Map getIssuerDNMap() {
+ if (this.issuerDNMap.size() == 0 && this.getX509Certificate() != null) {
+ fillDNMap(this.getX509Certificate().getIssuerDN().getName(), this.issuerDNMap);
+ }
+ return this.issuerDNMap;
+ }
+
+ public String certIssuerDNPart(String key) {
+ return (String)this.getIssuerDNMap().get(key);
+ }
+
+ private void fillDNMap(String dn, Map dnMap) {
+
+ // split at "," but not at "\,"
+ String[] arr = dn.split("\\s*(?<![\\\\]),\\s*");
+
+ for (int i = 0; i < arr.length; i++) {
+ String[] entry = arr[i].split("\\s*(=)\\s*");
+
+ // resolve escaped values according to RFC2253
+ entry[1] = entry[1].replaceAll("\\\\,", ","); // \, -> ,
+ entry[1] = entry[1].replaceAll("\\\\+", "+"); // \+ -> +
+ entry[1] = entry[1].replaceAll("\\\\\"", "\""); // \" -> "
+ entry[1] = entry[1].replaceAll("\\\\\\\\", "\\"); // \\ -> \
+ entry[1] = entry[1].replaceAll("\\\\<,", "<"); // \< -> <
+ entry[1] = entry[1].replaceAll("\\\\>", ">"); // \> -> >
+ entry[1] = entry[1].replaceAll("\\\\;", ";"); // \; -> ;
+ entry[1] = entry[1].replaceAll("\\\\#", "#"); // \# -> #
+
+ dnMap.put(entry[0], entry[1]);
+ }
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/SignSignatureObjectHelper.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/SignSignatureObjectHelper.java
new file mode 100644
index 0000000..4eb6e39
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/SignSignatureObjectHelper.java
@@ -0,0 +1,76 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+//package at.knowcenter.wag.egov.egiz.sig.connectors.bku;
+//
+//import at.knowcenter.wag.egov.egiz.sig.SignatureObject;
+//import at.knowcenter.wag.egov.egiz.sig.SignatureTypes;
+//
+///**
+// * @author wprinz
+// *
+// */
+//public abstract class SignSignatureObjectHelper
+//{
+// public static String retrieveStringValueFromSignatureObject (SignSignatureObject so, String key)
+// {
+// // mandatory
+// if (key.equals(SignatureTypes.SIG_DATE))
+// {
+// return so.getDate();
+// }
+// if (key.equals(SignatureTypes.SIG_VALUE))
+// {
+// return so.getSignatureValue();
+// }
+// if (key.equals(SignatureTypes.SIG_ISSUER))
+// {
+// return so.getIssuer();
+// }
+// if (key.equals(SignatureTypes.SIG_NUMBER))
+// {
+// return so.getSerialNumber();
+// }
+//
+// // connector
+// if (key.equals(SignatureTypes.SIG_ID))
+// {
+// return so.getSigID();
+// }
+//
+// // algorithm
+// if (key.equals(SignatureTypes.SIG_KZ))
+// {
+// return so.getSigKZ();
+// }
+//
+// // additional
+// if (key.equals(SignatureTypes.SIG_NAME))
+// {
+// return so.getName();
+// }
+//
+// throw new RuntimeException("The key '" + key + "' is not a recognized SignatorObject member."); //$NON-NLS-1$ //$NON-NLS-2$
+// }
+//
+//}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/DetachedLocRefMOAConnector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/DetachedLocRefMOAConnector.java
new file mode 100644
index 0000000..ea90841
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/DetachedLocRefMOAConnector.java
@@ -0,0 +1,661 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors.moa;
+
+import java.security.cert.X509Certificate;
+import java.util.Properties;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmMapper;
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteObject;
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteUtil;
+import at.gv.egiz.pdfas.api.xmldsig.XMLDsigData;
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.gv.egiz.pdfas.framework.ConnectorParameters;
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
+import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
+import at.knowcenter.wag.egov.egiz.exceptions.SignatureException;
+import at.knowcenter.wag.egov.egiz.sig.SignatureData;
+import at.knowcenter.wag.egov.egiz.sig.SignatureResponse;
+import at.knowcenter.wag.egov.egiz.sig.connectors.Connector;
+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.BKUHelper;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUPostConnection;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.DetachedBKUConnector;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject;
+import at.knowcenter.wag.egov.egiz.sig.sigid.DetachedLocRefMOAIdFormatter;
+import at.knowcenter.wag.egov.egiz.sig.sigkz.SigKZIDHelper;
+import at.knowcenter.wag.egov.egiz.tools.CodingHelper;
+import at.knowcenter.wag.egov.egiz.tools.FileHelper;
+
+/**
+ * Connects to MOA providing the Data detached as LocRef on a local resource.
+ *
+ * @author wprinz
+ */
+public class DetachedLocRefMOAConnector implements Connector
+{
+ //23.11.2010 changed by exthex - added reconstructXMLDsig method and moved xmldsig creation to chooseAndCreateXMLDsig method
+ /**
+ * The SIG_ID prefix.
+ */
+ // public static final String SIG_ID_PREFIX = "etsi-bku-detached@"; //$NON-NLS-1$
+ /**
+ * The log.
+ */
+ private static Log log = LogFactory.getLog(DetachedLocRefMOAConnector.class);
+
+ /**
+ * The environemnt configuration of this connector containing templates and
+ * other configurable elements.
+ */
+ protected Environment environment = null;
+
+ /**
+ * Constructor that builds the configuration environment for this connector
+ * according to the given profile.
+ *
+ * <p>
+ * If confuguration parameters are not defined on that profile, the default
+ * parameters defined in the configuration are used.
+ * </p>
+ *
+ * @param profile
+ * The profile from which the Environment should be assembled.
+ * @throws SettingsException
+ * f.e.
+ * @throws SignatureException
+ * f.e.
+ */
+ public DetachedLocRefMOAConnector(String profile, String signature_data_url) throws ConnectorException
+ {
+ this.environment = new Environment(profile, signature_data_url);
+ }
+
+ protected String prepareSignRequest(SignatureData data) throws ConnectorException
+ {
+ log.debug("prepareSignRequestDetached:"); //$NON-NLS-1$
+
+ String sign_request_template = this.environment.getSignRequestTemplate();
+
+ String sign_key_identifier = this.environment.getSignKeyIdentifier();
+ String loc_ref_content = this.environment.getSignatureDataUrl();
+ String mime_type = data.getMimeType();
+ if (log.isDebugEnabled())
+ {
+ log.debug("sign keybox identifier = " + sign_key_identifier); //$NON-NLS-1$
+ log.debug("LocRefContent = " + loc_ref_content); //$NON-NLS-1$
+ log.debug("mime type = " + mime_type); //$NON-NLS-1$
+ }
+
+ String sign_request_xml = sign_request_template.replaceFirst(TemplateReplaces.KEY_IDENTIFIER_REPLACE, sign_key_identifier);
+ sign_request_xml = sign_request_xml.replaceFirst(TemplateReplaces.LOC_REF_CONTENT_REPLACE, loc_ref_content);
+ sign_request_xml = sign_request_xml.replaceFirst(TemplateReplaces.MIME_TYPE_REPLACE, mime_type);
+
+ log.debug("prepareSignRequestDetached finished."); //$NON-NLS-1$
+ return sign_request_xml;
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.connectors.LocalConnector#analyzeSignResponse(java.util.Properties)
+ */
+ public SignSignatureObject analyzeSignResponse(Properties response_properties) throws ConnectorException
+ {
+ log.debug("analyzeSignResponse:"); //$NON-NLS-1$
+
+ String response_string = response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY);
+
+ BKUHelper.checkResponseForError(response_string);
+
+ SignSignatureObject so = MOAHelper.parseCreateXMLResponse(response_string, new DetachedLocRefMOAIdFormatter(), this.environment);
+
+ log.debug("analyzeSignResponse finished."); //$NON-NLS-1$
+ return so;
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.connectors.Connector#doSign(at.knowcenter.wag.egov.egiz.sig.SignatureData)
+ */
+ public SignSignatureObject doSign(SignatureData data) throws ConnectorException
+ {
+ log.debug("doSign:"); //$NON-NLS-1$
+
+ String sign_request_xml = prepareSignRequest(data);
+// DebugHelper.debugStringToFile(sign_request_xml, "MOA_DetLocRef_sign_request.xml"); //$NON-NLS-1$
+
+ String url = this.environment.getSignURL();
+ Properties response_properties = sendRequest(url, MOASoapConnection.SERVICE_SIGN, sign_request_xml);
+
+// DebugHelper.debugStringToFile(response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY), "MOA_DetLocRef_sign_response.xml"); //$NON-NLS-1$
+ SignSignatureObject sso = analyzeSignResponse(response_properties);
+
+ sso.response_properties = response_properties;
+
+ log.debug("doSign finished."); //$NON-NLS-1$
+ return sso;
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.connectors.Connector#doVerify(at.knowcenter.wag.egov.egiz.sig.SignatureData,
+ * at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject)
+ */
+ public SignatureResponse doVerify(SignatureData data, SignSignatureObject so, XMLDsigData dsig) throws ConnectorException
+ {
+ log.debug("doVerify:"); //$NON-NLS-1$
+
+ String verify_request_xml = prepareVerifyRequest(data, so, dsig);
+ log.debug("verify_request_xml = " + verify_request_xml); //$NON-NLS-1$
+
+ String url = this.environment.getVerifyURL();
+ Properties response_properties = sendRequest(url, MOASoapConnection.SERVICE_VERIFY, verify_request_xml);
+
+ SignatureResponse signature_response = analyzeVerifyResponse(response_properties);
+
+ log.debug("doVerify finished."); //$NON-NLS-1$
+ return signature_response;
+ }
+
+ /**
+ * Prepares the verify request xml to be sent using the verify request
+ * template.
+ *
+ * @param data
+ * The SignatureData.
+ * @param so
+ * The signature information object.
+ * @return Returns the verify request xml to be sent.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public String prepareVerifyRequest(SignatureData data, SignSignatureObject so, XMLDsigData dsigData) throws ConnectorException
+ {
+ String verify_request_template = this.environment.getVerifyRequestTemplate();
+
+ String xml_content = null;
+ if (dsigData != null && dsigData.getXmlDsig() != null)
+ {
+ xml_content = dsigData.getXmlDsig();
+ }
+ else
+ {
+ xml_content = chooseAndCreateXMLDsig(data, so);
+ }
+
+ String verify_request_xml = verify_request_template.replaceFirst(TemplateReplaces.XML_CONTENT_REPLACE, xml_content);
+ verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.TRUST_PROFILE_ID_REPLACE, this.environment.getVerifyTrustProfileId());
+ verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.LOC_REF_CONTENT_REPLACE, this.environment.getSignatureDataUrl());
+
+ log.debug("\r\n\r\n" + verify_request_xml + "\r\n\r\n");
+
+ return verify_request_xml;
+ }
+
+ /**
+ * Analyzes the verify response string.
+ *
+ * @param response_properties
+ * The response properties containing the response XML.
+ * @return Returns the SignatureResponse containing the verification result.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public SignatureResponse analyzeVerifyResponse(Properties response_properties) throws ConnectorException
+ {
+ log.debug("analyzeVerifyResponse:"); //$NON-NLS-1$
+
+ String response_string = response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY);
+
+ BKUHelper.checkResponseForError(response_string);
+
+ SignatureResponse signature_response = BKUHelper.parseVerifyXMLResponse(response_string);
+
+ log.debug("analyzeVerifyResponse finished."); //$NON-NLS-1$
+ return signature_response;
+ }
+
+ public String prepareXMLContent(SignatureData data, SignSignatureObject so) throws ConnectorException
+ {
+ log.debug("prepareXMLContent:"); //$NON-NLS-1$
+ try
+ {
+
+ X509Certificate cert = so.getX509Certificate();
+
+ // dferbas
+ AlgorithmSuiteObject algSuite = new AlgorithmSuiteObject();
+ String verify_xml = AlgorithmSuiteUtil.evaluateReplaceAlgs(algSuite, this.environment, so);
+
+ // data digest replace
+ {
+// byte[] data_value = data.getData();
+// byte[] data_value_hash = CodingHelper.buildDigest(data_value);
+ byte[] data_value_hash = CodingHelper.buildDigest(data.getDataSource(), algSuite.getDataDigestMethod());
+ String object_data_hash = CodingHelper.encodeBase64(data_value_hash);
+
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_SIGNED_DATA_REPLACE, object_data_hash);
+ }
+
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.SIGNATURE_VALUE_REPLACE, so.getSignatureValue());
+
+ // X.509 Certificate replace
+ byte[] der = cert.getEncoded();
+ byte[] cert_hash = CodingHelper.buildDigest(der, algSuite.getCertDigestMethod());
+ String certDigest = CodingHelper.encodeBase64(cert_hash);
+ String x509_cert_string = CodingHelper.encodeBase64(der);
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_CERTIFICATE_REPLACE, x509_cert_string);
+
+ // Qualified Properties replaces
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.SIGNING_TIME_REPLACE, so.getDate());
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_CERTIFICATE_REPLACE, certDigest);
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_ISSUER_NAME_REPLACE, so.getIssuer());
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_SERIAL_NUMBER_REPLACE, so.getSerialNumber());
+ // SigDataRefReplace already done above
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.MIME_TYPE_REPLACE, data.getMimeType());
+
+ // Signed Properties hash
+ {
+ final String ETSI_SIGNED_PROPERTIES_START_TAG = "<etsi:SignedProperties"; //$NON-NLS-1$
+ final String ETSI_SIGNED_PROPERTIES_END_TAG = "</etsi:SignedProperties>"; //$NON-NLS-1$
+
+ final int hash_start = verify_xml.indexOf(ETSI_SIGNED_PROPERTIES_START_TAG);
+ assert hash_start >= 0;
+ final int hash_end = verify_xml.indexOf(ETSI_SIGNED_PROPERTIES_END_TAG, hash_start) + ETSI_SIGNED_PROPERTIES_END_TAG.length();
+ assert hash_end - ETSI_SIGNED_PROPERTIES_END_TAG.length() >= 0;
+ assert hash_end > hash_start;
+
+ final String string_to_be_hashed = verify_xml.substring(hash_start, hash_end);
+ log.debug("etsi:SignedProperties string to be hashed: " + string_to_be_hashed); //$NON-NLS-1$
+
+ final byte[] bytes_to_be_hashed = string_to_be_hashed.getBytes("UTF-8"); //$NON-NLS-1$
+ byte[] sig_prop_code = CodingHelper.buildDigest(bytes_to_be_hashed, algSuite.getPropertiesDigestMethod());
+ String sig_prop_hash = CodingHelper.encodeBase64(sig_prop_code);
+
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_SIGNED_PROPERTIES_REPLACE, sig_prop_hash);
+ }
+
+ log.debug("prepareXMLContent finished."); //$NON-NLS-1$
+ return verify_xml;
+ }
+ catch (Exception e)
+ {
+ log.debug(e);
+ throw new ConnectorException(310, e);
+ }
+ }
+
+ protected Properties sendRequest(String url, String mode, String request_string) throws ConnectorException
+ {
+ try
+ {
+ Properties response_properties = MOASoapConnection.connectMOA(request_string, MOASoapConnection.SERVICE_SIGN, url);
+ return response_properties;
+ }
+ catch (Exception e)
+ {
+ throw new ConnectorException(330, e);
+ }
+ }
+
+ /**
+ * Holds environment configuration information like templates.
+ *
+ * @author wprinz
+ */
+ public static class Environment extends ConnectorEnvironment
+ {
+ /**
+ * The configuration key of the sign keybox identifier.
+ */
+ protected static final String SIGN_KEY_IDENTIFIER_KEY = "moa.sign.KeyIdentifier"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the sign request template.
+ */
+ protected static final String SIGN_REQUEST_TEMPLATE_KEY = "moa.sign.request.detached"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the sign URL.
+ */
+ protected static final String SIGN_URL_KEY = "moa.sign.url"; //$NON-NLS-1$
+
+ /**
+ * MOA template file prefix
+ */
+ protected static final String TEMPLATE_FILE_PREFIX = "/templates/moa.";
+
+ /**
+ * signing file template sufix
+ */
+ protected static final String SIGN_TEMPLATE_FILE_SUFIX = ".sign.xml";
+
+ /**
+ * verifing template file sufix
+ */
+ protected static final String VERIFY_REQUEST_TEMPLATE_FILE_SUFIX = ".verify.request.xml";
+
+ /**
+ * verifing file template key sufix
+ */
+ protected static final String VERIFY_TEMPLATE_SUFIX = ".verify.template.xml";
+
+ /**
+ * The configuration key of the verify request template.
+ */
+ protected static final String VERIFY_REQUEST_TEMPLATE_KEY = "moa.verify.request.detached"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the verify template.
+ */
+ protected static final String VERIFY_TEMPLATE_KEY = "moa.verify.template.detached"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the verify URL.
+ */
+ protected static final String VERIFY_URL_KEY = "moa.verify.url"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the trust profile id.
+ */
+ protected static final String VERIFY_TRUST_PROFILE_ID = "moa.verify.TrustProfileID"; //$NON-NLS-1$
+
+ /**
+ * The configuration key for the ECDSA cert alg property.
+ */
+ protected static final String ECDSA_CERT_ALG_KEY = "cert.alg.ecdsa"; //$NON-NLS-1$
+
+ /**
+ * The configuration key for the RSA cert alg property.
+ */
+ protected static final String RSA_CERT_ALG_KEY = "cert.alg.rsa"; //$NON-NLS-1$
+
+ protected String profile = null;
+
+ protected String signature_data_url = null;
+
+ protected String sign_key_identifier = null;
+
+ protected String sign_request_template = null;
+
+ protected String sign_url = null;
+
+ protected String verify_request_template = null;
+
+ protected String verify_template = null;
+
+ protected String verify_url = null;
+
+ protected String verify_trust_profile_id = null;
+
+ protected String cert_alg_ecdsa = null;
+
+ protected String cert_alg_rsa = null;
+
+ /**
+ * Initializes the environment with a given profile.
+ *
+ * @param profile
+ * The configuration profile.
+ * @throws SettingsException
+ * f.e.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public Environment(String profile, String signature_data_url) throws ConnectorException
+ {
+ this.profile = profile;
+
+ this.signature_data_url = signature_data_url;
+
+ SettingsReader settings = null;
+ try
+ {
+ settings = SettingsReader.getInstance();
+ }
+ catch (SettingsException e)
+ {
+ throw new ConnectorException(300, e);
+ }
+
+ this.sign_key_identifier = getConnectorValueFromProfile(settings, profile, SIGN_KEY_IDENTIFIER_KEY);
+
+ String sign_request_filename = TEMPLATE_FILE_PREFIX + settings.getValueFromKey("default.moa.algorithm.id") + SIGN_TEMPLATE_FILE_SUFIX;
+
+ // try to load template from file
+ //this.sign_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename));
+ this.sign_request_template = settings.readInternalResourceAsString(sign_request_filename);
+
+ if (this.sign_request_template == null)
+ {
+ sign_request_filename = getConnectorValueFromProfile(settings, profile, SIGN_REQUEST_TEMPLATE_KEY);
+ //this.sign_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename));
+ this.sign_request_template = settings.readInternalResourceAsString(sign_request_filename);
+ }
+
+ //this.sign_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename));
+ if (this.sign_request_template == null)
+ {
+ throw new ConnectorException(ErrorCode.SETTING_NOT_FOUND, "Can not read the create xml request template"); //$NON-NLS-1$
+ }
+
+ this.sign_url = getConnectorValueFromProfile(settings, profile, SIGN_URL_KEY);
+
+ String verify_request_filename = TEMPLATE_FILE_PREFIX + settings.getValueFromKey("default.moa.algorithm.id") + VERIFY_REQUEST_TEMPLATE_FILE_SUFIX;
+
+ // try to load template file for verifing
+ //this.verify_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_request_filename));
+ this.verify_request_template = settings.readInternalResourceAsString(verify_request_filename);
+
+ if (this.verify_request_template == null)
+ {
+ verify_request_filename = getConnectorValueFromProfile(settings, profile, VERIFY_REQUEST_TEMPLATE_KEY);
+ //this.verify_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_request_filename));
+ this.verify_request_template = settings.readInternalResourceAsString(verify_request_filename);
+ }
+
+ if (this.verify_request_template == null)
+ {
+ throw new ConnectorException(ErrorCode.SETTING_NOT_FOUND, "Can not read the verify xml request template"); //$NON-NLS-1$
+ }
+
+ // load template key file
+ String verify_filename = TEMPLATE_FILE_PREFIX + settings.getValueFromKey("default.moa.algorithm.id") + VERIFY_TEMPLATE_SUFIX;
+ //this.verify_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_filename));
+ this.verify_template = settings.readInternalResourceAsString(verify_filename);
+
+ if (this.verify_template == null)
+ {
+ verify_filename = getConnectorValueFromProfile(settings, profile, VERIFY_TEMPLATE_KEY);
+ //this.verify_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_filename));
+ this.verify_template = settings.readInternalResourceAsString(verify_filename);
+ }
+
+ if (this.verify_template == null)
+ {
+ throw new ConnectorException(ErrorCode.SETTING_NOT_FOUND, "Can not read the verify template"); //$NON-NLS-1$
+ }
+
+ this.verify_url = getConnectorValueFromProfile(settings, profile, VERIFY_URL_KEY);
+
+ this.verify_trust_profile_id = settings.getValueFromKey(VERIFY_TRUST_PROFILE_ID);
+
+ this.cert_alg_ecdsa = settings.getValueFromKey(ECDSA_CERT_ALG_KEY);
+
+ this.cert_alg_rsa = settings.getValueFromKey(RSA_CERT_ALG_KEY);
+
+ }
+
+ public String getProfile()
+ {
+ return this.profile;
+ }
+
+ /**
+ * Returns the URL where to load the detached data from.
+ *
+ * @return Returns the URL where to load the detached data from.
+ */
+ public String getSignatureDataUrl()
+ {
+ return this.signature_data_url;
+ }
+
+ /**
+ * Returns the sign key identifier.
+ *
+ * @return Returns the sign key identifier.
+ */
+ public String getSignKeyIdentifier()
+ {
+ return this.sign_key_identifier;
+ }
+
+ /**
+ * Returns the sign request template.
+ *
+ * @return Returns the sign request template.
+ */
+ public String getSignRequestTemplate()
+ {
+ return this.sign_request_template;
+ }
+
+ /**
+ * Returns the sign URL.
+ *
+ * @return Returns the sign URL.
+ */
+ public String getSignURL()
+ {
+ return this.sign_url;
+ }
+
+ /**
+ * Returns the verify request template.
+ *
+ * @return Returns the verify request template.
+ */
+ public String getVerifyRequestTemplate()
+ {
+ return this.verify_request_template;
+ }
+
+ /**
+ * Returns the verify template.
+ *
+ * @return Returns the verify template.
+ */
+ public String getVerifyTemplate()
+ {
+ return this.verify_template;
+ }
+
+ /**
+ * Returns the verify URL.
+ *
+ * @return Returns the verify URL.
+ */
+ public String getVerifyURL()
+ {
+ return this.verify_url;
+ }
+
+ /**
+ * Returns the verify trust profile id.
+ *
+ * @return Returns the verify trust profile id.
+ */
+ public String getVerifyTrustProfileId()
+ {
+ return this.verify_trust_profile_id;
+ }
+
+ /**
+ * Returns the ecdsa cert alg property.
+ *
+ * @return Returns the ecdsa cert alg property.
+ */
+ public String getCertAlgEcdsa()
+ {
+ return this.cert_alg_ecdsa;
+ }
+
+ /**
+ * Returns the rsa cert alg property.
+ *
+ * @return Returns the rsa cert alg property.
+ */
+ public String getCertAlgRsa()
+ {
+ return this.cert_alg_rsa;
+ }
+
+ /**
+ * Reads the configuration entry given by the key, first from the given
+ * profile, if not found from the defaults.
+ *
+ * @param settings
+ * The settings.
+ * @param profile
+ * The profile.
+ * @param key
+ * The configuration key.
+ * @return Returns the configuration entry.
+ */
+ public static String getConnectorValueFromProfile(SettingsReader settings, String profile, String key)
+ {
+ String value = settings.getValueFromKey("sig_obj." + profile + "." + key); //$NON-NLS-1$//$NON-NLS-2$
+ if (value == null)
+ {
+ value = settings.getValueFromKey(key);
+ }
+ return value;
+ }
+
+ }
+
+ public XMLDsigData reconstructXMLDsig(SignatureData data, SignSignatureObject so)
+ throws ConnectorException {
+ String xmldsig = chooseAndCreateXMLDsig(data, so);
+ return new XMLDsigData(xmldsig, true);
+ }
+
+ private String chooseAndCreateXMLDsig(SignatureData data, SignSignatureObject so) throws ConnectorException {
+ if (!SigKZIDHelper.isMOASigned(so))
+ {
+ ConnectorParameters cp = new ConnectorParameters();
+ cp.setProfileId(this.environment.getProfile());
+ DetachedBKUConnector bku_connector = new DetachedBKUConnector(cp, "not needed here");
+ return bku_connector.prepareXMLContent(data, so);
+ }
+ else
+ {
+ return prepareXMLContent(data, so);
+ }
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/EnvelopingBase64MOAConnector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/EnvelopingBase64MOAConnector.java
new file mode 100644
index 0000000..6f2d171
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/EnvelopingBase64MOAConnector.java
@@ -0,0 +1,638 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors.moa;
+
+import java.security.cert.X509Certificate;
+import java.util.Properties;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteObject;
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteUtil;
+import at.gv.egiz.pdfas.api.xmldsig.XMLDsigData;
+import at.gv.egiz.pdfas.framework.ConnectorParameters;
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
+import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
+import at.knowcenter.wag.egov.egiz.sig.SignatureData;
+import at.knowcenter.wag.egov.egiz.sig.SignatureResponse;
+import at.knowcenter.wag.egov.egiz.sig.connectors.Connector;
+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.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.OldEnvelopingBase64BKUConnector;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject;
+import at.knowcenter.wag.egov.egiz.sig.sigid.OldMOAIdFormatter;
+import at.knowcenter.wag.egov.egiz.sig.sigkz.SigKZIDHelper;
+import at.knowcenter.wag.egov.egiz.tools.CodingHelper;
+import at.knowcenter.wag.egov.egiz.tools.FileHelper;
+
+/**
+ * @author wprinz
+ *
+ */
+public class EnvelopingBase64MOAConnector implements Connector
+{
+ //23.11.2010 changed by exthex - added reconstructXMLDsig method and moved xmldsig creation to chooseAndCreateXMLDsig method
+ /**
+ * The log.
+ */
+ private static Log log = LogFactory.getLog(EnvelopingBase64MOAConnector.class);
+
+ /**
+ * The environemnt configuration of this connector containing templates and
+ * other configurable elements.
+ */
+ protected Environment environment = null;
+
+ protected ConnectorParameters params = null;
+
+ /**
+ * Constructor that builds the configuration environment for this connector
+ * according to the given profile.
+ *
+ * <p>
+ * If confuguration parameters are not defined on that profile, the default
+ * parameters defined in the configuration are used.
+ * </p>
+ *
+ * @param profile
+ * The profile from which the Environment should be assembled.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public EnvelopingBase64MOAConnector(ConnectorParameters connectorParameters) throws ConnectorException
+ {
+ this.params = connectorParameters;
+ this.environment = new Environment(connectorParameters.getProfileId(), connectorParameters.getSignatureKeyIdentifier());
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.connectors.Connector#doSign(at.knowcenter.wag.egov.egiz.sig.SignatureData)
+ */
+ public SignSignatureObject doSign(SignatureData data) throws ConnectorException
+ {
+ log.debug("doSign:"); //$NON-NLS-1$
+
+ String sign_request_xml = prepareSignRequest(data);
+ log.debug("sign_request_xml = " + sign_request_xml); //$NON-NLS-1$
+
+ String url = this.environment.getSignURL();
+ Properties response_properties = sendRequest(url, MOASoapConnection.SERVICE_SIGN, sign_request_xml);
+
+ log.debug("response_string = " + response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY));; //$NON-NLS-1$
+ SignSignatureObject sso = analyzeSignResponse(response_properties);
+
+ sso.response_properties = response_properties;
+
+ log.debug("doSign finished."); //$NON-NLS-1$
+ return sso;
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.connectors.Connector#doVerify(at.knowcenter.wag.egov.egiz.sig.SignatureData,
+ * at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject)
+ */
+ public SignatureResponse doVerify(SignatureData data, SignSignatureObject so, XMLDsigData dsig) throws ConnectorException
+ {
+ log.debug("doVerify:"); //$NON-NLS-1$
+
+ String verify_request_xml = prepareVerifyRequest(data, so, dsig);
+ log.debug("verify_request_xml = " + verify_request_xml); //$NON-NLS-1$
+
+ String url = this.environment.getVerifyURL();
+ Properties response_properties = sendRequest(url, MOASoapConnection.SERVICE_VERIFY, verify_request_xml);
+
+ SignatureResponse signature_response = analyzeVerifyResponse(response_properties);
+
+ log.debug("doVerify finished."); //$NON-NLS-1$
+ return signature_response;
+ }
+
+ protected Properties sendRequest(String url, String mode,
+ String request_string) throws ConnectorException
+ {
+ try
+ {
+ Properties response_properties = MOASoapConnection.connectMOA(request_string, MOASoapConnection.SERVICE_SIGN, url);
+ return response_properties;
+ }
+ catch (Exception e)
+ {
+ throw new ConnectorException(330, e);
+ }
+ }
+
+ /**
+ * Prepares the sign request xml to be sent using the sign request template.
+ *
+ * @param data
+ * The SignatureData.
+ * @return Returns the sign request xml to be sent.
+ * @throws ConnectorException
+ * f.e.
+ */
+ protected String prepareSignRequest(SignatureData data) throws ConnectorException
+ {
+ log.debug("prepareSignRequest:"); //$NON-NLS-1$
+
+ String sign_request_template = this.environment.getSignRequestTemplate();
+
+ String sign_key_identifier = this.environment.getSignKeyIdentifier();
+ String base64 = BKUHelper.prepareBase64Content(data);
+
+ String sign_request_xml = sign_request_template.replaceFirst(TemplateReplaces.KEY_IDENTIFIER_REPLACE, sign_key_identifier);
+ sign_request_xml = sign_request_xml.replaceFirst(TemplateReplaces.BASE64_CONTENT_REPLACE, base64);
+
+ log.debug("prepareSignRequest finished."); //$NON-NLS-1$
+ return sign_request_xml;
+ }
+
+ /**
+ * Prepares the verify request xml to be sent using the verify request
+ * template.
+ *
+ * @param data
+ * The SignatureData.
+ * @param so
+ * The signature information object.
+ * @return Returns the verify request xml to be sent.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public String prepareVerifyRequest(SignatureData data, SignSignatureObject so, XMLDsigData dsigData) throws ConnectorException
+ {
+ String verify_request_template = this.environment.getVerifyRequestTemplate();
+
+ String xml_content = null;
+ if (dsigData != null && dsigData.getXmlDsig() != null)
+ {
+ xml_content = dsigData.getXmlDsig();
+ }
+ else
+ {
+ xml_content = chooseAndCreateXMLDsig(data, so);
+ }
+
+ String verify_request_xml = verify_request_template.replaceFirst(TemplateReplaces.XML_CONTENT_REPLACE, xml_content);
+ verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.TRUST_PROFILE_ID_REPLACE, this.environment.getVerifyTrustProfileId());
+
+ String returnHashInputDataElement = "";
+ if (this.params.isReturnHashInputData())
+ {
+ returnHashInputDataElement = MOASoapWithAttachmentConnector.RETURN_HASH_INPUT_DATA;
+ }
+ verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.RETURN_HASH_INPUT_DATA_REPLACE, returnHashInputDataElement);
+
+ verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.DATE_TIME_REPLACE, BKUHelper.formDateTimeElement(this.params.getVerificationTime()));
+
+
+ log.debug("\r\n\r\n" + verify_request_xml + "\r\n\r\n");
+
+ return verify_request_xml;
+ }
+
+ /**
+ * Analyzes the sign response xml and extracts the signature data.
+ *
+ * @param response_properties
+ * The response properties containing the response String and
+ * transport related information.
+ * @return Returns the extracted data encapsulated in a SignatureObject.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public SignSignatureObject analyzeSignResponse(Properties response_properties) throws ConnectorException
+ {
+ log.debug("analyzeSignResponse:"); //$NON-NLS-1$
+
+ String response_string = response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY);
+
+ BKUHelper.checkResponseForError(response_string);
+
+ SignSignatureObject so = MOAHelper.parseCreateXMLResponse(response_string, new OldMOAIdFormatter(), this.environment);
+
+ log.debug("analyzeSignResponse finished."); //$NON-NLS-1$
+ return so;
+ }
+
+ /**
+ * Analyzes the verify response string.
+ *
+ * @param response_properties
+ * The response properties containing the response XML.
+ * @return Returns the SignatureResponse containing the verification result.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public SignatureResponse analyzeVerifyResponse(Properties response_properties) throws ConnectorException
+ {
+ log.debug("analyzeVerifyResponse:"); //$NON-NLS-1$
+
+ String response_string = response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY);
+
+ BKUHelper.checkResponseForError(response_string);
+
+ SignatureResponse signature_response = BKUHelper.parseVerifyXMLResponse(response_string);
+
+ log.debug("analyzeVerifyResponse finished."); //$NON-NLS-1$
+ return signature_response;
+ }
+
+ /**
+ * Prepares the XML content the holds the actual signature data.
+ *
+ * <p>
+ * This strongly rebuilds the XML content as retuned from a sign request.
+ * </p>
+ *
+ * @param data
+ * The data.
+ * @param so
+ * The signature object containing the signature information.
+ * @return Returns the XML content.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public String prepareXMLContent(SignatureData data, SignSignatureObject so) throws ConnectorException
+ {
+ log.debug("prepareXMLContent:"); //$NON-NLS-1$
+ try
+ {
+ X509Certificate cert = so.getX509Certificate();
+
+ // dferbas
+ AlgorithmSuiteObject algSuite = new AlgorithmSuiteObject();
+ String verify_xml = AlgorithmSuiteUtil.evaluateReplaceAlgs(algSuite, this.environment, so);
+
+ // data digest replace
+ byte[] data_value = BKUHelper.prepareEnvelopingData(data);
+ {
+ byte[] data_value_hash = CodingHelper.buildDigest(data_value, algSuite.getDataDigestMethod());
+ String object_data_hash = CodingHelper.encodeBase64(data_value_hash);
+
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_SIGNED_DATA_REPLACE, object_data_hash);
+ }
+
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.SIGNATURE_VALUE_REPLACE, so.getSignatureValue());
+
+ // X.509 Certificate replace
+ byte[] der = cert.getEncoded();
+ byte[] cert_hash = CodingHelper.buildDigest(der, algSuite.getCertDigestMethod());
+ String certDigest = CodingHelper.encodeBase64(cert_hash);
+ String x509_cert_string = CodingHelper.encodeBase64(der);
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_CERTIFICATE_REPLACE, x509_cert_string);
+
+ // Qualified Properties replaces
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.SIGNING_TIME_REPLACE, so.getDate());
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_CERTIFICATE_REPLACE, certDigest);
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_ISSUER_NAME_REPLACE, so.getIssuer());
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_SERIAL_NUMBER_REPLACE, so.getSerialNumber());
+ // SigDataRefReplace already done above
+
+ // Signed Properties hash
+ {
+ final String ETSI_SIGNED_PROPERTIES_START_TAG = "<etsi:SignedProperties"; //$NON-NLS-1$
+ final String ETSI_SIGNED_PROPERTIES_END_TAG = "</etsi:SignedProperties>"; //$NON-NLS-1$
+
+ final int hash_start = verify_xml.indexOf(ETSI_SIGNED_PROPERTIES_START_TAG);
+ assert hash_start >= 0;
+ final int hash_end = verify_xml.indexOf(ETSI_SIGNED_PROPERTIES_END_TAG, hash_start) + ETSI_SIGNED_PROPERTIES_END_TAG.length();
+ assert hash_end - ETSI_SIGNED_PROPERTIES_END_TAG.length() >= 0;
+ assert hash_end > hash_start;
+
+ final String string_to_be_hashed = verify_xml.substring(hash_start, hash_end);
+ log.debug("etsi:SignedProperties string to be hashed: " + string_to_be_hashed); //$NON-NLS-1$
+
+ final byte[] bytes_to_be_hashed = string_to_be_hashed.getBytes("UTF-8"); //$NON-NLS-1$
+ byte[] sig_prop_code = CodingHelper.buildDigest(bytes_to_be_hashed, algSuite.getPropertiesDigestMethod());
+ String sig_prop_hash = CodingHelper.encodeBase64(sig_prop_code);
+
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_SIGNED_PROPERTIES_REPLACE, sig_prop_hash);
+ }
+
+ // Base64 content replace -> do this at last for performance
+ String base64 = CodingHelper.encodeBase64(data_value);
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.BASE64_CONTENT_REPLACE, base64);
+
+ log.debug("prepareXMLContent finished."); //$NON-NLS-1$
+ return verify_xml;
+ }
+ catch (Exception e)
+ {
+ log.debug(e);
+ throw new ConnectorException(310, e);
+ }
+ }
+
+ /**
+ * Holds environment configuration information like templates.
+ *
+ * @author wprinz
+ */
+ public static class Environment extends ConnectorEnvironment
+ {
+ /**
+ * The configuration key of the sign keybox identifier.
+ */
+ protected static final String SIGN_KEY_IDENTIFIER_KEY = "moa.sign.KeyIdentifier"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the sign request template.
+ */
+ protected static final String SIGN_REQUEST_TEMPLATE_KEY = "moa.sign.request.base64"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the sign URL.
+ */
+ protected static final String SIGN_URL_KEY = "moa.sign.url"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the verify request template.
+ */
+ protected static final String VERIFY_REQUEST_TEMPLATE_KEY = "moa.verify.request.base64"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the verify template.
+ */
+ protected static final String VERIFY_TEMPLATE_KEY = "moa.verify.template.base64"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the verify URL.
+ */
+ protected static final String VERIFY_URL_KEY = "moa.verify.url"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the trust profile id.
+ */
+ protected static final String VERIFY_TRUST_PROFILE_ID = "moa.verify.TrustProfileID"; //$NON-NLS-1$
+
+ /**
+ * The configuration key for the ECDSA cert alg property.
+ */
+ protected static final String ECDSA_CERT_ALG_KEY = "cert.alg.ecdsa"; //$NON-NLS-1$
+
+ /**
+ * The configuration key for the RSA cert alg property.
+ */
+ protected static final String RSA_CERT_ALG_KEY = "cert.alg.rsa"; //$NON-NLS-1$
+
+ protected String profile = null;
+
+ protected String sign_key_identifier = null;
+
+ protected String sign_request_template = null;
+
+ protected String sign_url = null;
+
+ protected String verify_request_template = null;
+
+ protected String verify_template = null;
+
+ protected String verify_url = null;
+
+ protected String verify_trust_profile_id = null;
+
+ protected String cert_alg_ecdsa = null;
+
+ protected String cert_alg_rsa = null;
+
+ /**
+ * Initializes the environment with a given profile.
+ *
+ * @param profile
+ * The configuration profile.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public Environment(String profile, String signKeyIdentifier) throws ConnectorException
+ {
+ this.profile = profile;
+
+ SettingsReader settings = null;
+ try
+ {
+ settings = SettingsReader.getInstance();
+ }
+ catch (SettingsException e)
+ {
+ throw new ConnectorException(300, e);
+ }
+
+ if (signKeyIdentifier != null)
+ {
+ this.sign_key_identifier = signKeyIdentifier;
+ }
+ else
+ {
+ this.sign_key_identifier = getConnectorValueFromProfile(settings, profile, SIGN_KEY_IDENTIFIER_KEY);
+ }
+
+ String sign_request_filename = getConnectorValueFromProfile(settings, profile, SIGN_REQUEST_TEMPLATE_KEY);
+ //this.sign_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename));
+ this.sign_request_template = settings.readInternalResourceAsString(sign_request_filename);
+ if (this.sign_request_template == null)
+ {
+ throw new ConnectorException(300, "Can not read the create xml request template"); //$NON-NLS-1$
+ }
+
+ this.sign_url = getConnectorValueFromProfile(settings, profile, SIGN_URL_KEY);
+
+ String verify_request_filename = getConnectorValueFromProfile(settings, profile, VERIFY_REQUEST_TEMPLATE_KEY);
+ //this.verify_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_request_filename));
+ this.verify_request_template = settings.readInternalResourceAsString(verify_request_filename);
+ if (this.verify_request_template == null)
+ {
+ throw new ConnectorException(300, "Can not read the verify xml request template"); //$NON-NLS-1$
+ }
+
+ String verify_filename = getConnectorValueFromProfile(settings, profile, VERIFY_TEMPLATE_KEY);
+ //this.verify_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_filename));
+ this.verify_template = settings.readInternalResourceAsString(verify_filename);
+ if (this.verify_template == null)
+ {
+ throw new ConnectorException(300, "Can not read the verify template"); //$NON-NLS-1$
+ }
+
+ this.verify_url = getConnectorValueFromProfile(settings, profile, VERIFY_URL_KEY);
+
+ this.verify_trust_profile_id = settings.getValueFromKey(VERIFY_TRUST_PROFILE_ID);
+
+ this.cert_alg_ecdsa = settings.getValueFromKey(ECDSA_CERT_ALG_KEY);
+
+ this.cert_alg_rsa = settings.getValueFromKey(RSA_CERT_ALG_KEY);
+
+ }
+
+ public String getProfile()
+ {
+ return this.profile;
+ }
+
+ /**
+ * Returns the sign key identifier.
+ *
+ * @return Returns the sign key identifier.
+ */
+ public String getSignKeyIdentifier()
+ {
+ return this.sign_key_identifier;
+ }
+
+ /**
+ * Returns the sign request template.
+ *
+ * @return Returns the sign request template.
+ */
+ public String getSignRequestTemplate()
+ {
+ return this.sign_request_template;
+ }
+
+ /**
+ * Returns the sign URL.
+ *
+ * @return Returns the sign URL.
+ */
+ public String getSignURL()
+ {
+ return this.sign_url;
+ }
+
+ /**
+ * Returns the verify request template.
+ *
+ * @return Returns the verify request template.
+ */
+ public String getVerifyRequestTemplate()
+ {
+ return this.verify_request_template;
+ }
+
+ /**
+ * Returns the verify template.
+ *
+ * @return Returns the verify template.
+ */
+ public String getVerifyTemplate()
+ {
+ return this.verify_template;
+ }
+
+ /**
+ * Returns the verify URL.
+ *
+ * @return Returns the verify URL.
+ */
+ public String getVerifyURL()
+ {
+ return this.verify_url;
+ }
+
+ /**
+ * Returns the verify trust profile id.
+ *
+ * @return Returns the verify trust profile id.
+ */
+ public String getVerifyTrustProfileId()
+ {
+ return this.verify_trust_profile_id;
+ }
+
+ /**
+ * Returns the ecdsa cert alg property.
+ *
+ * @return Returns the ecdsa cert alg property.
+ */
+ public String getCertAlgEcdsa()
+ {
+ return this.cert_alg_ecdsa;
+ }
+
+ /**
+ * Returns the rsa cert alg property.
+ *
+ * @return Returns the rsa cert alg property.
+ */
+ public String getCertAlgRsa()
+ {
+ return this.cert_alg_rsa;
+ }
+
+ /**
+ * Reads the configuration entry given by the key, first from the given
+ * profile, if not found from the defaults.
+ *
+ * @param settings
+ * The settings.
+ * @param profile
+ * The profile.
+ * @param key
+ * The configuration key.
+ * @return Returns the configuration entry.
+ */
+ public static String getConnectorValueFromProfile(SettingsReader settings,
+ String profile, String key)
+ {
+ String value = settings.getValueFromKey("sig_obj." + profile + "." + key); //$NON-NLS-1$//$NON-NLS-2$
+ if (value == null)
+ {
+ value = settings.getValueFromKey(key);
+ }
+ return value;
+ }
+
+ }
+
+ public XMLDsigData reconstructXMLDsig(SignatureData data, SignSignatureObject so)
+ throws ConnectorException {
+ String xmldsig = chooseAndCreateXMLDsig(data, so);
+ return new XMLDsigData(xmldsig, false);
+ }
+
+ private String chooseAndCreateXMLDsig(SignatureData data, SignSignatureObject so) throws ConnectorException {
+ if (!SigKZIDHelper.isMOASigned(so))
+ {
+ if (SigKZIDHelper.isOldBKU(so))
+ {
+ OldEnvelopingBase64BKUConnector bku_connector = new OldEnvelopingBase64BKUConnector(this.environment.getProfile());
+ return bku_connector.prepareXMLContent(data, so);
+ }
+ else
+ {
+ EnvelopedBase64BKUConnector bku_connector = new EnvelopedBase64BKUConnector(this.environment.getProfile());
+ return bku_connector.prepareXMLContent(data, so);
+ }
+ }
+ else
+ {
+ return prepareXMLContent(data, so);
+ }
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/FilePartMR.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/FilePartMR.java
new file mode 100644
index 0000000..b52b39b
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/FilePartMR.java
@@ -0,0 +1,152 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors.moa;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.commons.httpclient.methods.multipart.PartSource;
+import org.apache.commons.httpclient.util.EncodingUtil;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+public class FilePartMR extends
+ org.apache.commons.httpclient.methods.multipart.FilePart {
+
+ /** Log object for this class. */
+ private static final Log LOG = LogFactory.getLog(FilePartMR.class);
+
+ /** Content dispostion characters */
+ protected static final String CONTENT_ID = "Content-Id: ";
+
+ /** Content dispostion as a byte array */
+ protected static final byte[] CONTENT_ID_BYTES =
+ EncodingUtil.getAsciiBytes(CONTENT_ID);
+
+ private String contentID = "";
+
+ public FilePartMR(String arg0, PartSource arg1) {
+ super(arg0, arg1);
+ // TODO Auto-generated constructor stub
+ }
+
+ public FilePartMR(String arg0, File arg1) throws FileNotFoundException {
+ super(arg0, arg1);
+ // TODO Auto-generated constructor stub
+ }
+
+ public FilePartMR(String arg0, String arg1, File arg2)
+ throws FileNotFoundException {
+ super(arg0, arg1, arg2);
+ // TODO Auto-generated constructor stub
+ }
+
+ public FilePartMR(String arg0, PartSource arg1, String arg2, String arg3) {
+ super(arg0, arg1, arg2, arg3);
+ // TODO Auto-generated constructor stub
+ }
+
+ public FilePartMR(String arg0, File arg1, String arg2, String arg3)
+ throws FileNotFoundException {
+ super(arg0, arg1, arg2, arg3);
+ // TODO Auto-generated constructor stub
+ }
+
+ public FilePartMR(String arg0, String arg1, File arg2, String arg3,
+ String arg4) throws FileNotFoundException {
+ super(arg0, arg1, arg2, arg3, arg4);
+ // TODO Auto-generated constructor stub
+ }
+
+
+ public void setContentID(String contentid) {
+ this.contentID = contentid;
+ }
+
+ public String getContentID() {
+ return this.contentID;
+ }
+
+ /**
+ * Write the content id header to the specified output stream
+ *
+ * @param out The output stream
+ * @throws IOException If an IO problem occurs.
+ */
+ protected void sendContentIDHeader(OutputStream out) throws IOException {
+ LOG.trace("enter sendContendID instead of ContentDisposition(OutputStream out)");
+ out.write(CONTENT_ID_BYTES);
+ out.write(EncodingUtil.getAsciiBytes(getContentID()));
+ }
+
+ /**
+ * Write all the data to the output stream.
+ * If you override this method make sure to override
+ * #length() as well
+ *
+ * @param out The output stream
+ * @throws IOException If an IO problem occurs.
+ */
+ public void send(OutputStream out) throws IOException {
+ LOG.trace("enter send(OutputStream out)");
+ sendStart(out);
+
+ sendContentIDHeader(out);
+ sendContentTypeHeader(out);
+ sendTransferEncodingHeader(out);
+ sendEndOfHeader(out);
+ sendData(out);
+ sendEnd(out);
+ }
+
+
+ /**
+ * Return the full length of all the data.
+ * If you override this method make sure to override
+ * #send(OutputStream) as well
+ *
+ * @return long The length.
+ * @throws IOException If an IO problem occurs
+ */
+ public long length() throws IOException {
+ LOG.trace("enter length()");
+ if (lengthOfData() < 0) {
+ return -1;
+ }
+ ByteArrayOutputStream overhead = new ByteArrayOutputStream();
+ sendStart(overhead);
+
+ sendContentIDHeader(overhead);
+ sendContentTypeHeader(overhead);
+ sendTransferEncodingHeader(overhead);
+ sendEndOfHeader(overhead);
+ sendEnd(overhead);
+ return overhead.size() + lengthOfData();
+ }
+
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOAHelper.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOAHelper.java
new file mode 100644
index 0000000..8cb9a92
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOAHelper.java
@@ -0,0 +1,228 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors.moa;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmMapper;
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteObject;
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteUtil;
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
+import at.knowcenter.wag.egov.egiz.sig.SignatureObject;
+import at.knowcenter.wag.egov.egiz.sig.X509Cert;
+import at.knowcenter.wag.egov.egiz.sig.connectors.ConnectorEnvironment;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUHelper;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject;
+import at.knowcenter.wag.egov.egiz.sig.sigid.IdFormatter;
+import at.knowcenter.wag.egov.egiz.tools.CodingHelper;
+
+/**
+ * @author wprinz
+ *
+ */
+public class MOAHelper
+{
+ /**
+ * The log.
+ */
+ private static Log log = LogFactory.getLog(MOAHelper.class);
+
+ /**
+ * This method parses the MOA-Response string.
+ *
+ * <p>
+ * It separates the SignatureValue, X509IssuerName, SigningTime,
+ * X509SerialNumber, X509Certificate, CertDigest and DigestValues. If the
+ * X509Certificate is extracted it would be stored in the certificates
+ * directory.
+ * </p>
+ *
+ * @param xmlResponse
+ * the response string from the MOA sign-request
+ * @throws ConnectorException
+ * ErrorCode (303, 304)
+ * @see SignatureObject
+ * @see CodingHelper
+ * @see X509Cert
+ */
+ public static SignSignatureObject parseCreateXMLResponse(String xmlResponse, IdFormatter id_formatter, ConnectorEnvironment environment) throws ConnectorException
+ {
+ Pattern sig_val_p_s = Pattern.compile("<[\\w]*:?SignatureValue>"); //$NON-NLS-1$
+ Pattern sig_val_p_e = Pattern.compile("</[\\w]*:?SignatureValue>"); //$NON-NLS-1$
+ Pattern iss_nam_p_s = Pattern.compile("<[\\w]*:?X509IssuerName>"); //$NON-NLS-1$
+ Pattern iss_nam_p_e = Pattern.compile("</[\\w]*:?X509IssuerName>"); //$NON-NLS-1$
+ Pattern sig_tim_p_s = Pattern.compile("<[\\w]*:?SigningTime>"); //$NON-NLS-1$
+ Pattern sig_tim_p_e = Pattern.compile("</[\\w]*:?SigningTime>"); //$NON-NLS-1$
+ Pattern ser_num_p_s = Pattern.compile("<[\\w]*:?X509SerialNumber>"); //$NON-NLS-1$
+ Pattern ser_num_p_e = Pattern.compile("</[\\w]*:?X509SerialNumber>"); //$NON-NLS-1$
+ Pattern sig_cer_p_s = Pattern.compile("<[\\w]*:?X509Certificate>"); //$NON-NLS-1$
+ Pattern sig_cer_p_e = Pattern.compile("</[\\w]*:?X509Certificate>"); //$NON-NLS-1$
+
+ // Pattern sig_cer_d_p_s = Pattern.compile("<[\\w]*:?CertDigest>");
+ // //$NON-NLS-1$
+ // Pattern sig_cer_d_p_e = Pattern.compile("</[\\w]*:?CertDigest>");
+ // //$NON-NLS-1$
+ // Pattern dig_val_p_s = Pattern.compile("<[\\w]*:?DigestValue>");
+ // //$NON-NLS-1$
+ // Pattern dig_val_p_e = Pattern.compile("</[\\w]*:?DigestValue>");
+ // //$NON-NLS-1$
+
+ Matcher sig_val_m_s = sig_val_p_s.matcher(xmlResponse);
+ Matcher sig_val_m_e = sig_val_p_e.matcher(xmlResponse);
+ Matcher iss_nam_m_s = iss_nam_p_s.matcher(xmlResponse);
+ Matcher iss_nam_m_e = iss_nam_p_e.matcher(xmlResponse);
+ Matcher sig_tim_m_s = sig_tim_p_s.matcher(xmlResponse);
+ Matcher sig_tim_m_e = sig_tim_p_e.matcher(xmlResponse);
+ Matcher ser_num_m_s = ser_num_p_s.matcher(xmlResponse);
+ Matcher ser_num_m_e = ser_num_p_e.matcher(xmlResponse);
+ Matcher sig_cer_m_s = sig_cer_p_s.matcher(xmlResponse);
+ Matcher sig_cer_m_e = sig_cer_p_e.matcher(xmlResponse);
+
+ // Matcher sig_cer_d_m_s = sig_cer_d_p_s.matcher(xmlResponse);
+ // Matcher sig_cer_d_m_e = sig_cer_d_p_e.matcher(xmlResponse);
+ // Matcher dig_val_m_s = dig_val_p_s.matcher(xmlResponse);
+ // Matcher dig_val_m_e = dig_val_p_e.matcher(xmlResponse);
+
+ // SignatureValue
+ String sig_val = null;
+ if (sig_val_m_s.find() && sig_val_m_e.find())
+ {
+ sig_val = BKUHelper.removeAllWhitespace(xmlResponse.substring(sig_val_m_s.end(), sig_val_m_e.start()));
+ }
+ log.debug("sig_val = " + sig_val); //$NON-NLS-1$
+
+ // X509IssuerName
+ String iss_nam = null;
+ if (iss_nam_m_s.find() && iss_nam_m_e.find())
+ {
+ iss_nam = xmlResponse.substring(iss_nam_m_s.end(), iss_nam_m_e.start());
+ }
+ log.debug("iss_nam = " + iss_nam); //$NON-NLS-1$
+
+ // X509SerialNumber
+ String ser_num = null;
+ if (ser_num_m_s.find() && ser_num_m_e.find())
+ {
+ ser_num = BKUHelper.removeAllWhitespace(xmlResponse.substring(ser_num_m_s.end(), ser_num_m_e.start()));
+ }
+ log.debug("ser_num = " + ser_num); //$NON-NLS-1$
+
+ // SigningTime
+ String sig_tim = null;
+ if (sig_tim_m_s.find() && sig_tim_m_e.find())
+ {
+ sig_tim = xmlResponse.substring(sig_tim_m_s.end(), sig_tim_m_e.start());
+ }
+ log.debug("sig_tim = " + sig_tim); //$NON-NLS-1$
+
+ // CertDigest
+ // if (sig_cer_d_m_s.find() && sig_cer_d_m_e.find())
+ // {
+ // String cert_digest = xmlResponse.substring(sig_cer_d_m_s.end(),
+ // sig_cer_d_m_e.start());
+ // if (dig_val_m_s.find() && dig_val_m_e.find())
+ // {
+ // sig_dig = cert_digest.substring(dig_val_m_s.end(), dig_val_m_e.start());
+ // //sigObj.setX509CertificateDigest(sig_dig);
+ // }
+ // }
+
+ // X509Certificate
+ X509Certificate cert = null;
+ if (sig_cer_m_s.find() && sig_cer_m_e.find())
+ {
+ String sig_cer = BKUHelper.removeAllWhitespace(xmlResponse.substring(sig_cer_m_s.end(), sig_cer_m_e.start()));
+
+ try
+ {
+ byte[] der = CodingHelper.decodeBase64(sig_cer);
+ ByteArrayInputStream bais = new ByteArrayInputStream(der);
+ CertificateFactory cf = CertificateFactory.getInstance("X.509"); //$NON-NLS-1$
+ cert = (X509Certificate) cf.generateCertificate(bais);
+ bais.close();
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ log.error(e);
+ throw new ConnectorException(300, e);
+ }
+ catch (CertificateException e)
+ {
+ log.error(e);
+ throw new ConnectorException(300, e);
+ }
+ catch (IOException e)
+ {
+ log.error(e);
+ throw new ConnectorException(300, e);
+ }
+ }
+ log.debug("X509Certificate = " + cert); //$NON-NLS-1$
+
+ if (log.isDebugEnabled())
+ {
+
+ String cert_iss = cert.getIssuerDN().getName();
+ log.debug("certificate's issuer = " + cert_iss); //$NON-NLS-1$
+ log.debug("response's issuer = " + iss_nam); //$NON-NLS-1$
+ log.debug("issuer matches = " + cert_iss.equals(iss_nam)); //$NON-NLS-1$
+ log.debug("ser number matches = " + cert.getSerialNumber().toString().equals(ser_num)); //$NON-NLS-1$
+ }
+
+ SignSignatureObject so = new SignSignatureObject();
+ so.date = sig_tim;
+ so.issuer = iss_nam;
+ so.signatureValue = sig_val;
+ so.x509Certificate = cert;
+
+ String algs = AlgorithmSuiteUtil.extractAlgorithmSuiteString(xmlResponse);
+
+ AlgorithmSuiteObject suite = new AlgorithmSuiteObject(algs, false);
+ so.sigAlgorithm = AlgorithmMapper.getUri(suite.getSignatureMethod());
+
+ String defaultCertAlg = environment.getDefaultAlgForCert(cert);
+
+ if (AlgorithmSuiteUtil.isDefaultCertAlg(algs, defaultCertAlg)) {
+ // do not embed default alg
+ algs = null;
+ }
+
+
+
+ so.id = id_formatter.formatIds(null, algs);
+
+ return so;
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapConnection.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapConnection.java
new file mode 100644
index 0000000..7aa3d7b
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapConnection.java
@@ -0,0 +1,277 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors.moa;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+import java.util.Vector;
+
+import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.rpc.Call;
+import javax.xml.rpc.Service;
+import javax.xml.rpc.ServiceFactory;
+
+import org.apache.axis.message.SOAPBodyElement;
+import org.apache.commons.httpclient.Header;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpException;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.methods.multipart.FilePart;
+import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
+import org.apache.commons.httpclient.methods.multipart.Part;
+import org.apache.commons.httpclient.methods.multipart.PartSource;
+import org.apache.commons.httpclient.methods.multipart.StringPart;
+import org.apache.commons.httpclient.params.HttpMethodParams;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.xml.serialize.OutputFormat;
+import org.apache.xml.serialize.XMLSerializer;
+import org.w3c.dom.Document;
+
+import at.knowcenter.wag.egov.egiz.exceptions.WebException;
+import at.knowcenter.wag.egov.egiz.sig.SignatureData;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUPostConnection;
+
+/**
+ * @author wprinz
+ *
+ */
+public final class MOASoapConnection
+{
+ /**
+ * MOA siganture verification mode
+ */
+ public static final String SERVICE_VERIFY = "SignatureVerification"; //$NON-NLS-1$
+
+ /**
+ * MOA siganture creation mode
+ */
+ public static final String SERVICE_SIGN = "SignatureCreation"; //$NON-NLS-1$
+
+ /**
+ * The log.
+ */
+ private static Log log = LogFactory.getLog(MOASoapConnection.class);
+
+ /**
+ * This method connects the moa server getting the requestString, the given
+ * serviseMode and the endpointUrl. The requestString is the envelope of the
+ * SOAP Message send and recieve by the AXIS module. The Response SOAP message
+ * of the MOA server is parsed by AXIS and the message envelope is send back
+ * to the calling method.
+ *
+ * @param requestString
+ * the request string (XML) to send.
+ * @param serviceMode
+ * the mode which connect to MOA
+ * @param endpointURL
+ * the URL which the MOA server is running
+ * @return the response string (XML) of the MOA server
+ * @throws WebException
+ */
+ public static Properties connectMOA(String requestString, String serviceMode,
+ String endpointURL) throws WebException
+ {
+ try
+ {
+ if (log.isDebugEnabled())
+ {
+ log.debug(serviceMode);
+ log.debug(endpointURL);
+ }
+ // Parser/DOMBuilder instanzieren
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setNamespaceAware(true);
+ DocumentBuilder builder = factory.newDocumentBuilder();
+
+ // XML Datei in einen DOM-Baum umwandeln
+ ByteArrayInputStream bais = new ByteArrayInputStream(requestString.getBytes("UTF-8")); //$NON-NLS-1$
+ Document xmlRequest = builder.parse(bais);
+
+ // Call öffnen
+ Call call = null;
+
+ // Neues BodyElement anlegen und mit dem DOM-Baum füllen
+ SOAPBodyElement body = new SOAPBodyElement(xmlRequest.getDocumentElement());
+ SOAPBodyElement[] params = new SOAPBodyElement[] { body };
+
+ // AXIS-Server instanzieren
+ Service service = ServiceFactory.newInstance().createService(new QName(serviceMode));
+ call = service.createCall();
+ call.setTargetEndpointAddress(endpointURL);
+
+ // Call auslösen und die Antworten speichern
+ log.debug("Calling MOA: " + endpointURL); //$NON-NLS-1$
+ Vector responses = (Vector) call.invoke(params);
+
+ // Erstes Body Element auslesen
+ SOAPBodyElement response = (SOAPBodyElement) responses.get(0);
+
+ // Aus der Response den DOM-Baum lesen
+ Document root_response = response.getAsDocument();
+ log.debug("Return from MOA: " + serviceMode); //$NON-NLS-1$
+
+ // XML-Formatierung konfiguieren
+ OutputFormat format = new OutputFormat((Document) root_response);
+ format.setLineSeparator("\n"); //$NON-NLS-1$
+ format.setIndenting(false);
+ format.setPreserveSpace(true);
+ format.setOmitXMLDeclaration(false);
+ format.setEncoding("UTF-8"); //$NON-NLS-1$
+
+ // Ausgabe der Webservice-Antwort auf die Konsole
+ // XMLSerializer conSerializer = new XMLSerializer(System.out, format);
+ // conSerializer.serialize(root_response);
+
+ // Ausgabe der Webservice-Antwort in Datei
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ XMLSerializer response_serializer = new XMLSerializer(baos, format);
+ response_serializer.serialize(root_response);
+ String response_string = baos.toString("UTF-8"); //$NON-NLS-1$
+
+ Properties response_properties = new Properties();
+ response_properties.setProperty(BKUPostConnection.RESPONSE_STRING_KEY, response_string);
+
+ return response_properties;
+ }
+ catch (Exception e)
+ {
+ throw new WebException(e);
+ }
+ // serialize signature only
+
+ // if
+ // (root_response.getDocumentElement().getLocalName().equals("CreateXMLSignatureResponse"))
+ // {
+ // Element signature = (Element)
+ // root_response.getElementsByTagNameNS("http://www.w3.org/2000/09/xmldsig#",
+ // "Signature").item(0);
+ // String signatureFile = getProperty(mode + "Request").substring(0,
+ // getProperty(mode +
+ // "Request").lastIndexOf('.')) + ".Signature.xml";
+ // fileSerializer = new XMLSerializer(new FileOutputStream(signatureFile),
+ // format);
+ // fileSerializer.serialize(signature);
+ // }
+
+ }
+
+ public static Properties doPostRequestMultipart(String url, String serviceMode, String request,
+ final SignatureData data) throws HttpException, IOException
+ {
+ log.debug("doPostRequestMultipart:"); //$NON-NLS-1$
+
+ // Wrap XMLRequest into SOAP-Body
+ request = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><soapenv:Body>" +
+ request.substring(request.indexOf("?>")+2)+ // do not forget to eliminate any additional XML-header
+ "</soapenv:Body></soapenv:Envelope>";
+
+ StringPartMR xmlpart = new StringPartMR("test", request, "UTF-8"); //$NON-NLS-1$//$NON-NLS-2$
+ xmlpart.setContentType("text/xml");
+ xmlpart.setContentID("<xmlrequest>");
+
+ // add file to be signed
+ final String filename = data.getMimeType().equals("application/pdf") ? "myfile.pdf" : "myfile.txt"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ PartSource ps = new PartSource() {
+ public InputStream createInputStream() throws IOException
+ {
+ return data.getDataSource().createInputStream();
+ }
+
+ public String getFileName()
+ {
+ return filename;
+ }
+
+ public long getLength()
+ {
+ return data.getDataSource().getLength();
+ }
+ };
+ //ByteArrayPartSource baps = new ByteArrayPartSource(filename, data.getData());
+ FilePartMR filepart = new FilePartMR("fileupload", ps); //$NON-NLS-1$
+ filepart.setContentType(data.getMimeType());
+ filepart.setContentID("<fileupload>");
+
+ // not really needed since external referenced data has to be taken "as-is" (binary stream) for
+ // digest calculation, so neither content type nor charset is relevant
+ filepart.setCharSet(data.getCharacterEncoding());
+
+ Part[] parts = { xmlpart, filepart };
+
+ HttpMethodParams method_params = new HttpMethodParams();
+ method_params.setContentCharset("UTF-8"); //$NON-NLS-1$
+
+ PostMethod post_method = new PostMethod(url);
+ post_method.setParams(method_params);
+
+
+ post_method.addRequestHeader("SOAPAction",serviceMode);
+
+// MultipartRequestEntity mprqe = new MultipartRequestEntity(parts, post_method.getParams());
+ MultipartRelatedEntity mprqe = new MultipartRelatedEntity(parts, post_method.getParams());
+ mprqe.setContentType("text/xml");
+ mprqe.setStartID("<xmlrequest>");
+
+ post_method.setRequestEntity(mprqe);
+ // post_method.setRequestHeader("Content-Type", "multipart/related; type=\"text/xml\"; boundary=\""+"\"");
+ HttpClient http_client = new HttpClient();
+
+ int method_response = http_client.executeMethod(post_method);
+ log.debug("method_response = " + method_response); //$NON-NLS-1$
+
+ Properties response_properties = new Properties();
+
+ if (log.isDebugEnabled())
+ {
+ Header[] response_headers = post_method.getResponseHeaders();
+ for (int i = 0; i < response_headers.length; i++)
+ {
+ log.debug(" response_header[" + i + "]: name = " + response_headers[i].getName() + ", value = " + response_headers[i].getValue()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+ }
+ Header server_header = post_method.getResponseHeader("Server"); //$NON-NLS-1$
+
+ response_properties.setProperty(BKUPostConnection.RESPONSE_STRING_KEY, server_header.getValue());
+
+ String charset = post_method.getResponseCharSet();
+ log.debug("MOA response charset is \"" + charset + "\"");
+ if (!"UTF-8".equalsIgnoreCase(charset) && !"UTF8".equalsIgnoreCase(charset)) //$NON-NLS-1$
+ {
+ log.warn("MOA response charset is not UTF-8!"); //$NON-NLS-1$
+ }
+ String response_string = post_method.getResponseBodyAsString();
+
+ response_properties.setProperty(BKUPostConnection.RESPONSE_STRING_KEY, response_string);
+
+ log.debug("doPostRequestMultipart finished."); //$NON-NLS-1$
+ return response_properties;
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapWithAttachmentConnector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapWithAttachmentConnector.java
new file mode 100644
index 0000000..db0a04f
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapWithAttachmentConnector.java
@@ -0,0 +1,745 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors.moa;
+
+import java.security.cert.X509Certificate;
+import java.util.Properties;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteObject;
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteUtil;
+import at.gv.egiz.pdfas.api.xmldsig.XMLDsigData;
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.gv.egiz.pdfas.framework.ConnectorParameters;
+import at.knowcenter.wag.egov.egiz.PdfAS;
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
+import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
+import at.knowcenter.wag.egov.egiz.sig.SignatureData;
+import at.knowcenter.wag.egov.egiz.sig.SignatureResponse;
+import at.knowcenter.wag.egov.egiz.sig.connectors.Connector;
+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.BKUHelper;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUPostConnection;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.DetachedBKUConnector;
+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.DetachedLocRefMOAIdFormatter;
+import at.knowcenter.wag.egov.egiz.sig.sigkz.SigKZIDHelper;
+import at.knowcenter.wag.egov.egiz.tools.CodingHelper;
+
+/**
+ * Connects to MOA providing the Data detached as LocRef on a local resource.
+ *
+ * @author wprinz
+ */
+public class MOASoapWithAttachmentConnector implements Connector
+{
+ //23.11.2010 changed by exthex - added reconstructXMLDsig method and moved xmldsig creation to chooseAndCreateXMLDsig method
+ public static final String ATRUST_VERIFY_TEMPLATE_KEY = "atrust.verify.template.detached";
+
+/**
+ * The SIG_ID prefix.
+ */
+ // public static final String SIG_ID_PREFIX = "etsi-bku-detached@"; //$NON-NLS-1$
+ /**
+ * The log.
+ */
+ private static Log log = LogFactory.getLog(MOASoapWithAttachmentConnector.class);
+
+ protected static final String MULTIPART_LOC_REF_CONTENT = "formdata:fileupload"; //$NON-NLS-1$
+
+ protected static final String RETURN_HASH_INPUT_DATA = "<ReturnHashInputData/>"; //$NON-NLS-1$
+
+ /**
+ * The connector parameters.
+ */
+ protected ConnectorParameters params = null;
+
+ /**
+ * The environemnt configuration of this connector containing templates and
+ * other configurable elements.
+ */
+ protected Environment environment = null;
+
+
+ /**
+ * Constructor that builds the configuration environment for this connector
+ * according to the given profile.
+ *
+ * <p>
+ * If confuguration parameters are not defined on that profile, the default
+ * parameters defined in the configuration are used.
+ * </p>
+ *
+ * @param connectorParameters
+ * The parameters for this connector.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public MOASoapWithAttachmentConnector(ConnectorParameters connectorParameters) throws ConnectorException
+ {
+ this.params = connectorParameters;
+ this.environment = new Environment(this.params.getProfileId(), this.params.getSignatureKeyIdentifier(), MULTIPART_LOC_REF_CONTENT);
+ }
+
+ protected String prepareSignRequest(SignatureData data) throws ConnectorException
+ {
+ log.debug("prepareSignRequestDetached:"); //$NON-NLS-1$
+
+ String sign_request_template = this.environment.getSignRequestTemplate();
+
+ String sign_key_identifier = this.environment.getSignKeyIdentifier();
+ String loc_ref_content = this.environment.getSignatureDataUrl();
+ String mime_type = data.getMimeType();
+ if (log.isDebugEnabled())
+ {
+ log.debug("sign keybox identifier = " + sign_key_identifier); //$NON-NLS-1$
+ log.debug("LocRefContent = " + loc_ref_content); //$NON-NLS-1$
+ log.debug("mime type = " + mime_type); //$NON-NLS-1$
+ }
+
+ String sign_request_xml = sign_request_template.replaceFirst(TemplateReplaces.KEY_IDENTIFIER_REPLACE, sign_key_identifier);
+ sign_request_xml = sign_request_xml.replaceFirst(TemplateReplaces.LOC_REF_CONTENT_REPLACE, loc_ref_content);
+ sign_request_xml = sign_request_xml.replaceFirst(TemplateReplaces.MIME_TYPE_REPLACE, mime_type);
+
+ log.debug("prepareSignRequestDetached finished."); //$NON-NLS-1$
+ return sign_request_xml;
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.connectors.LocalConnector#analyzeSignResponse(java.util.Properties)
+ */
+ public SignSignatureObject analyzeSignResponse(Properties response_properties) throws ConnectorException
+ {
+ log.debug("analyzeSignResponse:"); //$NON-NLS-1$
+
+ String response_string = response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY);
+
+ BKUHelper.checkResponseForError(response_string);
+
+ SignSignatureObject so = MOAHelper.parseCreateXMLResponse(response_string, new DetachedLocRefMOAIdFormatter(), this.environment);
+
+ log.debug("analyzeSignResponse finished."); //$NON-NLS-1$
+ return so;
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.connectors.Connector#doSign(at.knowcenter.wag.egov.egiz.sig.SignatureData)
+ */
+ public SignSignatureObject doSign(SignatureData data) throws ConnectorException
+ {
+ log.debug("doSign:"); //$NON-NLS-1$
+
+ String sign_request_xml = prepareSignRequest(data);
+// DebugHelper.debugStringToFile(sign_request_xml, "MOA_DetLocRef_sign_request.xml"); //$NON-NLS-1$
+
+ String url = this.environment.getSignURL();
+ Properties response_properties = sendRequest(url, MOASoapConnection.SERVICE_SIGN, sign_request_xml, data);
+
+// DebugHelper.debugStringToFile(response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY), "MOA_DetLocRef_sign_response.xml"); //$NON-NLS-1$
+ SignSignatureObject sso = analyzeSignResponse(response_properties);
+
+ sso.response_properties = response_properties;
+
+ log.debug("doSign finished."); //$NON-NLS-1$
+ return sso;
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.connectors.Connector#doVerify(at.knowcenter.wag.egov.egiz.sig.SignatureData,
+ * at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject)
+ */
+ public SignatureResponse doVerify(SignatureData data, SignSignatureObject so, XMLDsigData dsig) throws ConnectorException
+ {
+ log.debug("doVerify:"); //$NON-NLS-1$
+
+ String verify_request_xml = prepareVerifyRequest(data, so, dsig);
+ log.debug("verify_request_xml = " + verify_request_xml); //$NON-NLS-1$
+
+ String url = this.environment.getVerifyURL();
+ Properties response_properties = sendRequest(url, MOASoapConnection.SERVICE_VERIFY, verify_request_xml, data);
+
+ SignatureResponse signature_response = analyzeVerifyResponse(response_properties);
+
+ log.debug("doVerify finished."); //$NON-NLS-1$
+ return signature_response;
+ }
+
+ /**
+ * Prepares the verify request xml to be sent using the verify request
+ * template.
+ *
+ * @param data
+ * The SignatureData.
+ * @param so
+ * The signature information object.
+ * @return Returns the verify request xml to be sent.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public String prepareVerifyRequest(SignatureData data, SignSignatureObject so, XMLDsigData dsigData) throws ConnectorException
+ {
+ String verify_request_template = this.environment.getVerifyRequestTemplate();
+
+ String xml_content = null;
+ if (dsigData != null && dsigData.getXmlDsig() != null)
+ {
+ xml_content = dsigData.getXmlDsig();
+ }
+ else
+ {
+ xml_content = chooseAndCreateXMLDsig(data, so);
+ }
+
+ String verify_request_xml = verify_request_template.replaceFirst(TemplateReplaces.XML_CONTENT_REPLACE, xml_content);
+ verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.TRUST_PROFILE_ID_REPLACE, this.environment.getVerifyTrustProfileId());
+ verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.LOC_REF_CONTENT_REPLACE, this.environment.getSignatureDataUrl());
+
+ String returnHashInputDataElement = "";
+ if (this.params.isReturnHashInputData())
+ {
+ returnHashInputDataElement = RETURN_HASH_INPUT_DATA;
+ }
+ verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.RETURN_HASH_INPUT_DATA_REPLACE, returnHashInputDataElement);
+
+ verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.DATE_TIME_REPLACE, BKUHelper.formDateTimeElement(this.params.getVerificationTime()));
+
+
+ log.debug("\r\n\r\n" + verify_request_xml + "\r\n\r\n");
+
+ return verify_request_xml;
+ }
+
+ private String chooseAndCreateXMLDsig(SignatureData data, SignSignatureObject so) throws ConnectorException {
+
+ // MOA
+ if (SigKZIDHelper.isMOASigned(so)) {
+ log.debug("MOA signature detected.");
+ return prepareXMLContent(data, so);
+
+ // MOCCA
+ } else if (SigKZIDHelper.isMOCCASigned(so)) {
+ log.debug("MOCCA signature detected.");
+ String algorithmId = SigKZIDHelper.parseAlgorithmId(so.id);
+ log.debug("Algorithm = " + algorithmId);
+ LocRefDetachedMOCCAConnector mocca_connector = new LocRefDetachedMOCCAConnector(this.params, "not needed here", algorithmId);
+ return mocca_connector.prepareXMLContent(data, so);
+
+ // ATrust
+ } else if (SigKZIDHelper.isATrustSigned(so)) {
+ log.debug("A-Trust signature detected.");
+ this.environment.reInitVerifyTemplate(ATRUST_VERIFY_TEMPLATE_KEY);
+ return prepareXMLContent(data, so);
+
+ // TD bku
+ } else if (SigKZIDHelper.isBKUSigned(so)) {
+ log.debug("TD bku signature detected.");
+ DetachedBKUConnector bku_connector = new DetachedBKUConnector(this.params, "not needed here");
+ return bku_connector.prepareXMLContent(data, so);
+ } else {
+ throw new ConnectorException(ErrorCode.UNSUPPORTED_SIGNATURE, "Unsupported signature (" + so.id + ", " +so.kz + "). Please get a new version of PDF-AS. Your version is: " + PdfAS.PDFAS_VERSION);
+
+ }
+ }
+
+ /**
+ * Analyzes the verify response string.
+ *
+ * @param response_properties
+ * The response properties containing the response XML.
+ * @return Returns the SignatureResponse containing the verification result.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public SignatureResponse analyzeVerifyResponse(Properties response_properties) throws ConnectorException
+ {
+ log.debug("analyzeVerifyResponse:"); //$NON-NLS-1$
+
+ String response_string = response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY);
+
+ BKUHelper.checkResponseForError(response_string);
+
+ SignatureResponse signature_response = BKUHelper.parseVerifyXMLResponse(response_string);
+
+ log.debug("analyzeVerifyResponse finished."); //$NON-NLS-1$
+ return signature_response;
+ }
+
+ public String prepareXMLContent(SignatureData data, SignSignatureObject so) throws ConnectorException
+ {
+ log.debug("prepareXMLContent:"); //$NON-NLS-1$
+ try
+ {
+
+ String verify_xml = null;
+ X509Certificate cert = so.getX509Certificate();
+
+ // dferbas
+ AlgorithmSuiteObject algSuite = new AlgorithmSuiteObject();
+ verify_xml = AlgorithmSuiteUtil.evaluateReplaceAlgs(algSuite, this.environment, so);
+
+
+ // data digest replace
+ {
+// byte[] data_value = data.getData();
+// byte[] data_value_hash = CodingHelper.buildDigest(data_value);
+ byte[] data_value_hash = CodingHelper.buildDigest(data.getDataSource(), algSuite.getDataDigestMethod());
+ String object_data_hash = CodingHelper.encodeBase64(data_value_hash);
+
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_SIGNED_DATA_REPLACE, object_data_hash);
+ }
+
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.SIGNATURE_VALUE_REPLACE, so.getSignatureValue());
+
+ // X.509 Certificate replace
+ byte[] der = cert.getEncoded();
+ byte[] cert_hash = CodingHelper.buildDigest(der, algSuite.getCertDigestMethod());
+ String certDigest = CodingHelper.encodeBase64(cert_hash);
+ String x509_cert_string = CodingHelper.encodeBase64(der);
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_CERTIFICATE_REPLACE, x509_cert_string);
+
+ // Qualified Properties replaces
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.SIGNING_TIME_REPLACE, so.getDate());
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_CERTIFICATE_REPLACE, certDigest);
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_ISSUER_NAME_REPLACE, so.getIssuer());
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_SERIAL_NUMBER_REPLACE, so.getSerialNumber());
+ // SigDataRefReplace already done above
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.MIME_TYPE_REPLACE, data.getMimeType());
+
+ // Signed Properties hash
+ {
+ final String ETSI_SIGNED_PROPERTIES_START_TAG = "<etsi:SignedProperties"; //$NON-NLS-1$
+ final String ETSI_SIGNED_PROPERTIES_END_TAG = "</etsi:SignedProperties>"; //$NON-NLS-1$
+
+ final int hash_start = verify_xml.indexOf(ETSI_SIGNED_PROPERTIES_START_TAG);
+ assert hash_start >= 0;
+ final int hash_end = verify_xml.indexOf(ETSI_SIGNED_PROPERTIES_END_TAG, hash_start) + ETSI_SIGNED_PROPERTIES_END_TAG.length();
+ assert hash_end - ETSI_SIGNED_PROPERTIES_END_TAG.length() >= 0;
+ assert hash_end > hash_start;
+
+ final String string_to_be_hashed = verify_xml.substring(hash_start, hash_end);
+ log.debug("etsi:SignedProperties string to be hashed: " + string_to_be_hashed); //$NON-NLS-1$
+
+ final byte[] bytes_to_be_hashed = string_to_be_hashed.getBytes("UTF-8"); //$NON-NLS-1$
+ byte[] sig_prop_code = CodingHelper.buildDigest(bytes_to_be_hashed, algSuite.getPropertiesDigestMethod());
+ String sig_prop_hash = CodingHelper.encodeBase64(sig_prop_code);
+
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_SIGNED_PROPERTIES_REPLACE, sig_prop_hash);
+ }
+
+ log.debug("prepareXMLContent finished."); //$NON-NLS-1$
+ return verify_xml;
+ }
+ catch (Exception e)
+ {
+ log.debug(e);
+ throw new ConnectorException(310, e);
+ }
+ }
+
+
+ protected Properties sendRequest(String url, String mode, String request_string, SignatureData data) throws ConnectorException
+ {
+ try
+ {
+ // for performance measurement
+// long startTime = 0;
+// if (log.isInfoEnabled()) {
+// startTime = System.currentTimeMillis();
+// }
+
+// Properties response_properties = MOASoapConnection.connectMOA(request_string, MOASoapConnection.SERVICE_SIGN, url);
+ log.debug("Connecting to " + url);
+ Properties response_properties = MOASoapConnection.doPostRequestMultipart(url,mode, request_string, data );
+
+ // for performance measurement
+// if (log.isInfoEnabled()) {
+// long endTime = System.currentTimeMillis();
+// String toReport = "MOA-PROCESSING;-;-;" + (endTime - startTime) + ";";
+// log.info(toReport);
+// }
+
+ return response_properties;
+ }
+ catch (Exception e)
+ {
+ throw new ConnectorException(330, e);
+ }
+ }
+
+ public void reInitVerifyTemplate(String templatePropKey) throws ConnectorException {
+ this.environment.reInitVerifyTemplate(templatePropKey);
+ }
+
+ /**
+ * Holds environment configuration information like templates.
+ *
+ * @author wprinz
+ */
+ public static class Environment extends ConnectorEnvironment
+ {
+ /**
+ * The configuration key of the sign keybox identifier.
+ */
+ protected static final String SIGN_KEY_IDENTIFIER_KEY = "moa.sign.KeyIdentifier"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the sign request template.
+ */
+ protected static final String SIGN_REQUEST_TEMPLATE_KEY = "moa.sign.request.detached"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the sign URL.
+ */
+ protected static final String SIGN_URL_KEY = "moa.sign.url"; //$NON-NLS-1$
+
+ /**
+ * MOA template file prefix
+ */
+ protected static final String TEMPLATE_FILE_PREFIX = "/templates/moa.";
+
+ /**
+ * signing file template sufix
+ */
+ protected static final String SIGN_TEMPLATE_FILE_SUFIX = ".sign.xml";
+
+ /**
+ * verifing template file sufix
+ */
+ protected static final String VERIFY_REQUEST_TEMPLATE_FILE_SUFIX = ".verify.request.xml";
+
+ /**
+ * verifing file template key sufix
+ */
+ protected static final String VERIFY_TEMPLATE_SUFIX = ".verify.template.xml";
+
+ /**
+ * The configuration key of the verify request template.
+ */
+ protected static final String VERIFY_REQUEST_TEMPLATE_KEY = "moa.verify.request.detached"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the verify template.
+ */
+ protected static final String VERIFY_TEMPLATE_KEY = "moa.verify.template.detached"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the verify URL.
+ */
+ protected static final String VERIFY_URL_KEY = "moa.verify.url"; //$NON-NLS-1$
+
+ /**
+ * The configuration key of the trust profile id.
+ */
+ protected static final String VERIFY_TRUST_PROFILE_ID = "moa.verify.TrustProfileID"; //$NON-NLS-1$
+
+ /**
+ * The configuration key for the ECDSA cert alg property.
+ */
+ protected static final String ECDSA_CERT_ALG_KEY = "cert.alg.ecdsa"; //$NON-NLS-1$
+
+ /**
+ * The configuration key for the RSA cert alg property.
+ */
+ protected static final String RSA_CERT_ALG_KEY = "cert.alg.rsa"; //$NON-NLS-1$
+
+ protected String profile = null;
+
+ protected String signature_data_url = null;
+
+ protected String sign_key_identifier = null;
+
+ protected String sign_request_template = null;
+
+ protected String sign_url = null;
+
+ protected String verify_request_template = null;
+
+ protected String verify_template = null;
+
+ protected String verify_url = null;
+
+ protected String verify_trust_profile_id = null;
+
+ protected String cert_alg_ecdsa = null;
+
+ protected String cert_alg_rsa = null;
+
+
+ public void reInitVerifyTemplate(String templatePropKey) throws ConnectorException {
+ SettingsReader settings = null;
+ try
+ {
+ settings = SettingsReader.getInstance();
+ }
+ catch (SettingsException e)
+ {
+ throw new ConnectorException(300, e);
+ }
+
+ String verify_request_filename = getConnectorValueFromProfile(settings, this.profile, templatePropKey);
+ this.verify_template = settings.readInternalResourceAsString(verify_request_filename);
+
+ }
+ /**
+ * Initializes the environment with a given profile.
+ *
+ * @param profile
+ * The configuration profile.
+ * @throws SettingsException
+ * f.e.
+ * @throws ConnectorException
+ * f.e.
+ */
+ public Environment(String profile, String signKeyIdentifier, String signature_data_url) throws ConnectorException
+ {
+ this.profile = profile;
+
+ this.signature_data_url = signature_data_url;
+
+ SettingsReader settings = null;
+ try
+ {
+ settings = SettingsReader.getInstance();
+ }
+ catch (SettingsException e)
+ {
+ throw new ConnectorException(300, e);
+ }
+
+ if (signKeyIdentifier != null)
+ {
+ this.sign_key_identifier = signKeyIdentifier;
+ }
+ else
+ {
+ this.sign_key_identifier = getConnectorValueFromProfile(settings, profile, SIGN_KEY_IDENTIFIER_KEY);
+ }
+
+ String sign_request_filename = TEMPLATE_FILE_PREFIX + settings.getValueFromKey("default.moa.algorithm.id") + SIGN_TEMPLATE_FILE_SUFIX;
+
+ // try to load template from file
+ //this.sign_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename));
+ this.sign_request_template = settings.readInternalResourceAsString(sign_request_filename);
+
+ if (this.sign_request_template == null)
+ {
+ sign_request_filename = getConnectorValueFromProfile(settings, profile, SIGN_REQUEST_TEMPLATE_KEY);
+ this.sign_request_template = settings.readInternalResourceAsString(sign_request_filename);
+ //this.sign_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename));
+ }
+
+ //this.sign_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename));
+ if (this.sign_request_template == null)
+ {
+ throw new ConnectorException(ErrorCode.SETTING_NOT_FOUND, "Can not read the create xml request template"); //$NON-NLS-1$
+ }
+
+ this.sign_url = getConnectorValueFromProfile(settings, profile, SIGN_URL_KEY);
+
+ String verify_request_filename = TEMPLATE_FILE_PREFIX + settings.getValueFromKey("default.moa.algorithm.id") + VERIFY_REQUEST_TEMPLATE_FILE_SUFIX;
+
+ // try to load template file for verifing
+ //this.verify_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_request_filename));
+ this.verify_request_template = settings.readInternalResourceAsString(verify_request_filename);
+
+ if (this.verify_request_template == null)
+ {
+ verify_request_filename = getConnectorValueFromProfile(settings, profile, VERIFY_REQUEST_TEMPLATE_KEY);
+ //this.verify_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_request_filename));
+ this.verify_request_template = settings.readInternalResourceAsString(verify_request_filename);
+ }
+
+ if (this.verify_request_template == null)
+ {
+ throw new ConnectorException(ErrorCode.SETTING_NOT_FOUND, "Can not read the verify xml request template"); //$NON-NLS-1$
+ }
+
+ // load template key file
+ String verify_filename = TEMPLATE_FILE_PREFIX + settings.getValueFromKey("default.moa.algorithm.id") + VERIFY_TEMPLATE_SUFIX;
+ //this.verify_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_filename));
+ this.verify_template = settings.readInternalResourceAsString(verify_filename);
+
+ if (this.verify_template == null)
+ {
+ verify_filename = getConnectorValueFromProfile(settings, profile, VERIFY_TEMPLATE_KEY);
+ //this.verify_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_filename));
+ this.verify_template = settings.readInternalResourceAsString(verify_filename);
+ }
+
+ if (this.verify_template == null)
+ {
+ throw new ConnectorException(ErrorCode.SETTING_NOT_FOUND, "Can not read the verify template"); //$NON-NLS-1$
+ }
+
+ this.verify_url = getConnectorValueFromProfile(settings, profile, VERIFY_URL_KEY);
+
+ this.verify_trust_profile_id = settings.getValueFromKey(VERIFY_TRUST_PROFILE_ID);
+
+ this.cert_alg_ecdsa = settings.getValueFromKey(ECDSA_CERT_ALG_KEY);
+
+ this.cert_alg_rsa = settings.getValueFromKey(RSA_CERT_ALG_KEY);
+
+ }
+
+ public String getProfile()
+ {
+ return this.profile;
+ }
+
+ /**
+ * Returns the URL where to load the detached data from.
+ *
+ * @return Returns the URL where to load the detached data from.
+ */
+ public String getSignatureDataUrl()
+ {
+ return this.signature_data_url;
+ }
+
+ /**
+ * Returns the sign key identifier.
+ *
+ * @return Returns the sign key identifier.
+ */
+ public String getSignKeyIdentifier()
+ {
+ return this.sign_key_identifier;
+ }
+
+ /**
+ * Returns the sign request template.
+ *
+ * @return Returns the sign request template.
+ */
+ public String getSignRequestTemplate()
+ {
+ return this.sign_request_template;
+ }
+
+ /**
+ * Returns the sign URL.
+ *
+ * @return Returns the sign URL.
+ */
+ public String getSignURL()
+ {
+ return this.sign_url;
+ }
+
+ /**
+ * Returns the verify request template.
+ *
+ * @return Returns the verify request template.
+ */
+ public String getVerifyRequestTemplate()
+ {
+ return this.verify_request_template;
+ }
+
+ /**
+ * Returns the verify template.
+ *
+ * @return Returns the verify template.
+ */
+ public String getVerifyTemplate()
+ {
+ return this.verify_template;
+ }
+
+ /**
+ * Returns the verify URL.
+ *
+ * @return Returns the verify URL.
+ */
+ public String getVerifyURL()
+ {
+ return this.verify_url;
+ }
+
+ /**
+ * Returns the verify trust profile id.
+ *
+ * @return Returns the verify trust profile id.
+ */
+ public String getVerifyTrustProfileId()
+ {
+ return this.verify_trust_profile_id;
+ }
+
+ /**
+ * Returns the ecdsa cert alg property.
+ *
+ * @return Returns the ecdsa cert alg property.
+ */
+ public String getCertAlgEcdsa()
+ {
+ return this.cert_alg_ecdsa;
+ }
+
+ /**
+ * Returns the rsa cert alg property.
+ *
+ * @return Returns the rsa cert alg property.
+ */
+ public String getCertAlgRsa()
+ {
+ return this.cert_alg_rsa;
+ }
+
+ /**
+ * Reads the configuration entry given by the key, first from the given
+ * profile, if not found from the defaults.
+ *
+ * @param settings
+ * The settings.
+ * @param profile
+ * The profile.
+ * @param key
+ * The configuration key.
+ * @return Returns the configuration entry.
+ */
+ public static String getConnectorValueFromProfile(SettingsReader settings, String profile, String key)
+ {
+ String value = settings.getValueFromKey("sig_obj." + profile + "." + key); //$NON-NLS-1$//$NON-NLS-2$
+ if (value == null)
+ {
+ value = settings.getValueFromKey(key);
+ }
+ return value;
+ }
+
+ }
+
+ public XMLDsigData reconstructXMLDsig(SignatureData data, SignSignatureObject so)
+ throws ConnectorException {
+ String xmldsig = chooseAndCreateXMLDsig(data, so);
+ return new XMLDsigData(xmldsig, true);
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MultipartRelatedEntity.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MultipartRelatedEntity.java
new file mode 100644
index 0000000..dd9f8b8
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MultipartRelatedEntity.java
@@ -0,0 +1,79 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors.moa;
+
+import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
+import org.apache.commons.httpclient.methods.multipart.Part;
+import org.apache.commons.httpclient.params.HttpMethodParams;
+import org.apache.commons.httpclient.util.EncodingUtil;
+
+public class MultipartRelatedEntity extends MultipartRequestEntity {
+
+ /** The Content-Type for multipart/related. */
+ private static final String MULTIPART_RELATED_CONTENT_TYPE = "multipart/related";
+
+
+ private String startID;
+
+ private String contentType;
+
+ public MultipartRelatedEntity(Part[] parts, HttpMethodParams params) {
+ super(parts, params);
+ // TODO Auto-generated constructor stub
+ }
+
+
+ public void setContentType(String contentType) {
+ this.contentType = contentType;
+ }
+
+
+ public String getStartID() {
+ return startID;
+ }
+
+
+ public void setStartID(String startID) {
+ this.startID = startID;
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.apache.commons.httpclient.methods.RequestEntity#getContentType()
+ */
+ public String getContentType() {
+ StringBuffer buffer = new StringBuffer(MULTIPART_RELATED_CONTENT_TYPE);
+ buffer.append("; type=\"");
+ buffer.append(EncodingUtil.getAsciiString(this.contentType.getBytes()));
+ buffer.append("\"; start=\"");
+ buffer.append(EncodingUtil.getAsciiString(getStartID().getBytes()));
+ buffer.append("\"; boundary=\"");
+ buffer.append(EncodingUtil.getAsciiString(getMultipartBoundary()));
+ buffer.append("\"");
+ return buffer.toString();
+ }
+
+
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/StringPartMR.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/StringPartMR.java
new file mode 100644
index 0000000..2efcbcc
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/StringPartMR.java
@@ -0,0 +1,189 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors.moa;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.commons.httpclient.methods.multipart.StringPart;
+import org.apache.commons.httpclient.util.EncodingUtil;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+public class StringPartMR extends StringPart {
+
+ /** Log object for this class. */
+ private static final Log LOG = LogFactory.getLog(StringPartMR.class);
+
+
+ /** Content dispostion characters */
+ protected static final String CONTENT_ID = "Content-Id: ";
+
+ /** Content dispostion as a byte array */
+ protected static final byte[] CONTENT_ID_BYTES =
+ EncodingUtil.getAsciiBytes(CONTENT_ID);
+
+ private String contentID = "";
+
+ public StringPartMR(String name, String value, String charset) {
+ super(name, value, charset);
+ // TODO Auto-generated constructor stub
+ }
+
+ public StringPartMR(String name, String value) {
+ super(name, value);
+ // TODO Auto-generated constructor stub
+ }
+
+ /**
+ * Write the content disposition header to the specified output stream
+ *
+ * @param out The output stream
+ * @throws IOException If an IO problem occurs.
+ */
+ protected void sendDispositionHeader(OutputStream out) throws IOException {
+ LOG.trace("enter sendContendID instead of ContentDisposition(OutputStream out)");
+ // Do nothing !
+ }
+
+ /**
+ * Write the content id header to the specified output stream
+ *
+ * @param out The output stream
+ * @throws IOException If an IO problem occurs.
+ */
+ protected void sendContentIDHeader(OutputStream out) throws IOException {
+ LOG.trace("enter sendContendID instead of ContentDisposition(OutputStream out)");
+ out.write(CONTENT_ID_BYTES);
+ out.write(EncodingUtil.getAsciiBytes(getContentID()));
+ }
+
+
+ /**
+ * Write the content type header to the specified output stream
+ * @param out The output stream
+ * @throws IOException If an IO problem occurs.
+ */
+ protected void sendContentTypeHeader(OutputStream out) throws IOException {
+ LOG.trace("enter sendContentTypeHeader(OutputStream out)");
+ String contentType = getContentType();
+ if (contentType != null) {
+ out.write(CRLF_BYTES);
+ out.write(CONTENT_TYPE_BYTES);
+ out.write(EncodingUtil.getAsciiBytes(contentType));
+ String charSet = getCharSet();
+ if (charSet != null) {
+ out.write(CHARSET_BYTES);
+ out.write(EncodingUtil.getAsciiBytes(charSet));
+ }
+ }
+ }
+
+ /**
+ * Write the content transfer encoding header to the specified
+ * output stream
+ *
+ * @param out The output stream
+ * @throws IOException If an IO problem occurs.
+ */
+ protected void sendTransferEncodingHeader(OutputStream out) throws IOException {
+ LOG.trace("enter sendTransferEncodingHeader(OutputStream out)");
+ String transferEncoding = getTransferEncoding();
+ if (transferEncoding != null) {
+ out.write(CRLF_BYTES);
+ out.write(CONTENT_TRANSFER_ENCODING_BYTES);
+ out.write(EncodingUtil.getAsciiBytes(transferEncoding));
+ }
+ }
+
+ public void setContentID(String contentid) {
+ this.contentID = contentid;
+ }
+
+ public String getContentID() {
+ return this.contentID;
+ }
+
+ /**
+ * Write the end of the header to the output stream
+ * @param out The output stream
+ * @throws IOException If an IO problem occurs.
+ */
+ protected void sendEndOfHeader(OutputStream out) throws IOException {
+ LOG.trace("enter sendEndOfHeader(OutputStream out)");
+ out.write(CRLF_BYTES);
+ out.write(CRLF_BYTES);
+ }
+
+
+ /**
+ * Write all the data to the output stream.
+ * If you override this method make sure to override
+ * #length() as well
+ *
+ * @param out The output stream
+ * @throws IOException If an IO problem occurs.
+ */
+ public void send(OutputStream out) throws IOException {
+ LOG.trace("enter send(OutputStream out)");
+ sendStart(out);
+
+ sendContentIDHeader(out);
+ sendContentTypeHeader(out);
+ sendTransferEncodingHeader(out);
+ sendEndOfHeader(out);
+ sendData(out);
+ sendEnd(out);
+ }
+
+
+ /**
+ * Return the full length of all the data.
+ * If you override this method make sure to override
+ * #send(OutputStream) as well
+ *
+ * @return long The length.
+ * @throws IOException If an IO problem occurs
+ */
+ public long length() throws IOException {
+ LOG.trace("enter length()");
+ if (lengthOfData() < 0) {
+ return -1;
+ }
+ ByteArrayOutputStream overhead = new ByteArrayOutputStream();
+ sendStart(overhead);
+
+ sendContentIDHeader(overhead);
+ sendContentTypeHeader(overhead);
+ sendTransferEncodingHeader(overhead);
+ sendEndOfHeader(overhead);
+ sendEnd(overhead);
+ return overhead.size() + lengthOfData();
+ }
+
+
+
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/LocRefDetachedMOCCAConnector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/LocRefDetachedMOCCAConnector.java
new file mode 100644
index 0000000..12fc709
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/LocRefDetachedMOCCAConnector.java
@@ -0,0 +1,623 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors.mocca;
+
+import java.security.cert.X509Certificate;
+import java.util.Properties;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteObject;
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteUtil;
+import at.gv.egiz.pdfas.api.xmldsig.XMLDsigData;
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.gv.egiz.pdfas.framework.ConnectorParameters;
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
+import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
+import at.knowcenter.wag.egov.egiz.sig.SignatureData;
+import at.knowcenter.wag.egov.egiz.sig.SignatureResponse;
+import at.knowcenter.wag.egov.egiz.sig.connectors.Connector;
+import at.knowcenter.wag.egov.egiz.sig.connectors.ConnectorEnvironment;
+import at.knowcenter.wag.egov.egiz.sig.connectors.LocalConnector;
+import at.knowcenter.wag.egov.egiz.sig.connectors.TemplateReplaces;
+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.SignSignatureObject;
+import at.knowcenter.wag.egov.egiz.sig.signaturelayout.SignatureLayoutHandler;
+import at.knowcenter.wag.egov.egiz.sig.signaturelayout.SignatureLayoutHandlerFactory;
+import at.knowcenter.wag.egov.egiz.tools.CodingHelper;
+
+/**
+ * Connector for MOCCA.
+ * @author tknall
+ */
+public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector {
+ //23.11.2010 changed by exthex - added reconstructXMLDsig method and moved xmldsig creation to chooseAndCreateXMLDsig method
+
+ private static Log log = LogFactory.getLog(LocRefDetachedMOCCAConnector.class);
+
+ /**
+ * The connector parameters.
+ */
+ protected ConnectorParameters params = null;
+
+ /**
+ * The environment of this connector containing templates.
+ */
+ protected Environment environment = null;
+
+ /**
+ * Constructor that builds the configuration environment for this connector according to the
+ * given profile.
+ * @param connectorParameters The connectot parameters.
+ * @throws ConnectorException Thrown in case of error.
+ */
+ public LocRefDetachedMOCCAConnector(ConnectorParameters connectorParameters, String loc_ref_content) throws ConnectorException {
+ this(connectorParameters, loc_ref_content, null);
+ }
+
+ /**
+ * Constructor that builds the configuration environment for this connector according to the
+ * given profile.
+ * @param connectorParameters The connectot parameters.
+ * @param algorithmId The algorithm idenifier.
+ * @throws ConnectorException Thrown in case of error.
+ */
+ public LocRefDetachedMOCCAConnector(ConnectorParameters connectorParameters, String loc_ref_content, String algorithmId) throws ConnectorException {
+ this.params = connectorParameters;
+ this.environment = new Environment(this.params.getProfileId(), loc_ref_content, algorithmId);
+ }
+
+ /**
+ * Sends the request to the given URL. This method handles communication exceptions.
+ * The actual send work is done by doPostRequestMultipart.
+ * @see BKUPostConnection#doPostRequestMultipart(String, String, SignatureData)
+ * @param url The URL to send the request to.
+ * @param request_string The request XML.
+ * @param data The data.
+ * @return Returns the response properties containing among others the response XML.
+ * @throws ConnectorException Thrown in case of an error.
+ */
+ protected Properties sendRequest(String url, String request_string, SignatureData data) throws ConnectorException {
+ try {
+ Properties response_properties = BKUPostConnection.doPostRequestMultipart(url, request_string, data);
+ return response_properties;
+ } catch (Exception e) {
+ ConnectorException se = new ConnectorException(320, e);
+ throw se;
+ }
+ }
+
+ /**
+ * Starts a signature process.
+ * @param data The data to be signed.
+ * @return Returns the signature object containing the signed data.
+ * @throws ConnectorException Thrown in case of an error.
+ */
+ public SignSignatureObject doSign(SignatureData data) throws ConnectorException {
+ log.debug("doSign:");
+
+ String sign_request_xml = prepareSignRequest(data);
+ log.debug("sign_request_xml = " + sign_request_xml);
+
+ String url = this.environment.getSignURL();
+ Properties response_properties = sendRequest(url, sign_request_xml, data);
+
+ SignSignatureObject sso = analyzeSignResponse(response_properties);
+
+ sso.response_properties = response_properties;
+
+ log.debug("doSign finished.");
+ return sso;
+ }
+
+ /**
+ * Verification is not supported by MOCCA. Therefore this method always throws a
+ * {@link ConnectorException} with error code {@link ErrorCode#SIGNATURE_VERIFICATION_NOT_SUPPORTED}.
+ */
+ public SignatureResponse doVerify(SignatureData data, SignSignatureObject so, XMLDsigData dsig) throws ConnectorException {
+ throw new ConnectorException(ErrorCode.SIGNATURE_VERIFICATION_NOT_SUPPORTED, "Signature Verification is not supported by MOCCA.");
+ }
+
+ /**
+ * This method analyzes a signature response of the signature device.
+ * @param response_properties The response elements of the signature device.
+ * @return The parsed signed signature object.
+ * @throws ConnectorException Thrown in case of an error.
+ */
+ public SignSignatureObject analyzeSignResponse(Properties response_properties) throws ConnectorException {
+ log.debug("analyzeSignResponse:");
+ String response_string = response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY);
+
+ String bkuIdentifier = BKUHelper.getBKUIdentifier(response_properties);
+ log.debug("BKU identifier: \"" + bkuIdentifier + "\"");
+ SignatureLayoutHandler sigLayout;
+ try {
+ sigLayout = SignatureLayoutHandlerFactory.getSignatureLayoutHandlerInstance(bkuIdentifier);
+ } catch (SettingsException e) {
+ throw new ConnectorException(e.getErrorCode(), e.getMessage());
+ }
+
+ BKUHelper.checkResponseForError(response_string);
+
+// SignSignatureObject so = MOCCAHelper.parseCreateXMLResponse(response_string, new DetachedMOCIdFormatter());
+ SignSignatureObject so = sigLayout.parseCreateXMLSignatureResponse(response_string, this.environment);
+ so.response_properties = response_properties;
+ log.debug("analyzeSignResponse finished.");
+ return so;
+ }
+
+ /**
+ * Verification is not supported by MOCCA. Therefore this method always throws a
+ * {@link ConnectorException} with error code {@link ErrorCode#SIGNATURE_VERIFICATION_NOT_SUPPORTED}.
+ */
+ public SignatureResponse analyzeVerifyResponse(Properties response_properties) throws ConnectorException {
+ throw new ConnectorException(ErrorCode.SIGNATURE_VERIFICATION_NOT_SUPPORTED, "Signature Verification is not supported by MOCCA.");
+ }
+
+ /**
+ * Prepares the signature request xml to be sent using the sign request template.
+ * @param data The signature data.
+ * @return Returns the sign request xml to be sent.
+ * @throws ConnectorException Thrown in case of an error.
+ */
+ public String prepareSignRequest(SignatureData data) throws ConnectorException {
+ log.debug("prepareSignRequestDetached:");
+
+ String sign_request_template = this.environment.getSignRequestTemplate();
+
+ String sign_keybox_identifier = this.environment.getSignKeyboxIdentifier();
+ String mime_type = data.getMimeType();
+ String loc_ref_content = this.environment.getLocRefContent();
+
+ if (log.isDebugEnabled()) {
+ log.debug("sign keybox identifier = " + sign_keybox_identifier);
+ log.debug("mime type = " + mime_type);
+ log.debug("loc_ref_content = " + loc_ref_content);
+ }
+
+ String sign_request_xml = sign_request_template.replaceFirst(TemplateReplaces.KEYBOX_IDENTIFIER_REPLACE, sign_keybox_identifier);
+ sign_request_xml = sign_request_xml.replaceFirst(TemplateReplaces.MIME_TYPE_REPLACE, mime_type);
+ sign_request_xml = sign_request_xml.replaceFirst(TemplateReplaces.LOC_REF_CONTENT_REPLACE, loc_ref_content);
+
+ log.debug("sign_request_xml = " + sign_request_xml);
+ log.debug("prepareSignRequestDetached finished.");
+ return sign_request_xml;
+ }
+
+ /**
+ * Verification is not supported by MOCCA. Therefore this method always throws a
+ * {@link ConnectorException} with error code {@link ErrorCode#SIGNATURE_VERIFICATION_NOT_SUPPORTED}.
+ */
+ public String prepareVerifyRequest(SignatureData data, SignSignatureObject so, XMLDsigData dsigData) throws ConnectorException {
+ throw new ConnectorException(ErrorCode.SIGNATURE_VERIFICATION_NOT_SUPPORTED, "Signature Verification is not supported by MOCCA.");
+ }
+
+ /**
+ * Prepares the xml content of a signature creation request including the link to the signature data.
+ * @param data The signature data.
+ * @param so The signature object containing the signature information.
+ * @return Returns the xml content.
+ * @throws ConnectorException Thrown in case of an error.
+ */
+ public String prepareXMLContent(SignatureData data, SignSignatureObject so) throws ConnectorException {
+ log.debug("prepareXMLContent:");
+ try {
+
+ String ids_string = so.getSigID();
+ String sigId = this.parseSigId(ids_string);
+
+ X509Certificate cert = so.getX509Certificate();
+
+
+ // dferbas
+ AlgorithmSuiteObject algSuite = new AlgorithmSuiteObject();
+ String verify_xml = AlgorithmSuiteUtil.evaluateReplaceAlgs(algSuite, this.environment, so);
+
+ // data digest replace
+ byte[] data_value_hash = CodingHelper.buildDigest(data.getDataSource(), algSuite.getDataDigestMethod());
+ String object_data_hash = CodingHelper.encodeBase64(data_value_hash);
+
+ // template replacements
+
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_SIGNED_DATA_REPLACE, object_data_hash);
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.SIGNATURE_VALUE_REPLACE, so.getSignatureValue());
+
+ // X.509 Certificate replace
+ byte[] der = cert.getEncoded();
+ byte[] cert_hash = CodingHelper.buildDigest(der, algSuite.getCertDigestMethod());
+ String certDigest = CodingHelper.encodeBase64(cert_hash);
+ String x509_cert_string = CodingHelper.encodeBase64(der);
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_CERTIFICATE_REPLACE, x509_cert_string);
+
+ // Qualified Properties replaces
+ verify_xml = verify_xml.replaceAll(TemplateReplaces.SIG_ID_REPLACE, sigId);
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.SIGNING_TIME_REPLACE, so.getDate());
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_CERTIFICATE_REPLACE, certDigest);
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_ISSUER_NAME_REPLACE, so.getIssuer());
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_SERIAL_NUMBER_REPLACE, so.getSerialNumber());
+ // SigDataRefReplace already done above
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.MIME_TYPE_REPLACE, data.getMimeType());
+
+ // Signed Properties hash
+ Pattern spPattern = Pattern.compile("(<(\\w+:)?SignedProperties.*>.*</(\\w+:)?SignedProperties>)");
+ Matcher matcher = spPattern.matcher(verify_xml);
+ if (matcher.find()) {
+ log.debug("SignedProperties found.");
+ String string_to_be_hashed = matcher.group(1);
+ log.debug("SignedProperties string to be hashed: " + string_to_be_hashed);
+ final byte[] bytes_to_be_hashed = string_to_be_hashed.getBytes("UTF-8");
+ byte[] sig_prop_code = CodingHelper.buildDigest(bytes_to_be_hashed, algSuite.getPropertiesDigestMethod());
+ String sig_prop_hash = CodingHelper.encodeBase64(sig_prop_code);
+
+ verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_SIGNED_PROPERTIES_REPLACE, sig_prop_hash);
+ }
+
+ log.debug("prepareXMLContent finished.");
+ return verify_xml;
+ } catch (Exception e) {
+ log.debug(e);
+ throw new ConnectorException(310, e);
+ }
+ }
+
+ /**
+ * Holds environment configuration information like templates.
+ * @author wprinz
+ */
+ public static class Environment extends ConnectorEnvironment {
+
+ /**
+ * The configuration key of the sign keybox identifier.
+ */
+ protected static final String SIGN_KEYBOX_IDENTIFIER_KEY = "moc.sign.KeyboxIdentifier";
+
+ /**
+ * The configuration key of the sign request template.
+ */
+ protected static final String SIGN_REQUEST_TEMPLATE_KEY = "moc.sign.request.detached";
+
+ /**
+ * The configuration key of the sign URL.
+ */
+ protected static final String SIGN_URL_KEY = "moc.sign.url";
+
+ /**
+ * BKU template file prefix
+ */
+ protected static final String TEMPLATE_FILE_PREFIX = "/templates/moc.";
+
+ /**
+ * signing file template suffix
+ */
+ protected static final String SIGN_TEMPLATE_FILE_SUFFIX = ".sign.request.xml";
+
+ /**
+ * verifing template file suffix
+ */
+ /* signature verification is not supported by mocca
+ protected static final String VERIFY_REQUEST_TEMPLATE_FILE_SUFIX = ".verify.request.xml";
+ */
+
+ /**
+ * verifing file template key suffix
+ */
+ protected static final String VERIFY_TEMPLATE_SUFFIX = ".verify.template.xml";
+
+ /**
+ * The configuration key of the verify request template.
+ */
+ /* signature verification is not supported by mocca
+ protected static final String VERIFY_REQUEST_TEMPLATE_KEY = "moc.verify.request.detached";
+ */
+
+ /**
+ * The configuration key of the verify template.
+ */
+ protected static final String VERIFY_TEMPLATE_KEY = "moc.verify.template.detached";
+
+ /**
+ * The configuration key of the verify URL.
+ */
+ /* signature verification is not supported by mocca
+ protected static final String xxxVERIFY_URL_KEY = "moc.verify.url";
+ */
+
+ /**
+ * The configuration key for the ECDSA cert alg property.
+ */
+ protected static final String ECDSA_CERT_ALG_KEY = "cert.alg.ecdsa";
+
+ /**
+ * The configuration key for the RSA cert alg property.
+ */
+ protected static final String RSA_CERT_ALG_KEY = "cert.alg.rsa";
+
+ protected String profile = null;
+
+ protected String loc_ref_content = null;
+
+ protected String sign_keybox_identifier = null;
+
+ protected String sign_request_template = null;
+
+ protected String sign_url = null;
+
+ /* signature verification is not supported by mocca
+ protected String verify_request_template = null;
+ */
+
+ protected String verify_template = null;
+
+ /* signature verification is not supported by mocca
+ protected String verify_url = null;
+ */
+
+ protected String cert_alg_ecdsa = null;
+
+ protected String cert_alg_rsa = null;
+
+ protected String algorithmId = null;
+
+ /**
+ * Initializes the environment with a given profile.
+ * @param profile The configuration profile.
+ * @param algorithmId The algorithm identifer.
+ * @throws ConnectorException Thrown in case of an error.
+ */
+ public Environment(String profile, String loc_ref_content, String algorithmId) throws ConnectorException {
+ this.profile = profile;
+
+ this.loc_ref_content = loc_ref_content;
+
+ SettingsReader settings = null;
+ try {
+ settings = SettingsReader.getInstance();
+ } catch (SettingsException e) {
+ throw new ConnectorException(300, e);
+ }
+
+ this.sign_keybox_identifier = getConnectorValueFromProfile(settings, profile, SIGN_KEYBOX_IDENTIFIER_KEY);
+
+ if (algorithmId == null) {
+ this.algorithmId = settings.getValueFromKey("default.moc.algorithm.id");
+ } else {
+ this.algorithmId = algorithmId;
+ }
+
+ // SIGN REQUEST
+
+ // try specific file
+ String sign_request_filename = TEMPLATE_FILE_PREFIX + this.algorithmId + SIGN_TEMPLATE_FILE_SUFFIX;
+ log.debug("Trying to load specific sign request file " + sign_request_filename);
+ //this.sign_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename));
+ this.sign_request_template = settings.readInternalResourceAsString(sign_request_filename);
+
+ // try default request file
+ if (this.sign_request_template == null) {
+ sign_request_filename = getConnectorValueFromProfile(settings, profile, SIGN_REQUEST_TEMPLATE_KEY);
+ log.debug("Specific file not found. Trying default sign request file " + sign_request_filename);
+ //this.sign_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename));
+ this.sign_request_template = settings.readInternalResourceAsString(sign_request_filename);
+ }
+
+ // request file is needed !!!
+ if (this.sign_request_template == null) {
+ throw new ConnectorException(300, "Can not read the create xml request template");
+ }
+
+ this.sign_url = getConnectorValueFromProfile(settings, profile, SIGN_URL_KEY);
+
+
+ // VERIFY REQUEST
+ /* signature verification is not supported by mocca
+
+ // try specific file
+ String verify_request_filename = TEMPLATE_FILE_PREFIX + settings.getValueFromKey("default.moc.algorithm.id") + VERIFY_REQUEST_TEMPLATE_FILE_SUFIX;
+ log.debug("Trying to load specific verify request file " + verify_request_filename);
+ this.verify_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_request_filename));
+
+ // try default request file
+ if (this.verify_request_template == null) {
+ verify_request_filename = getConnectorValueFromProfile(settings, profile, VERIFY_REQUEST_TEMPLATE_KEY);
+ log.debug("Specific file not found. Trying default verify request file " + verify_request_filename);
+ this.verify_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_request_filename));
+ }
+
+ // request file is needed !!!
+ if (this.verify_request_template == null) {
+ throw new ConnectorException(ErrorCode.SETTING_NOT_FOUND, "Can not read the verify xml request template");
+ }
+
+ */
+
+ // load template file
+ // try specific file
+ String verify_filename = TEMPLATE_FILE_PREFIX + this.algorithmId + VERIFY_TEMPLATE_SUFFIX;
+ log.debug("Trying to load specific signature template file " + verify_filename);
+ //this.verify_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_filename));
+ this.verify_template = settings.readInternalResourceAsString(verify_filename);
+
+ // try default signature template file
+ if (this.verify_template == null) {
+ verify_filename = getConnectorValueFromProfile(settings, profile, VERIFY_TEMPLATE_KEY);
+ log.debug("Specific signature template file not found. Trying default signature template file " + verify_filename);
+ //this.verify_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_filename));
+ this.verify_template = settings.readInternalResourceAsString(verify_filename);
+ }
+
+ // signature template is needed !!!
+ if (this.verify_template == null) {
+ throw new ConnectorException(ErrorCode.SETTING_NOT_FOUND, "Can not read the verify template");
+ }
+
+ /* signature verification is not supported by mocca
+ this.verify_url = getConnectorValueFromProfile(settings, profile, VERIFY_URL_KEY);
+ */
+
+ this.cert_alg_ecdsa = settings.getValueFromKey(ECDSA_CERT_ALG_KEY);
+
+ this.cert_alg_rsa = settings.getValueFromKey(RSA_CERT_ALG_KEY);
+
+ }
+
+ /**
+ * Returns the profile name.
+ * @return The profile name.
+ */
+ public String getProfile() {
+ return this.profile;
+ }
+
+ /**
+ * Returns the LocRef content.
+ *
+ * @return Returns the LocRef content.
+ */
+ public String getLocRefContent() {
+ return this.loc_ref_content;
+ }
+
+ /**
+ * Returns the sign keybox identifier.
+ *
+ * @return Returns the sign keybox identifier.
+ */
+ public String getSignKeyboxIdentifier() {
+ return this.sign_keybox_identifier;
+ }
+
+ /**
+ * Returns the sign request template.
+ *
+ * @return Returns the sign request template.
+ */
+ public String getSignRequestTemplate() {
+ return this.sign_request_template;
+ }
+
+ /**
+ * Returns the sign URL.
+ *
+ * @return Returns the sign URL.
+ */
+ public String getSignURL() {
+ return this.sign_url;
+ }
+
+ /**
+ * Returns the verify request template.
+ *
+ * @return Returns the verify request template.
+ */
+ /* signature verification is not supported by mocca
+ public String getVerifyRequestTemplate() {
+ return this.verify_request_template;
+ }
+ */
+
+ /**
+ * Returns the verify template.
+ *
+ * @return Returns the verify template.
+ */
+ public String getVerifyTemplate() {
+ return this.verify_template;
+ }
+
+ /**
+ * Returns the verify URL.
+ *
+ * @return Returns the verify URL.
+ */
+ /* signature verification is not supported by mocca
+ public String getVerifyURL() {
+ return this.verify_url;
+ }
+ */
+
+ /**
+ * Returns the ecdsa cert alg property.
+ *
+ * @return Returns the ecdsa cert alg property.
+ */
+ public String getCertAlgEcdsa() {
+ return this.cert_alg_ecdsa;
+ }
+
+ /**
+ * Returns the rsa cert alg property.
+ *
+ * @return Returns the rsa cert alg property.
+ */
+ public String getCertAlgRsa() {
+ return this.cert_alg_rsa;
+ }
+
+ /**
+ * Reads the configuration entry given by the key, first from the given
+ * profile, if not found from the defaults.
+ *
+ * @param settings
+ * The settings.
+ * @param profile
+ * The profile.
+ * @param key
+ * The configuration key.
+ * @return Returns the configuration entry.
+ */
+ public static String getConnectorValueFromProfile(SettingsReader settings, String profile, String key) {
+ String value = settings.getValueFromKey("sig_obj." + profile + "." + key); //$NON-NLS-2$
+ if (value == null) {
+ value = settings.getValueFromKey(key);
+ }
+ return value;
+ }
+ }
+
+ /**
+ * Parses the common part for all id attributes from a given signature parameter string.
+ * @param sigIdString The given signature parameter string.
+ * @return The common part of all id attributes.
+ */
+ protected String parseSigId(String sigIdString) {
+ String[] parts = sigIdString.split("@");
+ String result = null;
+ if (parts != null && parts.length > 1) {
+ result = parts[1].trim();
+ }
+ return result;
+ }
+
+ public XMLDsigData reconstructXMLDsig(SignatureData data, SignSignatureObject so)
+ throws ConnectorException {
+ String xmldsig = prepareXMLContent(data, so);
+ return new XMLDsigData(xmldsig, true);
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/MOCCAHelper.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/MOCCAHelper.java
new file mode 100644
index 0000000..6b90fa1
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/MOCCAHelper.java
@@ -0,0 +1,223 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.connectors.mocca;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmMapper;
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteObject;
+import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteUtil;
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
+import at.knowcenter.wag.egov.egiz.sig.SignatureObject;
+import at.knowcenter.wag.egov.egiz.sig.X509Cert;
+import at.knowcenter.wag.egov.egiz.sig.connectors.ConnectorEnvironment;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUHelper;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject;
+import at.knowcenter.wag.egov.egiz.sig.connectors.moa.MOASoapWithAttachmentConnector.Environment;
+import at.knowcenter.wag.egov.egiz.sig.sigid.IdFormatter;
+import at.knowcenter.wag.egov.egiz.tools.CodingHelper;
+
+/**
+ * Provides useful methods for the usage of the open source cce mocca.
+ *
+ * @author tknall
+ */
+public final class MOCCAHelper {
+
+ /**
+ * Prevents this plain util class from being instantiated.
+ */
+ private MOCCAHelper() {
+ }
+
+ /**
+ * The logging implementation.
+ */
+ private final static Log log = LogFactory.getLog(MOCCAHelper.class);
+
+ /**
+ * This method parses the signature creation response of the signature
+ * device mocca.
+ *
+ * @param xmlResponse The response string.
+ * @return Returns the parsed signature object holding the data.
+ * @see SignatureObject
+ * @see CodingHelper
+ * @see X509Cert
+ */
+ public final static SignSignatureObject parseCreateXMLResponse(String xmlResponse, IdFormatter id_formatter, ConnectorEnvironment environment) throws ConnectorException {
+
+ if (log.isDebugEnabled()) {
+ log.debug("xmlResponse = " + xmlResponse);
+ }
+
+ Pattern iss_nam_p_s = Pattern.compile("<[\\w]*:?X509IssuerName[^>]*>");
+ Pattern iss_nam_p_e = Pattern.compile("</[\\w]*:?X509IssuerName>");
+ Pattern sig_tim_p_s = Pattern.compile("<[\\w]*:?SigningTime>");
+ Pattern sig_tim_p_e = Pattern.compile("</[\\w]*:?SigningTime>");
+ Pattern ser_num_p_s = Pattern.compile("<[\\w]*:?X509SerialNumber[^>]*>");
+ Pattern ser_num_p_e = Pattern.compile("</[\\w]*:?X509SerialNumber>");
+ Pattern sig_cer_p_s = Pattern.compile("<[\\w]*:?X509Certificate>");
+ Pattern sig_cer_p_e = Pattern.compile("</[\\w]*:?X509Certificate>");
+
+ Matcher iss_nam_m_s = iss_nam_p_s.matcher(xmlResponse);
+ Matcher iss_nam_m_e = iss_nam_p_e.matcher(xmlResponse);
+ Matcher sig_tim_m_s = sig_tim_p_s.matcher(xmlResponse);
+ Matcher sig_tim_m_e = sig_tim_p_e.matcher(xmlResponse);
+ Matcher ser_num_m_s = ser_num_p_s.matcher(xmlResponse);
+ Matcher ser_num_m_e = ser_num_p_e.matcher(xmlResponse);
+ Matcher sig_cer_m_s = sig_cer_p_s.matcher(xmlResponse);
+ Matcher sig_cer_m_e = sig_cer_p_e.matcher(xmlResponse);
+
+ // SignatureValue
+ String sig_val = null;
+ Pattern signatureValuePattern = Pattern.compile("<(\\w+:)?SignatureValue( Id=\"[\\w-]+\")?>\\s*(.*)\\s*</(\\w+:)?SignatureValue>", Pattern.DOTALL);
+ Matcher signatureValueMatcher = signatureValuePattern.matcher(xmlResponse);
+ if (signatureValueMatcher.find()) {
+ sig_val = signatureValueMatcher.group(3);
+ if (sig_val != null) {
+ sig_val = sig_val.replaceAll("\\s", "");
+ }
+ }
+ log.debug("sig_val = " + sig_val);
+
+ // X509IssuerName
+ String iss_nam = null;
+ if (iss_nam_m_s.find() && iss_nam_m_e.find()) {
+ iss_nam = xmlResponse.substring(iss_nam_m_s.end(), iss_nam_m_e.start());
+ }
+ log.debug("iss_nam = " + iss_nam);
+
+ // X509SerialNumber
+ String ser_num = null;
+ if (ser_num_m_s.find() && ser_num_m_e.find()) {
+ ser_num = BKUHelper.removeAllWhitespace(xmlResponse.substring(ser_num_m_s.end(), ser_num_m_e.start()));
+ }
+ log.debug("ser_num = " + ser_num);
+
+ // SigningTime
+ String sig_tim = null;
+ if (sig_tim_m_s.find() && sig_tim_m_e.find()) {
+ sig_tim = xmlResponse.substring(sig_tim_m_s.end(), sig_tim_m_e.start());
+ }
+ log.debug("sig_tim = " + sig_tim);
+
+ // X509Certificate
+ X509Certificate cert = null;
+ if (sig_cer_m_s.find() && sig_cer_m_e.find()) {
+ String sig_cer = BKUHelper.removeAllWhitespace(xmlResponse.substring(sig_cer_m_s.end(), sig_cer_m_e.start()));
+
+ try {
+ byte[] der = CodingHelper.decodeBase64(sig_cer);
+ ByteArrayInputStream bais = new ByteArrayInputStream(der);
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ cert = (X509Certificate) cf.generateCertificate(bais);
+ bais.close();
+ } catch (UnsupportedEncodingException e) {
+ throw new ConnectorException(300, e);
+ } catch (CertificateException e) {
+ throw new ConnectorException(300, e);
+ } catch (IOException e) {
+ throw new ConnectorException(300, e);
+ }
+ }
+ log.debug("X509Certificate = " + cert);
+
+ if (log.isDebugEnabled()) {
+
+ String cert_iss = cert.getIssuerDN().getName();
+ log.debug("certificate's issuer = " + cert_iss);
+ log.debug("response's issuer = " + iss_nam);
+ log.debug("issuer matches = " + cert_iss.equals(iss_nam));
+ log.debug("ser number matches = " + cert.getSerialNumber().toString().equals(ser_num));
+ }
+
+ SignSignatureObject so = new SignSignatureObject();
+
+ // extract Signature Id's
+ String[] ids = extractIds(xmlResponse);
+ // dferbas
+ String algs = AlgorithmSuiteUtil.extractAlgorithmSuiteString(xmlResponse);
+
+ AlgorithmSuiteObject suite = new AlgorithmSuiteObject(algs, false);
+ so.sigAlgorithm = AlgorithmMapper.getUri(suite.getSignatureMethod());
+
+ String defaultCertAlg = environment.getDefaultAlgForCert(cert);
+
+ if (AlgorithmSuiteUtil.isDefaultCertAlg(algs, defaultCertAlg)) {
+ // do not embed default alg
+ algs = null;
+ }
+
+ String final_ids = id_formatter.formatIds(ids, algs);
+
+
+ so.date = sig_tim;
+ so.issuer = iss_nam;
+ so.signatureValue = sig_val;
+ so.x509Certificate = cert;
+
+ so.id = final_ids;
+
+ return so;
+ }
+
+ /**
+ * Extraction of the id attributes from the xml response.
+ *
+ * @param xmlResponse The xml response.
+ * @return The parsed id attributes.
+ */
+ public final static String[] extractIds(String xmlResponse) {
+ return new String[] { extractId(xmlResponse) };
+ }
+
+ /**
+ * There is only one special common part of all id attributes of this
+ * connector that has to be stored. This method returns that single part.
+ *
+ * @param xmlResponse The xml response.
+ * @return The parsed common part of all id attributes.
+ */
+ private final static String extractId(String xmlResponse) {
+ final Pattern ID_PATTERN = Pattern.compile("Id\\s*=\\s*\"\\s*Signature-([\\p{XDigit}]+)-\\d+\\s*\"");
+ Matcher matcher = ID_PATTERN.matcher(xmlResponse);
+ if (matcher.find() && matcher.groupCount() > 0) {
+ return matcher.group(1);
+ }
+ return null;
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigid/DetachedIdFormatter.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigid/DetachedIdFormatter.java
new file mode 100644
index 0000000..359e49b
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigid/DetachedIdFormatter.java
@@ -0,0 +1,101 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.sigid;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
+
+/**
+ * @author wprinz
+ *
+ */
+public class DetachedIdFormatter implements IdFormatter
+{
+ /**
+ * The SIG_ID prefix.
+ * Default value: etsi-bka-1.0
+ */
+ public static String SIG_ID_PREFIX = "etsi-bka-1.0"; //$NON-NLS-1$
+
+ /**
+ * Key value in property file
+ */
+ public static final String SIG_ID_PROPERTY_KEY = "default.bku.algorithm.id";
+
+ /**
+ * The log.
+ */
+ private static Log log = LogFactory.getLog(DetachedIdFormatter.class);
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.sigid.IdFormatter#formatIds(java.lang.String[])
+ */
+ public String formatIds(String[] ids, String algorithmParams)
+ {
+ // read id from property file and use it
+ try {
+ SIG_ID_PREFIX = SettingsReader.getInstance().getValueFromKey(SIG_ID_PROPERTY_KEY);
+ } catch (SettingsException e) {
+ log.error(e.getMessage(), e);
+ }
+
+ // ids algorithm:
+ String join = ""; //$NON-NLS-1$
+ String base = null;
+ for (int arr_idx = 0; arr_idx < ids.length; arr_idx++)
+ {
+ String id = ids[arr_idx];
+ if (log.isDebugEnabled())
+ {
+ log.debug("Set BKU id:" + id); //$NON-NLS-1$
+ }
+ int id_idx = id.lastIndexOf("-"); //$NON-NLS-1$
+ if (arr_idx == 0)
+ {
+ base = id.substring(0, id_idx);
+ }
+ String cur_id = id.substring(id_idx + 1);
+ if (cur_id.equalsIgnoreCase("")) //$NON-NLS-1$
+ {
+ cur_id = "0"; //$NON-NLS-1$
+ }
+
+ join += "-" + cur_id; //$NON-NLS-1$
+ }
+ String idstr = base + "@" + join.substring(1); //$NON-NLS-1$
+
+ // dferbas
+ StringBuffer final_ids = new StringBuffer(SIG_ID_PREFIX);
+ //String final_ids = SIG_ID_PREFIX + "@" + idstr;
+ if (algorithmParams != null && algorithmParams.length() > 0) {
+ final_ids.append(":").append(algorithmParams);
+ }
+ final_ids.append("@").append(idstr);
+ return final_ids.toString();
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigid/DetachedLocRefMOAIdFormatter.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigid/DetachedLocRefMOAIdFormatter.java
new file mode 100644
index 0000000..a83540b
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigid/DetachedLocRefMOAIdFormatter.java
@@ -0,0 +1,80 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.sigid;
+
+import org.apache.commons.lang.BooleanUtils;
+import org.apache.log4j.Logger;
+
+import at.knowcenter.wag.egov.egiz.cfg.ConfigLogger;
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
+
+/**
+ * @author wprinz
+ *
+ */
+public class DetachedLocRefMOAIdFormatter implements IdFormatter
+{
+ /**
+ * The SIG_ID prefix.
+ * Default value: etsi-bka-moa-1.0
+ */
+ public static String SIG_ID_PREFIX = "etsi-bka-moa-1.0"; //$NON-NLS-1$
+
+ private static final Logger logger_ = ConfigLogger.getLogger(DetachedLocRefMOAIdFormatter.class);
+
+ /**
+ * Key value in property file
+ */
+ public static final String SIG_ID_PROPERTY_KEY = "default.moa.algorithm.id";
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.sigid.IdFormatter#formatIds(java.lang.String[])
+ */
+ public String formatIds(String[] ids, String algorithmParams)
+ {
+ // read id from property file and use it
+
+ try
+ {
+ // dferbas
+// if (!BooleanUtils.toBoolean(SettingsReader.getInstance().getValueFromKey("moa.id.field.visible"))) {
+// return null;
+// }
+
+
+ SIG_ID_PREFIX = SettingsReader.getInstance().getValueFromKey(SIG_ID_PROPERTY_KEY);
+ } catch (SettingsException e)
+ {
+ logger_.error(e.getMessage(), e);
+ }
+
+ // dferbas
+ if (algorithmParams != null && algorithmParams.length() > 0) {
+ return SIG_ID_PREFIX + ":" + algorithmParams;
+ } else {
+ return SIG_ID_PREFIX;
+ }
+ }
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigid/DetachedMOCIdFormatter.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigid/DetachedMOCIdFormatter.java
new file mode 100644
index 0000000..1ba7916
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigid/DetachedMOCIdFormatter.java
@@ -0,0 +1,78 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.sigid;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
+
+/**
+ * @author tknall
+ *
+ */
+public class DetachedMOCIdFormatter implements IdFormatter {
+
+ /**
+ * Key value in property file
+ */
+ private static final String SIG_ID_PROPERTY_KEY = "default.moc.algorithm.id";
+
+ /**
+ * The log.
+ */
+ private static Log log = LogFactory.getLog(DetachedIdFormatter.class);
+
+ private String algorithmId;
+
+ public DetachedMOCIdFormatter(String algorithmId) {
+ this.algorithmId = algorithmId;
+ }
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.sigid.IdFormatter#formatIds(java.lang.String[])
+ */
+ public String formatIds(String[] ids, String algorithmParams) {
+ // read id from property file and use it
+ String prefix = null;
+ try {
+ prefix = SettingsReader.getInstance().getValueFromKey(SIG_ID_PROPERTY_KEY);
+ } catch (SettingsException e) {
+ log.error(e.getMessage(), e);
+ }
+ prefix = StringUtils.defaultIfEmpty(this.algorithmId, prefix);
+
+ // dferbas
+ StringBuffer formattedIds = new StringBuffer(prefix);
+ if (algorithmParams != null && algorithmParams.length() > 0) {
+ formattedIds.append(":").append(algorithmParams);
+ }
+ formattedIds.append("@").append(ids[0]);
+ return formattedIds.toString();
+
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigid/HotfixIdFormatter.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigid/HotfixIdFormatter.java
new file mode 100644
index 0000000..ea6637a
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigid/HotfixIdFormatter.java
@@ -0,0 +1,74 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.sigid;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * @author wprinz
+ *
+ */
+public class HotfixIdFormatter implements IdFormatter
+{
+ /**
+ * The SIG_ID prefix.
+ */
+ public static final String SIG_ID_PREFIX = "etsi-bka-1.0"; //$NON-NLS-1$
+
+ /**
+ * The log.
+ */
+ private static Log log = LogFactory.getLog(HotfixIdFormatter.class);
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.sigid.IdFormatter#formatIds(java.lang.String[])
+ */
+ public String formatIds(String[] ids, String algorithmParams)
+ {
+ // ids algorithm:
+ String join = ""; //$NON-NLS-1$
+ String base = null;
+ for (int arr_idx = 0; arr_idx < ids.length; arr_idx++)
+ {
+ String id = ids[arr_idx];
+ if (log.isDebugEnabled())
+ {
+ log.debug("Set BKU id:" + id); //$NON-NLS-1$
+ }
+ int id_idx = id.lastIndexOf("-"); //$NON-NLS-1$
+ if (arr_idx == 0)
+ {
+ base = id.substring(0, id_idx);
+ }
+ String cur_id = id.substring(id_idx + 1);
+ join += "-" + cur_id; //$NON-NLS-1$
+ }
+
+ String idstr = base + "@" + join.substring(1); //$NON-NLS-1$
+ String final_ids = SIG_ID_PREFIX + "@" + idstr;
+
+ return final_ids;
+ }
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigid/IdFormatter.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigid/IdFormatter.java
new file mode 100644
index 0000000..9747055
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigid/IdFormatter.java
@@ -0,0 +1,34 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.sigid;
+
+/**
+ * @author wprinz
+ *
+ */
+public interface IdFormatter
+{
+ public String formatIds (String [] ids, String algorithmParams);
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigid/OldMOAIdFormatter.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigid/OldMOAIdFormatter.java
new file mode 100644
index 0000000..ff0c9f3
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigid/OldMOAIdFormatter.java
@@ -0,0 +1,42 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.sigid;
+
+/**
+ * @author wprinz
+ *
+ */
+public class OldMOAIdFormatter implements IdFormatter
+{
+
+ /**
+ * @see at.knowcenter.wag.egov.egiz.sig.sigid.IdFormatter#formatIds(java.lang.String[])
+ */
+ public String formatIds(String[] ids, String algorithmParams)
+ {
+ return null;//"etsi-bka-moa-1.0";
+ }
+
+}
+
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigid/SimpleIdFormatter.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigid/SimpleIdFormatter.java
new file mode 100644
index 0000000..8e79dc4
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigid/SimpleIdFormatter.java
@@ -0,0 +1,48 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.sigid;
+
+/**
+ * {@link IdFormatter} implementation that uses specified algorithmid but not additional parameters.<br>
+ * usage A-Trust bku
+ * @author dferbas
+ *
+ */
+public class SimpleIdFormatter implements IdFormatter {
+ private String algorithmId;
+
+ public SimpleIdFormatter(String algorithmId) {
+ this.algorithmId = algorithmId;
+ }
+
+ public String formatIds(String[] ids, String algorithmParams) {
+ // dferbas
+ if (algorithmParams != null && algorithmParams.length() > 0) {
+ return this.algorithmId + ":" + algorithmParams;
+ } else {
+ return this.algorithmId;
+ }
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigkz/SigKZIDHelper.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigkz/SigKZIDHelper.java
new file mode 100644
index 0000000..094880d
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigkz/SigKZIDHelper.java
@@ -0,0 +1,262 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.sigkz;
+
+import java.util.Iterator;
+import java.util.Vector;
+import java.util.regex.Pattern;
+
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.lang.StringUtils;
+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.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
+import at.knowcenter.wag.egov.egiz.exceptions.InvalidIDException;
+import at.knowcenter.wag.egov.egiz.exceptions.SettingNotFoundException;
+import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
+import at.knowcenter.wag.egov.egiz.framework.SignatorFactory;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject;
+import at.knowcenter.wag.egov.egiz.sig.sigid.DetachedLocRefMOAIdFormatter;
+import at.knowcenter.wag.egov.egiz.sig.sigid.HotfixIdFormatter;
+
+/**
+ * @author wprinz
+ *
+ */
+public final class SigKZIDHelper
+{
+
+ /**
+ * The Logger.
+ */
+ protected static Log logger = LogFactory.getLog(SigKZIDHelper.class);
+
+ public static boolean isTextual(PdfASID sig_kz)
+ {
+ if (sig_kz == null)
+ {
+ // Old signature -> must be textual.
+
+ return true;
+ }
+
+ // new signauture -> sig_kz decides
+ return sig_kz.getType().equals(SignatorFactory.TYPE_TEXTUAL);
+ }
+
+ public static boolean isBinary(PdfASID sig_kz)
+ {
+ return ! isTextual(sig_kz);
+ }
+
+
+ public static boolean isMOASigned(PdfASID sig_kz, String sig_id)
+ {
+ if (sig_kz == null || sig_kz.getVersion().equals(SignatorFactory.VERSION_1_0_0))
+ {
+ // old signature - if sig_id is null this means MOA
+
+ return sig_id == null;
+ }
+
+ if(sig_id == null)
+ return true;
+
+ // new signature - sig_id decides
+ String [] ids = sig_id.split("@");
+ // dferbas
+ String prefix = (ids[0].split(":"))[0];
+
+
+ if (prefix.equals(DetachedLocRefMOAIdFormatter.SIG_ID_PREFIX))
+ {
+ return true;
+ }
+ return false;
+ }
+
+ public static boolean isMOASigned(SignSignatureObject so)
+ {
+ String sig_kz = so.kz;
+ String sig_id = so.id;
+ PdfASID kz = null;
+ if (sig_kz != null)
+ {
+ try
+ {
+ kz = new PdfASID(sig_kz);
+ }
+ catch (InvalidIDException e)
+ {
+ logger.error(e.getMessage(), e);
+ }
+ }
+
+ return isMOASigned(kz, sig_id);
+ }
+
+ /**
+ * @author tknall
+ */
+ public static boolean isMOCCASigned(SignSignatureObject so) {
+ String sig_id = so.id;
+ if (StringUtils.isEmpty(sig_id)) {
+ return false;
+ }
+ String[] ids = sig_id.split("@");
+ if (ArrayUtils.isEmpty(ids)) {
+ return false;
+ }
+ String algorithmId = parseAlgorithmId(sig_id);
+ if (algorithmId == null) {
+ return false;
+ } else {
+ return algorithmId.startsWith("etsi-moc-1.0") || algorithmId.startsWith("etsi-moc-1.1");
+ }
+ }
+
+ /**
+ * @author tknall
+ */
+ public static String parseAlgorithmId(String algorithmParameter) {
+ if (StringUtils.isEmpty(algorithmParameter)) {
+ return null;
+ }
+ // dferbas
+ String[] ids = algorithmParameter.split("@")[0].split(":");
+ if (ArrayUtils.isEmpty(ids)) {
+ return null;
+ }
+ return ids[0];
+ }
+
+ public static boolean isOldBKU(PdfASID sig_kz, String sig_id) throws ConnectorException
+ {
+ if (sig_kz == null)
+ {
+ return true;
+ }
+
+ if (sig_kz.getVersion().equals(SignatorFactory.VERSION_1_0_0))
+ {
+ if (sig_id == null)
+ {
+ throw new ConnectorException(310, "The SIG_ID is null - so this isn't a BKU at all.");
+ }
+
+ String[] sig_id_parts = sig_id.split("@");
+ if (sig_id_parts.length == 2)
+ {
+ return true;
+ }
+ // dferbas
+ if (sig_id_parts[0].startsWith(HotfixIdFormatter.SIG_ID_PREFIX))
+ {
+
+ return false;
+ }
+
+ throw new ConnectorException(310, "The SIG_KZ version is 1.0.0, but SIG_ID is neither MOA nor Old base64 nor Hotfix base64 ???'");
+ }
+
+ return false;
+ }
+
+ public static boolean isOldBKU(SignSignatureObject so) throws ConnectorException
+ {
+ String sig_kz = so.kz;
+ String sig_id = so.id;
+ PdfASID kz = null;
+ if (sig_kz != null)
+ {
+ try
+ {
+ kz = new PdfASID(sig_kz);
+ }
+ catch (InvalidIDException e)
+ {
+ logger.error(e.getMessage(), e);
+ }
+ }
+
+ return isOldBKU(kz, sig_id);
+ }
+
+ public static String getAlgorithmId(String bkuIdentifier) throws SettingsException, SettingNotFoundException, ConnectorException {
+ SettingsReader sr = SettingsReader.getInstance();
+
+ String base = "signaturelayout.pattern";
+ Vector v = sr.getSettingKeys(base);
+
+ Iterator it = v.iterator();
+ while (it.hasNext()) {
+ String subKey = (String) it.next();
+ String key = base + "." + subKey;
+ String value = sr.getSetting(key);
+ Pattern p = Pattern.compile(value);
+ if (p.matcher(bkuIdentifier).matches()) {
+ String algKey = "signaturelayout.algorithm.id." + subKey;
+ String algValue = sr.getSetting(algKey);
+ return algValue;
+ }
+ }
+
+ if ("true".equalsIgnoreCase(sr.getSetting("signaturelayout.strict", "false"))) {
+ logger.debug("Enforcing bku support check.");
+ throw new ConnectorException(ErrorCode.BKU_NOT_SUPPORTED, "Unsupported BKU: " + bkuIdentifier);
+ } else {
+ logger.debug("bku support check disabled.");
+ return null;
+ }
+
+ }
+
+ public static boolean isATrustSigned(SignSignatureObject so) {
+ String sig_id = so.id;
+ if (sig_id == null && StringUtils.isEmpty(sig_id)) {
+ return false;
+ }
+ return sig_id.startsWith("etsi-bka-atrust-1.0");
+ }
+
+ /**
+ * Checks if signed with a known BKU method/param
+ * @param so
+ * @return
+ */
+ public static boolean isBKUSigned(SignSignatureObject so) throws ConnectorException {
+ if (isOldBKU(so)) return true;
+
+ if (so.id.startsWith("etsi-bka-1.0")) {
+ return true;
+ }
+
+ return false;
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/SignatureLayoutHandler.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/SignatureLayoutHandler.java
new file mode 100644
index 0000000..b58b2e4
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/SignatureLayoutHandler.java
@@ -0,0 +1,45 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.signaturelayout;
+
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
+import at.knowcenter.wag.egov.egiz.sig.connectors.ConnectorEnvironment;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject;
+
+/**
+ * Considers different signature layout characteristics among different versions of citizen card
+ * environments.
+ * @author tknall
+ */
+public interface SignatureLayoutHandler {
+
+ /**
+ * This method parses the CreateXMLSignatureResponse given from a certain signature device.
+ *
+ * @param xmlResponse The response string.
+ * @return Returns the parsed signature object.
+ */
+ public SignSignatureObject parseCreateXMLSignatureResponse(String xmlResponse, ConnectorEnvironment env) throws ConnectorException;
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/SignatureLayoutHandlerFactory.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/SignatureLayoutHandlerFactory.java
new file mode 100644
index 0000000..07a7792
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/SignatureLayoutHandlerFactory.java
@@ -0,0 +1,147 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.signaturelayout;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Vector;
+import java.util.regex.Pattern;
+
+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.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
+import at.knowcenter.wag.egov.egiz.exceptions.SettingNotFoundException;
+import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
+
+/**
+ * Returns instances of signature layout handlers based on given bku
+ * identifiers.
+ *
+ * @author tknall
+ */
+public class SignatureLayoutHandlerFactory {
+
+ /**
+ * Prefix of configuration keys defining bku identifiers for a signature layout.
+ */
+ private final static String SIGNATURE_LAYOUT_CONFIG_KEY_PATTERN = "signaturelayout.pattern";
+
+ /**
+ * Prefix of configuration keys defining implementations of signature layout handlers.
+ * @see SignatureLayoutHandler
+ */
+ private final static String SIGNATURE_LAYOUT_CONFIG_KEY_IMPL = "signaturelayout.implementation";
+
+ /**
+ * A map holding instantiated signature layout implementations (for performance reasons).
+ */
+ private final static Map instances = Collections.synchronizedMap(new HashMap());
+
+ /**
+ * The log.
+ */
+ private static Log log = LogFactory.getLog(SignatureLayoutHandlerFactory.class);
+
+ /**
+ * Returns an instance of a signature layout handler based on the given bku identifier.
+ * @param bkuIdentifier The bku identifier (e.g. <code>citizen-card-environment/1.2 MOCCA/1.1.1</code>).
+ * @return An implementation of a signature layout handler.
+ * @throws ConnectorException Thrown in case of an error finding a match within the configuration with the given bku identifier.
+ * @throws SettingsException Thrown in case of an error within the configuration.
+ */
+ public static SignatureLayoutHandler getSignatureLayoutHandlerInstance(String bkuIdentifier) throws ConnectorException, SettingsException {
+ if (bkuIdentifier == null) {
+ throw new SettingsException(ErrorCode.MISSING_HEADER_SERVER_USER_AGENT, "Unable to determine type of citizen card environment. Response header \"Server\" resp. \"user-agent\" is missing. Refer to security layer specification 1.2.2, section 3.3.2.");
+ }
+ SignatureLayoutHandler signatureLayoutHandler = (SignatureLayoutHandler) instances.get(bkuIdentifier);
+
+ if (signatureLayoutHandler == null) {
+ SettingsReader sr = SettingsReader.getInstance();
+
+ Vector v = sr.getSettingKeys(SIGNATURE_LAYOUT_CONFIG_KEY_PATTERN);
+ String implValue = null;
+
+ Iterator it = v.iterator();
+ try {
+ while (it.hasNext()) {
+ String subKey = (String) it.next();
+ String key = SIGNATURE_LAYOUT_CONFIG_KEY_PATTERN + "." + subKey;
+ String value = sr.getSetting(key);
+ Pattern p = Pattern.compile(value);
+ if (p.matcher(bkuIdentifier).matches()) {
+ String implKey = SIGNATURE_LAYOUT_CONFIG_KEY_IMPL + "." + subKey;
+ implValue = sr.getSetting(implKey);
+ }
+ }
+ } catch (SettingNotFoundException e) {
+ throw new SettingsException(ErrorCode.INVALID_SIGNATURE_LAYOUT_IMPL_CONFIGURED, e.getMessage());
+ }
+
+ if (implValue == null) {
+ throw new ConnectorException(ErrorCode.BKU_NOT_SUPPORTED, "Unsupported BKU: " + bkuIdentifier);
+ }
+
+ log.debug("Trying to instantiate SignatureLayoutHandler \"" + implValue + "\".");
+
+ try {
+ Class clazz = Class.forName(implValue);
+ Object obj = clazz.newInstance();
+ if (!(obj instanceof SignatureLayoutHandler)) {
+ throw new SettingsException(ErrorCode.INVALID_SIGNATURE_LAYOUT_IMPL_CONFIGURED, "Invalid signature layout implementation (\"" + implValue + "\") configured for bku identifier \"" + bkuIdentifier + "\".");
+ }
+ signatureLayoutHandler = (SignatureLayoutHandler) obj;
+ } catch (InstantiationException e) {
+ throw new SettingsException(ErrorCode.INVALID_SIGNATURE_LAYOUT_IMPL_CONFIGURED, "Error instantiating signature layout implementation (\"" + implValue + "\") configured for bku identifier \"" + bkuIdentifier + "\".");
+ } catch (IllegalAccessException e) {
+ throw new SettingsException(ErrorCode.INVALID_SIGNATURE_LAYOUT_IMPL_CONFIGURED, "Illegal access instantiating signature layout implementation (\"" + implValue + "\") configured for bku identifier \"" + bkuIdentifier + "\".");
+ } catch (ClassNotFoundException e) {
+ throw new SettingsException(ErrorCode.INVALID_SIGNATURE_LAYOUT_IMPL_CONFIGURED, "Unable to find signature layout implementation (\"" + implValue + "\") configured for bku identifier \"" + bkuIdentifier + "\".");
+ }
+
+ log.debug("SignatureLayoutHandler successfully instantiated.");
+ instances.put(bkuIdentifier, signatureLayoutHandler);
+ } else {
+ log.trace("SignatureLayoutHandler has already been instantiated. Returning old instance.");
+ }
+
+ return signatureLayoutHandler;
+
+ }
+
+ /**
+ * Verifies that the bku is supported trying to match the given bku identifier.
+ * @param bkuIdentifier The bku identifier (e.g. <code>citizen-card-environment/1.2 MOCCA/1.1.1</code>).
+ * @throws ConnectorException Thrown in case of an error (e.g. bku not supported).
+ * @throws SettingsException Thrown in case of an error within the configuration.
+ */
+ public static void verifyBKUSupport(String bkuIdentifier) throws ConnectorException, SettingsException {
+ getSignatureLayoutHandlerInstance(bkuIdentifier);
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/atrust/ATrustSignatureLayoutHandler.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/atrust/ATrustSignatureLayoutHandler.java
new file mode 100644
index 0000000..b7cf72b
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/atrust/ATrustSignatureLayoutHandler.java
@@ -0,0 +1,47 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.signaturelayout.atrust;
+
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
+import at.knowcenter.wag.egov.egiz.sig.connectors.ConnectorEnvironment;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject;
+import at.knowcenter.wag.egov.egiz.sig.connectors.moa.MOAHelper;
+import at.knowcenter.wag.egov.egiz.sig.sigid.SimpleIdFormatter;
+import at.knowcenter.wag.egov.egiz.sig.signaturelayout.SignatureLayoutHandler;
+
+/**
+ * Layout handler for atrust bku
+ *
+ * @author dferbas
+ */
+public class ATrustSignatureLayoutHandler implements SignatureLayoutHandler {
+
+ public static final String ETSI_BKA_ATRUST_1_0 = "etsi-bka-atrust-1.0";
+
+ public SignSignatureObject parseCreateXMLSignatureResponse(String xmlResponse,
+ ConnectorEnvironment env) throws ConnectorException {
+ return MOAHelper.parseCreateXMLResponse(xmlResponse, new SimpleIdFormatter(ETSI_BKA_ATRUST_1_0), env);
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/mocca/MOCCASignatureLayout10Handler.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/mocca/MOCCASignatureLayout10Handler.java
new file mode 100644
index 0000000..600b503
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/mocca/MOCCASignatureLayout10Handler.java
@@ -0,0 +1,48 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.signaturelayout.mocca;
+
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
+import at.knowcenter.wag.egov.egiz.sig.connectors.ConnectorEnvironment;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject;
+import at.knowcenter.wag.egov.egiz.sig.connectors.mocca.MOCCAHelper;
+import at.knowcenter.wag.egov.egiz.sig.sigid.DetachedMOCIdFormatter;
+import at.knowcenter.wag.egov.egiz.sig.signaturelayout.SignatureLayoutHandler;
+
+/**
+ * Implementation of a signature layout handler for the first release of mocca.
+ * @author tknall
+ */
+public class MOCCASignatureLayout10Handler implements SignatureLayoutHandler {
+
+ private final static String ALGORITHM_ID = "etsi-moc-1.1";
+
+ /**
+ * Parses the given xmlResponse with respect to the specific signature layout of mocca.
+ */
+ public SignSignatureObject parseCreateXMLSignatureResponse(String xmlResponse, ConnectorEnvironment env) throws ConnectorException {
+ return MOCCAHelper.parseCreateXMLResponse(xmlResponse, new DetachedMOCIdFormatter(ALGORITHM_ID), env);
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/mocca/OldMOCCASignatureLayoutHandler.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/mocca/OldMOCCASignatureLayoutHandler.java
new file mode 100644
index 0000000..988a930
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/mocca/OldMOCCASignatureLayoutHandler.java
@@ -0,0 +1,48 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.signaturelayout.mocca;
+
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
+import at.knowcenter.wag.egov.egiz.sig.connectors.ConnectorEnvironment;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject;
+import at.knowcenter.wag.egov.egiz.sig.connectors.mocca.MOCCAHelper;
+import at.knowcenter.wag.egov.egiz.sig.sigid.DetachedMOCIdFormatter;
+import at.knowcenter.wag.egov.egiz.sig.signaturelayout.SignatureLayoutHandler;
+
+/**
+ * Implementation of a signature layout handler for the beta version of mocca.
+ * @author tknall
+ */
+public class OldMOCCASignatureLayoutHandler implements SignatureLayoutHandler {
+
+ private final static String ALGORITHM_ID = "etsi-moc-1.0";
+
+ /**
+ * Parses the given xmlResponse with respect to the specific signature layout of mocca.
+ */
+ public SignSignatureObject parseCreateXMLSignatureResponse(String xmlResponse, ConnectorEnvironment env) throws ConnectorException {
+ return MOCCAHelper.parseCreateXMLResponse(xmlResponse, new DetachedMOCIdFormatter(ALGORITHM_ID), env);
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/td/TrustDeskSignatureLayoutHandler.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/td/TrustDeskSignatureLayoutHandler.java
new file mode 100644
index 0000000..a13ce52
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/td/TrustDeskSignatureLayoutHandler.java
@@ -0,0 +1,46 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.signaturelayout.td;
+
+import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
+import at.knowcenter.wag.egov.egiz.sig.connectors.ConnectorEnvironment;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUHelper;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject;
+import at.knowcenter.wag.egov.egiz.sig.sigid.DetachedIdFormatter;
+import at.knowcenter.wag.egov.egiz.sig.signaturelayout.SignatureLayoutHandler;
+
+/**
+ * Implementation of a signature layout handler for trustDesk basic.
+ * @author tknall
+ */
+public class TrustDeskSignatureLayoutHandler implements SignatureLayoutHandler {
+
+ /**
+ * Parses the given xmlResponse with respect to the specific signature layout of trustDesk basic.
+ */
+ public SignSignatureObject parseCreateXMLSignatureResponse(String xmlResponse, ConnectorEnvironment env) throws ConnectorException {
+ return BKUHelper.parseCreateXMLResponse(xmlResponse, new DetachedIdFormatter(), env);
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signatureobject/AdditionalSignatureInformation.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signatureobject/AdditionalSignatureInformation.java
new file mode 100644
index 0000000..7c86e62
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signatureobject/AdditionalSignatureInformation.java
@@ -0,0 +1,41 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.signatureobject;
+
+import java.security.cert.X509Certificate;
+
+/**
+ * @author wprinz
+ *
+ */
+public interface AdditionalSignatureInformation
+{
+
+ public String getName();
+
+ public X509Certificate getX509Certificate();
+
+ // dferbas: baik
+ public String getSigAlgorithm();
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signatureobject/AlgorithmSignatureInformation.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signatureobject/AlgorithmSignatureInformation.java
new file mode 100644
index 0000000..7d81758
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signatureobject/AlgorithmSignatureInformation.java
@@ -0,0 +1,33 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.signatureobject;
+
+/**
+ * @author wprinz
+ *
+ */
+public interface AlgorithmSignatureInformation
+{
+public String getSigKZ();
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signatureobject/ConnectorSignatureInformation.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signatureobject/ConnectorSignatureInformation.java
new file mode 100644
index 0000000..6b5ef18
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signatureobject/ConnectorSignatureInformation.java
@@ -0,0 +1,34 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.signatureobject;
+
+/**
+ *
+ * @author wprinz
+ *
+ */
+public interface ConnectorSignatureInformation
+{
+ public String getSigID();
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signatureobject/MandatorySignatureInformation.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signatureobject/MandatorySignatureInformation.java
new file mode 100644
index 0000000..2da1b02
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signatureobject/MandatorySignatureInformation.java
@@ -0,0 +1,40 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.signatureobject;
+
+/**
+ * Encapsulates all information required to define a signature.
+ *
+ * @author wprinz
+ */
+public interface MandatorySignatureInformation
+{
+ public String getDate();
+
+ public String getSignatureValue();
+
+ public String getIssuer();
+
+ public String getSerialNumber();
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signatureobject/SignatureObjectHelper.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signatureobject/SignatureObjectHelper.java
new file mode 100644
index 0000000..6a8afc0
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/signatureobject/SignatureObjectHelper.java
@@ -0,0 +1,81 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.sig.signatureobject;
+
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.knowcenter.wag.egov.egiz.PdfASID;
+import at.knowcenter.wag.egov.egiz.exceptions.SignatureException;
+import at.knowcenter.wag.egov.egiz.exceptions.SignatureTypesException;
+import at.knowcenter.wag.egov.egiz.sig.SignatureObject;
+import at.knowcenter.wag.egov.egiz.sig.X509Cert;
+import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject;
+
+/**
+ * Contains helper methods for dealing with signature objects.
+ *
+ * @author wprinz
+ *
+ */
+public final class SignatureObjectHelper
+{
+
+ public static SignatureObject convertSignSignatureObjectToSignatureObject (SignSignatureObject sso, String signature_type) throws SignatureTypesException, SignatureException
+ {
+ SignatureObject so = new SignatureObject();
+ so.setSigType(signature_type);
+ so.initByType();
+ so.setSignationDate(sso.getDate());
+ so.setSignationIssuer(sso.getIssuer());
+ so.setSignationSerialNumber(sso.getSerialNumber());
+ so.setSignationValue(sso.getSignatureValue());
+ so.setSignationIDs(sso.getSigID());
+ so.setKZ(new PdfASID(sso.getSigKZ()));
+ so.setSignationName(sso.getName());
+
+ so.setSigAlg(sso.getSigAlgorithm());
+
+ so.setX509Certificate(sso.getX509Certificate());
+
+ return so;
+ }
+
+ public static SignSignatureObject convertSignatureObjectToSignSignatureObject (SignatureObject so) throws SignatureException
+ {
+ SignSignatureObject sso = new SignSignatureObject();
+ sso.date = so.getSignationDate();
+ sso.signatureValue = so.getSignationValue();
+ sso.issuer = so.getSignationIssuer();
+ X509Cert cert = so.getX509Cert();
+ if (cert == null)
+ {
+ throw new SignatureException(ErrorCode.CERTIFICATE_NOT_FOUND, "so.getX509Cert returned null. No cert found.");
+ }
+ sso.x509Certificate = cert.getX509Certificate();
+ sso.id = so.getSignationIds();
+ sso.kz = so.getKZ() == null ? null : so.getKZ().toString();
+ sso.sigAlgorithm = so.getSigAlg();
+
+ return sso;
+ }
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/table/Entry.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/table/Entry.java
new file mode 100644
index 0000000..289a7f6
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/table/Entry.java
@@ -0,0 +1,235 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: Entry.java,v 1.3 2006/08/25 17:08:19 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.table;
+
+import java.io.Serializable;
+
+/**
+ * This class implements a table entry for different types. A table entry can be
+ * styled and setting there column dimensions. The default value for the column
+ * dimension is 1. To declare the type of the entry use the public
+ * <code>TYPE_</code> definitions.
+ *
+ * @author wlackner
+ */
+public class Entry implements Serializable
+{
+
+ /**
+ * SVUID.
+ */
+ private static final long serialVersionUID = -7952755200668528348L;
+
+ /**
+ * Type for a text entry.
+ */
+ public final static int TYPE_CAPTION = 0;
+
+ /**
+ * Type for a text entry.
+ */
+ public final static int TYPE_VALUE = 1;
+
+ /**
+ * Type for an image entry.
+ */
+ public final static int TYPE_IMAGE = 2;
+
+ /**
+ * Type for a table entry.
+ */
+ public final static int TYPE_TABLE = 3;
+
+ /**
+ * The type info holder, default value is 0!
+ */
+ private int type_ = 0;
+
+ /**
+ * The entry value.
+ */
+ private Object value_ = null;
+
+ /**
+ * The key value
+ */
+ private String key_ = null;
+
+ /**
+ * The entry style information.
+ */
+ private Style style_ = null;
+
+ /**
+ * The column dimension.
+ */
+ private int colSpan_ = 1;
+
+ /**
+ * Text wrap indicator, default is <code>false</code>.
+ */
+ private boolean noWrap_ = false;
+
+ /**
+ * The empty constructor.
+ */
+ public Entry()
+ {
+ }
+
+ /**
+ * A constructor setting the type and the value.
+ *
+ * @param type
+ * the entry type to set
+ * @param value
+ * the entry value to set
+ */
+ public Entry(int type, Object value, String key)
+ {
+ type_ = type;
+ value_ = value;
+ key_ = key;
+ }
+
+ /**
+ * @return Returns the entry style.
+ */
+ public Style getStyle()
+ {
+ return style_;
+ }
+
+ /**
+ * @param style
+ * The style to set.
+ */
+ public void setStyle(Style style)
+ {
+ style_ = style;
+ }
+
+ /**
+ * @return Returns the entry type.
+ */
+ public int getType()
+ {
+ return type_;
+ }
+
+ /**
+ * @param type
+ * The type to set.
+ */
+ public void setType(int type)
+ {
+ type_ = type;
+ }
+
+ /**
+ * @return Returns the entry value.
+ */
+ public Object getValue()
+ {
+ return value_;
+ }
+
+ /**
+ * @param value
+ * The value to set.
+ */
+ public void setValue(Object value)
+ {
+ value_ = value;
+ }
+
+ /**
+ * @return Returns the key.
+ */
+
+ public String getKey()
+ {
+ return key_;
+ }
+
+ /**
+ * @param key
+ * The key to set.
+ */
+ public void setKey(String key)
+ {
+ key_ = key;
+ }
+
+ /**
+ * @return Returns the colSpan.
+ */
+ public int getColSpan()
+ {
+ return colSpan_;
+ }
+
+ /**
+ * @param colSpan
+ * The colSpan to set.
+ */
+ public void setColSpan(int colSpan)
+ {
+ colSpan_ = colSpan;
+ }
+
+ /**
+ * @return Returns the wrap indicator.
+ */
+ public boolean isNoWrap()
+ {
+ return noWrap_;
+ }
+
+ /**
+ * @param noWrap
+ * The wrap indicator to set.
+ */
+ public void setNoWrap(boolean noWrap)
+ {
+ noWrap_ = noWrap;
+ }
+
+ /**
+ * The toString method, used for tests or debugging.
+ */
+ public String toString()
+ {
+ Object obj = getValue();
+ String value = null;
+ if (obj != null)
+ {
+ value = obj.toString();
+ }
+ return "Type:" + getType() + " Value:" + value + " ColSpan:" + getColSpan();
+ }
+
+} \ No newline at end of file
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/table/Style.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/table/Style.java
new file mode 100644
index 0000000..10686b6
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/table/Style.java
@@ -0,0 +1,630 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: Style.java,v 1.3 2006/08/25 17:08:19 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.table;
+
+import java.awt.Color;
+import java.io.Serializable;
+
+/**
+ * This class implements an abstract style definiton used in tables or table entrys. Predefined
+ * values exists for valign and halign. Color definitions uses the native awt color declarations.
+ * <br>
+ * The predefined keys are used in the setting definition file to style tables and table entries.
+ * <br>
+ * It provides an static method to inherit style informations from a given style object.
+ * {@link at.knowcenter.wag.egov.egiz.table.Style#doInherit}
+ *
+ *
+ * @author wlackner
+ * @see java.awt.Color
+ */
+public class Style implements Serializable {
+
+// 03.11.2010 changed by exthex - added valuevalign and valuehalign to allow separate layout for value and non-value cells.
+// Also the hardcoded default values for halign and valign were removed to allow proper inheritment.
+// 04.11.2010 changed by exthex - added imagevalign and imagehalign analog to valuevalign/valuehalign
+
+ /**
+ * SVUID.
+ */
+ private static final long serialVersionUID = 5855722896712428387L;
+
+ /**
+ * valign statement key top
+ */
+ public final static String TOP = "top";
+ /**
+ * valign statement key middle
+ */
+ public final static String MIDDLE = "middle";
+ /**
+ * valign statement key bottom
+ */
+ public final static String BOTTOM = "bottom";
+ /**
+ * halign statement key left
+ */
+ public final static String LEFT = "left";
+ /**
+ * halign statement key center
+ */
+ public final static String CENTER = "center";
+ /**
+ * halign statement key right
+ */
+ public final static String RIGHT = "right";
+
+ /**
+ * bgcolor key
+ */
+ public final static String BGCOLOR = "bgcolor";
+ /**
+ * halign key
+ */
+ public final static String HALIGN = "halign";
+ /**
+ * valign key
+ */
+ public final static String VALIGN = "valign";
+
+ /**
+ * value halign key
+ */
+ public final static String VALUEHALIGN = "valuehalign";
+ /**
+ * value valign key
+ */
+ public final static String VALUEVALIGN = "valuevalign";
+
+ /**
+ * image halign key
+ */
+ public final static String IMAGEHALIGN = "imagehalign";
+ /**
+ * image valign key
+ */
+ public final static String IMAGEVALIGN = "imagevalign";
+ /**
+ * padding key, default padding = 1
+ */
+ public final static String PADDING = "padding";
+ /**
+ * border key, default border = 1;<br>
+ * The border value is one value for all border lines of an entry or table! <br>
+ * No separte definitions for top, right, bottom or left are possible.
+ */
+ public final static String BORDER = "border";
+
+ /**
+ * Font key
+ */
+ public final static String FONT = "font";
+
+ /**
+ * The value font key.
+ */
+ public final static String VALUEFONT = "valuefont";
+
+ /**
+ * The imageScaleToFit key.
+ */
+ public final static String IMAGE_SCALE_TO_FIT = "imagescaletofit";
+
+ /**
+ * Font name HELVETICA
+ */
+ public final static String HELVETICA = "HELVETICA";
+ /**
+ * Font name TIMES_ROMAN
+ */
+ public final static String TIMES_ROMAN = "TIMES_ROMAN";
+ /**
+ * Font name COURIER
+ */
+ public final static String COURIER = "COURIER";
+ /**
+ * Font type NORMAL
+ */
+ public final static String NORMAL = "NORMAL";
+ /**
+ * Font type BOLD
+ */
+ public final static String BOLD = "BOLD";
+ /**
+ * Font type ITALIC
+ */
+ public final static String ITALIC = "ITALIC";
+ /**
+ * Font type BOLDITALIC
+ */
+ public final static String BOLDITALIC = "BOLDITALIC";
+ /**
+ * Font type UNDERLINE
+ */
+ public final static String UNDERLINE = "UNDERLINE";
+ /**
+ * Font type STRIKETHRU
+ */
+ public final static String STRIKETHRU = "STRIKETHRU";
+
+
+ /**
+ * all paddings initialized with the default padding value (1)
+ */
+ private static final float DEFAULT_PADDING = 1;
+ /**
+ * all borders initialized with the default border value (1)
+ */
+ private static final float DEFAULT_BORDER = 1;
+ /**
+ * The background color definition.
+ */
+ private Color bgColor_ = null;
+ /**
+ * The current padding value -> initialized with the default padding value
+ */
+ private float padding_ = DEFAULT_PADDING;
+ /**
+ * The current halign value
+ */
+ private String hAlign_ = null;
+ /**
+ * The current valign value
+ */
+ private String vAlign_ = null;
+ /**
+ * The current valuehalign value
+ */
+ private String valueHAlign_ = null;
+ /**
+ * The current valuevalign value
+ */
+ private String valueVAlign_ = null;
+ /**
+ * The current imagehalign value
+ */
+ private String imageHAlign_ = null;
+ /**
+ * The current imagevalign value
+ */
+ private String imageVAlign_ = null;
+ /**
+ * The current border value -> initialized with the default border value
+ */
+ private float border_ = DEFAULT_BORDER;
+ /**
+ * The font string of the style definition
+ */
+ private String font_ = null;
+ /**
+ * The font string of the value font.
+ */
+ private String valuefont_ = null;
+ /**
+ * The scaleToFit dimensions to be applied for image-cells.
+ */
+ private ImageScaleToFit imageScaleToFit_ = null;
+
+ /**
+ * The empty constructor.
+ */
+ public Style() {
+ }
+
+ /**
+ * Set a style attribute. The style attribute must be one of the public definitions
+ *
+ * @param id the style attribute to set
+ * @param value the style value to set for the given attribute
+ */
+ public void setStyle(String id, String value) {
+ if (BGCOLOR.equals(id)) {
+ String[] col_strg = value.split(" ");
+ if (col_strg.length == 3) {
+ int r = Integer.parseInt(col_strg[0]);
+ int g = Integer.parseInt(col_strg[1]);
+ int b = Integer.parseInt(col_strg[2]);
+ if (r < 256 && g < 256 && b < 256 && r >= 0 && g >= 0 && b >= 0) {
+ bgColor_ = new Color(r, g, b);
+ }
+ }
+ }
+ if (HALIGN.equals(id)) {
+ if (LEFT.equals(value) || CENTER.equals(value) || RIGHT.equals(value)) {
+ hAlign_ = value;
+ }
+ }
+ if (VALIGN.equals(id)) {
+ if (TOP.equals(value) || MIDDLE.equals(value) || BOTTOM.equals(value)) {
+ vAlign_ = value;
+ }
+ }
+ if (VALUEHALIGN.equals(id)) {
+ if (LEFT.equals(value) || CENTER.equals(value) || RIGHT.equals(value)) {
+ valueHAlign_ = value;
+ }
+ }
+ if (VALUEVALIGN.equals(id)) {
+ if (TOP.equals(value) || MIDDLE.equals(value) || BOTTOM.equals(value)) {
+ valueVAlign_ = value;
+ }
+ }
+ if (IMAGEHALIGN.equals(id)) {
+ if (LEFT.equals(value) || CENTER.equals(value) || RIGHT.equals(value)) {
+ imageHAlign_ = value;
+ }
+ }
+ if (IMAGEVALIGN.equals(id)) {
+ if (TOP.equals(value) || MIDDLE.equals(value) || BOTTOM.equals(value)) {
+ imageVAlign_ = value;
+ }
+ }
+ if (PADDING.equals(id)) {
+ padding_ = Float.parseFloat(value);
+ }
+ if (BORDER.equals(id)) {
+ border_ = Float.parseFloat(value);
+ }
+ if (FONT.equals(id)) {
+ font_ = value;
+ }
+ if (VALUEFONT.equals(id)) {
+ valuefont_ = value;
+ }
+ if (IMAGE_SCALE_TO_FIT.equals(id))
+ {
+ imageScaleToFit_ = parseImageScaleToFit(value);
+ }
+ }
+
+ /**
+ * @return Returns the bgColor.
+ */
+ public Color getBgColor() {
+ return bgColor_;
+ }
+
+ /**
+ * @param bgColor The bgColor to set.
+ */
+ public void setBgColor(Color bgColor) {
+ bgColor_ = bgColor;
+ }
+
+ /**
+ * @return Returns the hAlign.
+ */
+ public String getHAlign() {
+ return hAlign_;
+ }
+
+ /**
+ * @param align The hAlign to set.
+ */
+ public void setHAlign(String align) {
+ hAlign_ = align;
+ }
+
+ /**
+ * @return Returns the padding.
+ */
+ public float getPadding() {
+ return padding_;
+ }
+
+ /**
+ * @param padding The padding to set.
+ */
+ public void setPadding(float padding) {
+ padding_ = padding;
+ }
+
+ /**
+ * @return Returns the vAlign.
+ */
+ public String getVAlign() {
+ return vAlign_;
+ }
+
+ /**
+ * @param align The vAlign to set.
+ */
+ public void setVAlign(String align) {
+ vAlign_ = align;
+ }
+
+ /**
+ * @return Returns the border.
+ */
+ public float getBorder() {
+ return border_;
+ }
+
+ /**
+ * @param border The border to set.
+ */
+ public void setBorder(float border) {
+ border_ = border;
+ }
+
+
+ /**
+ * @return Returns the font.
+ */
+ public String getFont() {
+ return font_;
+ }
+
+ /**
+ * @param font The font to set.
+ */
+ public void setFont(String font) {
+ font_ = font;
+ }
+
+
+ /**
+ * Returns the value font.
+ * @return Returns the value font.
+ */
+ public String getValueFont()
+ {
+ return valuefont_;
+ }
+
+ /**
+ * Sets the value font.
+ * @param valuefont The value font to be set.
+ */
+ public void setValueFont(String valuefont)
+ {
+ this.valuefont_ = valuefont;
+ }
+
+ /**
+ * @param align The valueHAlign to set.
+ */
+ public void setValueHAlign(String align) {
+ valueHAlign_ = align;
+ }
+
+ /**
+ * Returns the value halign
+ * @return Returns the value halign
+ */
+ public String getValueHAlign() {
+ return valueHAlign_;
+ }
+
+ /**
+ * @param align The valueVAlign to set.
+ */
+ public void setValueVAlign(String align) {
+ valueVAlign_ = align;
+ }
+
+ /**
+ * Returns the value valign
+ * @return Returns the value valign
+ */
+ public String getValueVAlign() {
+ return valueVAlign_;
+ }
+
+ /**
+ * @param align The imageHAlign to set.
+ */
+ public void setImageHAlign(String align) {
+ imageHAlign_ = align;
+ }
+
+ /**
+ * Returns the image halign
+ * @return Returns the image halign
+ */
+ public String getImageHAlign() {
+ return imageHAlign_;
+ }
+
+ /**
+ * @param align The imageVAlign to set.
+ */
+ public void setImageVAlign(String align) {
+ imageVAlign_ = align;
+ }
+
+ /**
+ * Returns the image valign
+ * @return Returns the image valign
+ */
+ public String getImageVAlign() {
+ return imageVAlign_;
+ }
+
+ /**
+ * Returns the scaleToFit dimensions to be applied for image-cells.
+ * @return Returns the scaleToFit dimensions to be applied for image-cells.
+ */
+ public ImageScaleToFit getImageScaleToFit()
+ {
+ return this.imageScaleToFit_;
+ }
+
+ /**
+ * Sets the scaleToFit dimensions to be applied for image-cells.
+ * @param imageScaleToFit_ The scaleToFit dimensions to be applied for image-cells.
+ */
+ public void setImageScaleToFit(ImageScaleToFit imageScaleToFit)
+ {
+ this.imageScaleToFit_ = imageScaleToFit;
+ }
+
+ /**
+ * The toString method, used for tests or debugging.
+ */
+ public String toString() {
+ return "bgcolor:" + getBgColor() + " halign:" + getHAlign() + " valign:" + getVAlign() + " padding:" + getPadding() + " border:" + getBorder() + " font:" + getFont() + " valuefont:" + getValueFont() + " imageScaleToFit:" + getImageScaleToFit();
+ }
+
+ /**
+ * This method inherits all style attributes (values) from a given style object.
+ *
+ * <p>
+ * A new style object is created that receives the properly inherited styles.
+ * </p>
+ * <p>
+ * If a value is not defined in the <code>baseStyle</code> object it would be inhert from the <code>inheritStyle</code> object.
+ * </p>
+ *
+ * @param baseStyle the style object that serves as a primary style source.
+ * @param inheritStyle the style object that serves as a secondary style source in case a style attribute is not defined on the primary style source.
+ * @param isValue
+ * @return Returns a new Style object being fully equipped with styles.
+ */
+ public static Style doInherit(Style baseStyle, Style inheritStyle) {
+ Style newStyle = new Style();
+
+ if (baseStyle != null)
+ {
+ newStyle.setBgColor(baseStyle.getBgColor());
+ newStyle.setBorder(baseStyle.getBorder());
+ newStyle.setFont(baseStyle.getFont());
+ newStyle.setHAlign(baseStyle.getHAlign());
+ newStyle.setImageHAlign(baseStyle.getImageHAlign());
+ newStyle.setImageVAlign(baseStyle.getImageVAlign());
+ newStyle.setPadding(baseStyle.getPadding());
+ newStyle.setVAlign(baseStyle.getVAlign());
+ newStyle.setValueFont(baseStyle.getValueFont());
+ newStyle.setValueHAlign(baseStyle.getValueHAlign());
+ newStyle.setValueVAlign(baseStyle.getValueVAlign());
+ newStyle.setImageScaleToFit(baseStyle.getImageScaleToFit());
+ }
+
+ if (inheritStyle != null)
+ {
+ if (newStyle.getBgColor() == null) { newStyle.setBgColor(inheritStyle.getBgColor()); }
+ if (newStyle.getBorder() == DEFAULT_BORDER) { newStyle.setBorder(inheritStyle.getBorder()); }
+ if (newStyle.getFont() == null) { newStyle.setFont(inheritStyle.getFont()); }
+ if (newStyle.getHAlign() == null) { newStyle.setHAlign(inheritStyle.getHAlign()); }
+ if (newStyle.getImageHAlign() == null) { newStyle.setImageHAlign(inheritStyle.getImageHAlign()); }
+ if (newStyle.getImageVAlign() == null) { newStyle.setImageVAlign(inheritStyle.getImageVAlign()); }
+ if (newStyle.getPadding() == DEFAULT_PADDING) { newStyle.setPadding(inheritStyle.getPadding()); }
+ if (newStyle.getVAlign() == null) { newStyle.setVAlign(inheritStyle.getVAlign()); }
+ if (newStyle.getValueFont() == null) { newStyle.setValueFont(inheritStyle.getValueFont()); }
+ if (newStyle.getValueHAlign() == null) { newStyle.setValueHAlign(inheritStyle.getValueHAlign()); }
+ if (newStyle.getValueVAlign() == null) { newStyle.setValueVAlign(inheritStyle.getValueVAlign()); }
+ if (newStyle.getImageScaleToFit() == null) { newStyle.setImageScaleToFit(inheritStyle.getImageScaleToFit()); }
+ }
+
+ return newStyle;
+ }
+
+ protected static ImageScaleToFit parseImageScaleToFit (String imageScaleToFit)
+ {
+ if (imageScaleToFit == null || imageScaleToFit.length() == 0 || imageScaleToFit.trim().length() == 0)
+ {
+ return null;
+ }
+
+ String [] dimensions = imageScaleToFit.split(";");
+ if (dimensions.length != 2)
+ {
+ return null;
+ }
+
+ float width = Float.parseFloat(dimensions[0]);
+ float height = Float.parseFloat(dimensions[0]);
+
+ return new ImageScaleToFit(width, height);
+ }
+
+ /**
+ * Holds the width and the height an image can be scaled to fit.
+ *
+ * @author wprinz
+ */
+ public static class ImageScaleToFit
+ {
+ /**
+ * The width.
+ */
+ protected float width;
+
+ /**
+ * The height.
+ */
+ protected float height;
+
+ /**
+ * Constructor.
+ *
+ * @param width The width.
+ * @param height The height.
+ */
+ public ImageScaleToFit(float width, float height)
+ {
+ this.width = width;
+ this.height = height;
+ }
+
+ /**
+ * Returns the width.
+ * @return Returns the width.
+ */
+ public float getWidth()
+ {
+ return this.width;
+ }
+
+ /**
+ * Sets the width.
+ * @param width The width to set.
+ */
+ public void setWidth(float width)
+ {
+ this.width = width;
+ }
+
+ /**
+ * Returns the height.
+ * @return Returns the height.
+ */
+ public float getHeight()
+ {
+ return this.height;
+ }
+
+ /**
+ * Sets the height.
+ * @param height The height to set.
+ */
+ public void setHeight(float height)
+ {
+ this.height = height;
+ }
+
+ }
+} \ No newline at end of file
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/table/Table.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/table/Table.java
new file mode 100644
index 0000000..29d1c9c
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/table/Table.java
@@ -0,0 +1,223 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: Table.java,v 1.2 2006/08/25 17:08:19 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.table;
+
+import java.io.Serializable;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.ArrayList;
+
+/**
+ * This class implements an abstract table definition. The table contains table
+ * rows and the table rows contains the table entries. A table can be styled and
+ * a relative column width can be set.
+ *
+ * @author wlackner
+ * @see at.knowcenter.wag.egov.egiz.table.Style
+ * @see at.knowcenter.wag.egov.egiz.table.Entry
+ */
+public class Table implements Serializable
+{
+
+ /**
+ * SVUID.
+ */
+ private static final long serialVersionUID = 8488947943674086618L;
+
+ /**
+ * The table column settings.
+ */
+ private float[] colsRelativeWith_ = null;
+
+ /**
+ * The row definitions.
+ */
+ private Map rows_ = new HashMap();
+
+ /**
+ * The table width.
+ */
+ private float width_ = 100;
+
+ /**
+ * The table style.
+ */
+ private Style style_ = null;
+
+ /**
+ * Number of columns that are defined for the current table.
+ */
+ private int maxCols_ = 0;
+
+ /**
+ * A table name.
+ */
+ private String name_ = null;
+
+ /**
+ * The table constructor init by a table name.
+ *
+ * @param name
+ * the name for the table.
+ */
+ public Table(String name)
+ {
+ name_ = name;
+ }
+
+ /**
+ * The width of the columns are relative to each other. This means the values
+ * are summarized and divided into portions of columns used. <br>
+ * Example: <code>[1,4]</code> means the second column is four times wider
+ * than the first column.
+ *
+ * @return Returns the relative width of the columns
+ */
+ public float[] getColsRelativeWith()
+ {
+ return colsRelativeWith_;
+ }
+
+ /**
+ * The width of the columns are relative to each other. This means the values
+ * are summarized and divided into portions of columns used. <br>
+ * Example: <code>[10,90]</code> means the first colum consumes 10% and the
+ * second column consumes 90% of the table width. <br>
+ * The relative width of the columns to set.
+ */
+ public void setColsRelativeWith(float[] cols)
+ {
+ colsRelativeWith_ = cols;
+ }
+
+ /**
+ * @return Returns the style.
+ */
+ public Style getStyle()
+ {
+ return style_;
+ }
+
+ /**
+ * @param style
+ * The style to set.
+ */
+ public void setStyle(Style style)
+ {
+ style_ = style;
+ }
+
+ /**
+ * @return Returns the width.
+ */
+ public float getWidth()
+ {
+ return width_;
+ }
+
+ /**
+ * @param width
+ * The width to set.
+ */
+ public void setWidth(float width)
+ {
+ width_ = width;
+ }
+
+ /**
+ * @return Returns the maxCols.
+ */
+ public int getMaxCols()
+ {
+ return maxCols_;
+ }
+
+ /**
+ * @return Returns the name.
+ */
+ public String getName()
+ {
+ return name_;
+ }
+
+ /**
+ * This method returns a sorted row list beginning with the row number 1. The
+ * entrys in a row also stored in a <code>{@link ArrayList}</code>.
+ *
+ * @return Returns the sorted (by row number) table rows.
+ */
+ public ArrayList getRows()
+ {
+ ArrayList rows = new ArrayList();
+ for (int row_idx = 1; row_idx <= rows_.size(); row_idx++)
+ {
+ ArrayList row = (ArrayList) rows_.get("" + row_idx);
+ rows.add(row);
+ }
+ return rows;
+ }
+
+ /**
+ * Add a comlete table row to the current table. Be carefull usding the
+ * correct row number because no check is done if a row with the given row
+ * number does exist! In that case the stored row would be replaced!
+ *
+ * @param rowNumber
+ * the row number to store the row entries
+ * @param row
+ * the entry list to store
+ */
+ public void addRow(String rowNumber, ArrayList row)
+ {
+ rows_.put(rowNumber, row);
+ if (row.size() > maxCols_)
+ {
+ maxCols_ = row.size();
+ }
+ }
+
+ /**
+ * The toString method, used for tests or debugging.
+ */
+ public String toString()
+ {
+ String the_string = "\n#### TABLE " + name_ + " BEGIN #####";
+ the_string += " Width:" + width_ + " max cols:" + maxCols_ + " cols:" + colsRelativeWith_;
+ the_string += "\nStyle:" + style_;
+ ArrayList rows = getRows();
+ for (int row_idx = 0; row_idx < rows.size(); row_idx++)
+ {
+ ArrayList row = (ArrayList) rows.get(row_idx);
+ String row_prefix = "\n ++ ROW " + row_idx + " ++ ";
+ for (int entry_idx = 0; entry_idx < row.size(); entry_idx++)
+ {
+ the_string += row_prefix + ((Entry) row.get(entry_idx)).toString();
+ }
+ }
+ the_string += "\n#### TABLE " + name_ + " END #####";
+ return the_string;
+ }
+} \ No newline at end of file
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/tools/CodingHelper.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/tools/CodingHelper.java
new file mode 100644
index 0000000..5132021
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/tools/CodingHelper.java
@@ -0,0 +1,301 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: CodingHelper.java,v 1.6 2006/10/11 07:52:36 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.tools;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import org.apache.commons.codec.binary.Base64;
+
+import at.gv.egiz.pdfas.framework.input.DataSource;
+import at.gv.egiz.pdfas.impl.input.helper.DataSourceHelper;
+
+/**
+ * This class provides encoding and decoding methods and other coding methods.
+ * All methods are static!
+ *
+ * @author wlackner
+ */
+public class CodingHelper
+{
+
+ /**
+ * Static Base64 object
+ */
+ private static Base64 b64 = new Base64();
+
+ /**
+ * This method encodes a given Unicode (Java) String to UTF-8 bytes and then
+ * encodes these UTF-8 bytes to a Base64 US-ASCII (Java) String.
+ *
+ * @param plain_string
+ * to be encoded
+ * @return the UTF-8 and Base64 encoded string
+ */
+ public static String encodeUTF8AsBase64(String plain_string)
+ {
+ try
+ {
+ byte[] utf8_bytes = plain_string.getBytes("UTF-8");
+ byte[] base64_bytes = b64.encode(utf8_bytes);
+ String encoded_string = new String(base64_bytes, "US-ASCII");
+ return encoded_string;
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * This method decodes the UTF-8 bytes from a Base64 US-ASCII (Java) String
+ * and decodes the UTF-8 bytes to a unicode (Java) String.
+ *
+ * @param encoded_string
+ * to be decoded
+ * @return the Base64 and UTF-8 decoded string
+ */
+ public static String decodeUTF8FromBase64(String encoded_string)
+ {
+ try
+ {
+ byte[] base64_bytes = encoded_string.getBytes("US-ASCII");
+ byte[] utf8_bytes = b64.decode(base64_bytes);
+ String plain_string = new String(utf8_bytes, "UTF-8");
+ return plain_string;
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ }
+ }
+
+ // /**
+ // * This method encodes a given string UTF-8
+ // *
+ // * @param theString to be encoded
+ // * @return the UTF-8 encoded string
+ // */
+ // public static byte[] encodeUTF8(String theString) {
+ // byte[] utf8 = null;
+ // try {
+ // utf8 = theString.getBytes("UTF-8");
+ // } catch (UnsupportedEncodingException e) {
+ // e.printStackTrace();
+ // }
+ // return utf8;
+ // }
+
+ // /**
+ // * This method decodes a given UTF-8 string
+ // *
+ // * @param theString to be decoded
+ // * @return the decoded UTF-8 string
+ // */
+ // public static String decodeUTF8(String theString) {
+ // byte[] ba = theString.getBytes();
+ // String the_string = decodeUTF8(ba);
+ // if (the_string != null) {
+ // return the_string;
+ // }
+ // return theString;
+ // }
+
+ // /**
+ // * This method decodes a given UTF-8 byte array
+ // *
+ // * @param ba the byte array to be decoded
+ // * @return the decoded UTF-8 string
+ // */
+ // public static String decodeUTF8(byte[] ba) {
+ // String the_string = null;
+ // try {
+ // the_string = new String(ba, "UTF-8");
+ // } catch (UnsupportedEncodingException e) {
+ // e.printStackTrace();
+ // }
+ // return the_string;
+ // }
+
+ /**
+ * This method decodes a given Base64 string.
+ *
+ * <p>
+ * Note that the given String must only contain Base64 characters. (The string
+ * will be converted to a byte array of "US-ASCII" (7 bit) bytes and then this
+ * byte array will be decoded using the Base64 algorithm.
+ * </p>
+ *
+ * @param theString
+ * to be decoded
+ * @return a Base64 decoded byte array
+ */
+ public static byte[] decodeBase64(String theString)
+ {
+ try
+ {
+ byte[] base64_bytes = theString.getBytes("US-ASCII");
+ return b64.decode(base64_bytes);
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ e.printStackTrace();
+ throw new RuntimeException("Very Strange: US-ASCII encoding not supported???", e);
+ }
+ }
+
+ /**
+ * This method decodes a given Base64 byte array
+ *
+ * @param ba
+ * the byte array to be decoded
+ * @return a Base64 decoded byte array
+ */
+ public static byte[] decodeBase64(byte[] ba)
+ {
+ return b64.decode(ba);
+ }
+
+ /**
+ * This method encodes a given byte array Base64
+ *
+ * @param plainString
+ * the byte array to be encoded
+ * @return the Base64 encoded string
+ */
+ public static String encodeBase64(byte[] plainString)
+ {
+ try
+ {
+ byte[] base64_bytes = b64.encode(plainString);
+ return new String(base64_bytes, "US-ASCII");
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ e.printStackTrace();
+ throw new RuntimeException("Very Strange: US-ASCII encoding not supported???", e);
+ }
+ }
+
+ // dferbas
+ /**
+ * This method builds an hash value of a given byte array.
+ *
+ * @param data
+ * the byte array to build the hash value for
+ * @param hashAlg hash algorithm for {@link MessageDigest} e.g. "SHA-1"
+ * @return the calculated hash value as a byte array
+ * @see MessageDigest
+ */
+ public static byte[] buildDigest(byte[] data, String hashAlg)
+ {
+ MessageDigest digester = null;
+ try
+ {
+ digester = MessageDigest.getInstance(hashAlg);
+ digester.update(data);
+ return digester.digest();
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ // dferbas
+ /**
+ * This method builds an hash value of a given byte array.
+ * @param input
+ * @param hashAlg hashAlg hash algorithm for {@link MessageDigest} e.g. "SHA-1"
+ * @return the calculated hash value as a byte array
+ * @throws IOException
+ */
+ public static byte[] buildDigest(DataSource input, String hashAlg) throws IOException
+ {
+ // PERF: digesting needs data source.
+ byte [] data = DataSourceHelper.convertDataSourceToByteArray(input);
+ return buildDigest(data, hashAlg);
+ }
+
+ /**
+ * This method escapes a given string with HTML entities.
+ *
+ * @param rawString
+ * the string to escaped
+ * @return the HTML escaped string
+ */
+ public static String htmlEscape(String rawString)
+ {
+ rawString = rawString.replaceAll("\\&", "&amp;");
+ rawString = rawString.replaceAll("\\<", "&lt;");
+ rawString = rawString.replaceAll("\\>", "&gt;");
+ rawString = rawString.replaceAll("\">", "&quot;");
+ return rawString;
+ }
+
+ /**
+ * This method checks, if a byte array contains chars that are not base64
+ * conform.
+ *
+ * @param byteArray
+ * the array to test
+ * @return boolean, if a byte array is base64 conform, false otherwise
+ */
+ public static boolean isB64(byte[] byteArray)
+ {
+ try
+ {
+ return Base64.isArrayByteBase64(byteArray);
+ }
+ catch (ArrayIndexOutOfBoundsException e)
+ {
+ return false;
+ }
+ }
+
+ /**
+ * This method checks, if a string contains chars that are not base64 conform.
+ *
+ * @param string
+ * the chars to test
+ * @return boolean, if the given string is base64 conform, false otherwise
+ */
+ public static boolean isB64(String string)
+ {
+ try
+ {
+ return Base64.isArrayByteBase64(string.getBytes());
+ }
+ catch (ArrayIndexOutOfBoundsException e)
+ {
+ return false;
+ }
+ }
+} \ No newline at end of file
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/tools/DebugHelper.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/tools/DebugHelper.java
new file mode 100644
index 0000000..762cb71
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/tools/DebugHelper.java
@@ -0,0 +1,90 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.knowcenter.wag.egov.egiz.tools;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStreamWriter;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import at.knowcenter.wag.egov.egiz.sig.connectors.moa.EnvelopingBase64MOAConnector;
+
+/**
+ * Contains useful helper methods for debugging.
+ *
+ * @author wprinz
+ */
+public final class DebugHelper
+{
+ /**
+ * The log.
+ */
+ private static Log log = LogFactory.getLog(DebugHelper.class);
+
+ /**
+ * Tells, if Strings should be debugged to a file.
+ *
+ * <p>
+ * If set to false, the corresponding methods will simply do nothing.
+ * </p>
+ */
+ public static boolean debug_to_file = true;
+
+ /**
+ * The directory under which the debug files are to be stored.
+ */
+ public static File debug_dir = new File("C:\\wprinz\\Filer\\egiz2"); //$NON-NLS-1$
+
+ /**
+ * Writes the given String to a file with the given file name in UTF-8
+ * encoding.
+ *
+ * @param str
+ * The String to be written.
+ * @param file_name
+ * The file the String will be written to.
+ */
+ public static void debugStringToFile(String str, String file_name)
+ {
+ if (!debug_to_file)
+ {
+ return;
+ }
+
+ try
+ {
+ File file = new File(debug_dir, file_name);
+ FileOutputStream fos = new FileOutputStream(file);
+ OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8"); //$NON-NLS-1$
+ osw.write(str);
+ osw.close();
+ }
+ catch (Exception e)
+ {
+ log.error(e.getMessage(), e);
+ }
+ }
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/tools/FileHelper.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/tools/FileHelper.java
new file mode 100644
index 0000000..17b98d7
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/tools/FileHelper.java
@@ -0,0 +1,125 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: FileHelper.java,v 1.2 2006/05/15 12:05:21 wlackner Exp $
+ */
+package at.knowcenter.wag.egov.egiz.tools;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import org.apache.log4j.Logger;
+
+import at.knowcenter.wag.egov.egiz.cfg.ConfigLogger;
+
+/**
+ * This class provides file reader and writer methods. All methods are static!
+ *
+ * @author wlackner
+ */
+public class FileHelper {
+ /**
+ * The logger definition.
+ */
+ private static final Logger logger_ = ConfigLogger.getLogger(FileHelper.class);
+
+ /**
+ * This method reads a file by reading line by line.
+ *
+ * @param fileName the file to be read
+ * @return the content string of the file
+ */
+ public static String readFromFile(String fileName) {
+ String file_string = null;
+ logger_.trace("Looking for file: " + fileName);
+ try {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(fileName), "UTF-8"));
+ logger_.trace("Reading file: " + fileName);
+ String line = null;
+ file_string = "";
+ while ((line = reader.readLine()) != null) {
+ file_string += line;
+ }
+ reader.close();
+ logger_.debug("File successfully read: " + fileName);
+ } catch (FileNotFoundException e) {
+ logger_.debug("File not found: " + fileName);
+ } catch (IOException e) {
+ logger_.debug("Error reading file: " + fileName);
+ }
+ return file_string;
+ }
+
+ /**
+ * This method reads a file by reading line by line.
+ *
+ * @param fileName the file to be read
+ * @return the content string of the file
+ */
+ public static String readFromInputStream(InputStream inputStream) {
+ String file_string = null;
+ if (inputStream == null) {
+ return null;
+ }
+ try {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
+ String line = null;
+ file_string = "";
+ while ((line = reader.readLine()) != null) {
+ file_string += line;
+ }
+ reader.close();
+ } catch (IOException e) {
+ logger_.debug("Error reading inputstream.");
+ }
+ return file_string;
+ }
+
+ /**
+ * This method writes a file line by line.
+ *
+ * @param fileName the file to be written
+ * @param fileString the content to be written
+ * @return true if the file could be written sucessfully, false otherwise
+ */
+ public static boolean writeToFile(String fileName, String fileString) {
+ BufferedWriter writer;
+ try {
+ FileWriter fwriter = new FileWriter(fileName);
+ writer = new BufferedWriter(fwriter);
+ writer.write(fileString);
+ writer.close();
+ } catch (IOException e) {
+ logger_.info("File:" + fileName + " can not be written. Cause:" + e.getMessage());
+ return false;
+ }
+ return true;
+ }
+} \ No newline at end of file
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/tools/Normalize.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/tools/Normalize.java
new file mode 100644
index 0000000..2b0b8c2
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/tools/Normalize.java
@@ -0,0 +1,55 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: Normalize.java,v 1.2 2006/05/15 12:05:21 wlackner Exp $
+ */
+package at.knowcenter.wag.egov.egiz.tools;
+
+
+/**
+ * Defines an interface to get access to different normalizer implementations.
+ *
+ * @author wlackner
+ */
+public interface Normalize {
+
+ /**
+ * Normalize a given text.
+ * @param rawText the raw text to normalize
+ * @param keepMultipleLineBreaks if true multiple line breaks in a row will not be normalized to a single line break
+ * @return the normalized string
+ */
+ public String normalize(String rawText, boolean keepMultipleLineBreaks);
+ /**
+ * Return the current normalizer version string.
+ * @return the version string
+ */
+ public String getVersion();
+
+ /**
+ * Returns the normalizer line separator string.
+ * @return the line separator string
+ */
+ public String getNormCR();
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/tools/NormalizeV01.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/tools/NormalizeV01.java
new file mode 100644
index 0000000..57b8e6f
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/tools/NormalizeV01.java
@@ -0,0 +1,184 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: NormalizeV01.java,v 1.5 2006/10/31 08:20:56 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.tools;
+
+import java.io.Serializable;
+
+/**
+ * This ist the first version implementing a normalizer method. The normalize statements are
+ * performed by using regular expressions.
+ *
+ * @author wlackner
+ */
+public class NormalizeV01 implements Normalize, Serializable {
+// 04.11.2010 change by exthex - added keepMultipleLineBreaks parameter to normalize method
+// to allow multiple line breaks to not be normalized to a single one
+ /**
+ * SVUID.
+ */
+ private static final long serialVersionUID = 2302956630639871601L;
+
+ /**
+ * The space string
+ */
+ private final static String NORM_SP = " "; //\u0020
+ /**
+ * The line break string --> use only \n because XML-Parser ignores \r\n
+ */
+ private final static String NORM_CR = "\n"; //
+ /**
+ * The apostrophe string
+ */
+ private final static String NORM_AP = "'"; //\u0027
+ /**
+ * The quotation mark string
+ */
+ private final static String NORM_QU = "\""; //\u0022
+ /**
+ * The hypens string
+ */
+ private final static String NORM_HY = "-"; //\u002D
+ /**
+ * The current version string
+ */
+ protected static final String VERSION = "V01";
+
+ /**
+ * The empty constructor.
+ */
+ public NormalizeV01() {
+ }
+
+ /**
+ * The normalizer implementation. <br>
+ * Normalizer algorithums:
+ * <ol>
+ * <li>code all multiple line breaks as \n\n</li>
+ * <li>replace all Tabs and form feeds with spaces</li>
+ * <li>code line breaks as \n</li>
+ * <li>reduce all multiple line breaks into one line break (only if keepMultipleLineBreaks == false), code line break as \r</li>
+ * <li>replace all single line breaks with space</li>
+ * <li>normalize spaces</li>
+ * <li>remove spaces before and after a line break</li>
+ * <li>remove leading and trailing space or line break in the string</li>
+ * <li>normalize line breaks</li>
+ * <li>normalize apostrophes</li>
+ * <li>normalize quotations</li>
+ * <li>normalize hypens</li>
+ * </ol>
+ *
+ * @param rawText the text to normalize
+ * @param keepMultipleLineBreaks if true, multiple newlines in a row will not be normalized to a single line break
+ * @see at.knowcenter.wag.egov.egiz.tools.Normalize#normalize(java.lang.String)
+ */
+ public String normalize(String rawText, boolean keepMultipleLineBreaks) {
+ if (rawText == null || rawText.equals("null") || rawText.length() == 0) {
+ return "";
+ }
+ String normText = rawText;
+
+ // replace all null values
+ normText = normText.replaceAll("\u0000+", "");
+
+ // replace all Tabs and form feeds with spaces
+ normText = normText.replaceAll("[\t\f]", NORM_SP);
+
+ // replace all non breaking spaces with normal spaces
+ normText = normText.replaceAll("\u00a0+", NORM_SP);
+
+ // code all windows line breaks as \n
+ normText = normText.replaceAll("\r\n", "\n");
+
+ // code all mac line breaks as \n
+ normText = normText.replace('\r', '\n');
+
+ if (!keepMultipleLineBreaks)
+ {
+ // reduce all multiple line breaks into two line breaks, code muliple line break as \r\r
+ normText = normText.replaceAll("\n[\\s\n]*\n", "\r\r");
+ }
+
+ // replace all single line breaks with one line break
+ normText = normText.replace('\n', '\r');
+
+ // normalize spaces
+ normText = normText.replaceAll(" +", NORM_SP);
+
+ // remove spaces before and after a single line break
+ normText = normText.replaceAll(" ?\r ?", "\r");
+
+ if (keepMultipleLineBreaks)
+ {
+ // remove spaces before and after a multiple line breaks
+ normText = normText.replaceAll(" ?\r\r ?", "\r\r");
+ } else
+ {
+ normText = normText.replaceAll(" ?\r\r ?", "\r");
+ }
+
+ // remove leading and trailing space or line break in the string
+ int start_idx = (normText.charAt(0) == ' ' || normText.charAt(0) == '\r' ? 1 : 0);
+ int end_idx = (normText.charAt(normText.length() - 1) == ' ' || normText.charAt(normText.length() - 1) == '\r' ? normText.length() - 1 : normText.length());
+ if (end_idx < start_idx) {
+ end_idx = start_idx;
+ }
+
+ // System.err.println("Start idx:" + start_idx + " End idx:" + end_idx + " Text length:" +
+ // normText_.length());
+ normText = normText.substring(start_idx, end_idx);
+
+ // normalize line breaks
+ normText = normText.replaceAll("\r", NORM_CR);
+
+ // normalize apostrophes
+ normText = normText.replaceAll("[\u0060\u00B4\u2018\u2019\u201A\u201B]", NORM_AP);
+
+ // normalize quotations
+ normText = normText.replaceAll("[\u201C\u201D\u201E\u201F]", NORM_QU);
+
+ // normalize hypens
+ normText = normText.replaceAll("[\u00AD\u2013\u2014]", NORM_HY);
+
+ return normText;
+ }
+
+ /**
+ * Return the version string.
+ *
+ * @see at.knowcenter.wag.egov.egiz.tools.Normalize#getVersion()
+ */
+ public String getVersion() {
+ return VERSION;
+ }
+
+ /**
+ * Returns the normalizer line separator string.
+ * @return the line separator string
+ */
+ public String getNormCR() {
+ return NORM_CR;
+ }
+} \ No newline at end of file
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/tools/Normalizer.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/tools/Normalizer.java
new file mode 100644
index 0000000..a08c12e
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/tools/Normalizer.java
@@ -0,0 +1,280 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: Normalizer.java,v 1.5 2006/10/31 08:20:56 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.tools;
+
+import java.io.Serializable;
+
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+
+import at.knowcenter.wag.egov.egiz.cfg.ConfigLogger;
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.exceptions.NormalizeException;
+import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
+
+/**
+ * This class provides wrapper methods to get an access to different normalizer implementations.
+ * <br>
+ * This class is to load the corresponding implementation of a normalizer class. Therefor it seams
+ * to be a factory. The factory settings are read from the configuration file calling the
+ * SettingsReader.
+ *
+ * @author wlackner
+ * @see at.knowcenter.wag.egov.egiz.tools.Normalizer
+ * @see at.knowcenter.wag.egov.egiz.tools.NormalizeV01
+ * @see at.knowcenter.wag.egov.egiz.cfg.SettingsReader
+ */
+public class Normalizer implements Serializable {
+// 04.11.2010 changed by exthex - normalize methods use and propagate the keepMultipleNewlines parameter
+
+ /**
+ * SVUID.
+ */
+ private static final long serialVersionUID = 4201772508393848555L;
+
+ /**
+ * The current raw string to normalize
+ */
+ private String rawString_ = null;
+ /**
+ * The current normalisation version string
+ */
+ private String normVersion_ = null;
+ /**
+ * The normalized string cache
+ */
+ private String normString_ = null;
+ /**
+ * The reference to the normalizer implementation
+ */
+ private Normalize normalize_ = null;
+// /**
+// * A given Encoding, not used now
+// */
+// private String encoding_ = null;
+ /**
+ * The SettingsReader instance
+ */
+ private SettingsReader settings_ = null;
+ /**
+ * The factory class prefix
+ */
+ private final static String CLASS_PREFIX = ".Normalize";
+ /**
+ * The default version string
+ */
+ protected final static String DEFAULT_VERSION = "V01";
+ /**
+ * The settings key defined in the settings file
+ *
+ * @see SettingsReader
+ */
+ protected final static String SETTINGS_VERSION_KEY = "normalizer.version";
+ /**
+ * The logger definition.
+ */
+ private static final Logger logger_ = ConfigLogger.getLogger(Normalizer.class);
+
+ /**
+ * New Normalizer init by the raw string and a normalizer version.
+ *
+ * @param rawString the raw string to normalize
+ * @param normVersion the nomalizer version that should be used
+ * @throws NormalizeException ErrorCode:400
+ */
+ public Normalizer(String rawString, String normVersion) throws NormalizeException {
+ rawString_ = rawString;
+ normVersion_ = normVersion;
+ init();
+ }
+
+ /**
+ * New Normalizer init by the raw string.
+ *
+ * @param rawString the raw string to normalize
+ * @throws NormalizeException ErrorCode:400
+ */
+ public Normalizer(String rawString) throws NormalizeException {
+ rawString_ = rawString;
+ init();
+ }
+
+ /**
+ * The empty constructor.
+ *
+ * @throws NormalizeException ErrorCode:400
+ */
+ public Normalizer() throws NormalizeException {
+ init();
+ }
+
+ /**
+ * Load the factory implementation. This method trys to load the configured normalizer library.
+ *
+ * @throws NormalizeException
+ */
+ public void init() throws NormalizeException {
+ loadSettings();
+ String class_name = this.getClass().getPackage().getName() + getClassName();
+ Class normalize_class = null;
+ try {
+ normalize_class = Class.forName(class_name);
+ } catch (ClassNotFoundException e) {
+ if (logger_.isEnabledFor(Level.FATAL)) {
+ logger_.fatal("Class not found:" + class_name);
+ }
+ throw new NormalizeException("Can not load normalizer library", e);
+ }
+ try {
+ normalize_ = (Normalize) normalize_class.newInstance();
+ } catch (InstantiationException e) {
+ if (logger_.isEnabledFor(Level.FATAL)) {
+ logger_.fatal("Can not instantiate:" + class_name);
+ }
+ throw new NormalizeException("Can not load normalizer library", e);
+ } catch (IllegalAccessException e) {
+ if (logger_.isEnabledFor(Level.FATAL)) {
+ logger_.fatal("Can not access:" + class_name);
+ }
+ throw new NormalizeException("Can not load normalizer library", e);
+ }
+ }
+
+ /**
+ * Returns the underlying normalizer instance.
+ * @author tknall
+ */
+ public Normalize getInstance() {
+ return this.normalize_;
+ }
+
+ /**
+ * Read the class postfix from the configuration file
+ *
+ * @return the full qualified class name
+ */
+ private String getClassName() {
+ if (normVersion_ == null) {
+ normVersion_ = settings_.getSetting(SETTINGS_VERSION_KEY, DEFAULT_VERSION);
+ }
+ return CLASS_PREFIX + normVersion_;
+ }
+
+ /*
+ * public void setEncoding(String encoding) { encoding_ = encoding; }
+ */
+
+ /**
+ * Set the raw string to normalize
+ */
+ public void setRawString(String rawString) {
+ rawString_ = rawString;
+ }
+
+// /**
+// * Return the normalized string. If the chached value does not exist the normalize method from the
+// * current normalizer implementation is called.
+// *
+// * @return the normalized string
+// */
+// public String getNormalizedString() {
+// if (normString_ == null) {
+// normalize();
+// }
+// return normString_;
+// }
+
+ /**
+ * Set a normalizer version. This activity load the new requested normalizer implementation.
+ *
+ * @param normVersion the normalizer version to be use
+ * @throws NormalizeException ErrorCode:400
+ */
+ public void setVersion(String normVersion) throws NormalizeException {
+ normVersion_ = normVersion;
+ init();
+ }
+
+ /**
+ * Return the current version string.
+ *
+ * @return the normaliser version string
+ */
+ public String getVersion() {
+ return normVersion_;
+ }
+
+ /**
+ * Wrapper method. Call the normalizer implementation method.
+ *
+ * @param rawString the raw string to normalize
+ * @param keepMultipleNewlines
+ * @return the normalized string
+ * @see NormalizeV01
+ */
+ public String normalize(String rawString, boolean keepMultipleNewlines) {
+ return normalize_.normalize(rawString, keepMultipleNewlines);
+ }
+
+ /**
+ * Wrapper method. Call the normalizer implementation method. Normalize the current raw string.
+ *
+ * @return the normalized string
+ * @see NormalizeV01
+ */
+ public String normalize(boolean keepMultipleNewlines) {
+ if (normString_ == null) {
+ normString_ = normalize(rawString_, keepMultipleNewlines);
+ }
+ return normString_;
+ }
+
+ /**
+ * Returns the normalizer line separator string.
+ * @return the line separator string
+ */
+ public String getNormCR() {
+ return normalize_.getNormCR();
+ }
+
+ /**
+ * load the class settings
+ *
+ * @throws NormalizeException
+ * @see SettingsReader
+ */
+ private void loadSettings() throws NormalizeException {
+ if (settings_ == null) {
+ try {
+ settings_ = SettingsReader.getInstance();
+ } catch (SettingsException e) {
+ String log_message = "Can not load normalizer settings. Cause:\n" + e.getMessage();
+ logger_.error(log_message, e);
+ throw new NormalizeException(log_message, e);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/ByteArrayUtils.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/ByteArrayUtils.java
new file mode 100644
index 0000000..4442650
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/ByteArrayUtils.java
@@ -0,0 +1,148 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: ByteArrayUtils.java,v 1.1 2006/08/25 17:00:59 wprinz Exp $
+ */
+package at.knowcenter.wag.exactparser;
+
+import java.io.UnsupportedEncodingException;
+
+/**
+ * Abstract class that contains utility methods for handling byte arrays.
+ *
+ * @author wprinz
+ */
+public abstract class ByteArrayUtils {
+
+ public static final String BYTE_ARRAY_ENCODING = "ISO-8859-1";
+
+ /**
+ * Converts the byte array to a String.
+ *
+ * @param data
+ * The byte array.
+ * @return Returns the String.
+ * @throws UnsupportedEncodingException
+ * Forwarded exception
+ */
+ public static String convertByteArrayToString(final byte[] data) throws UnsupportedEncodingException {
+ return new String(data, BYTE_ARRAY_ENCODING);
+ }
+
+ /**
+ * Finds the first occurance of search in data starting to search from the
+ * given index.
+ *
+ * @param data
+ * The big array.
+ * @param index
+ * The index to start searching from.
+ * @param search
+ * The sought array.
+ * @return Returns the index of the found occurence or -1 if nothing was
+ * found.
+ */
+ public static int indexOf(final byte[] data, final int index, final byte[] search) {
+ for (int i = index; i <= data.length - search.length; i++) {
+ if (compareByteArrays(data, i, search)) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Finds the last occurance of the array.
+ *
+ * @param data
+ * The source array to be searched.
+ * @param search
+ * The sought array.
+ * @return Returns the index of the last occurance - or -1 if nothing was
+ * found.
+ */
+ public static int lastIndexOf(final byte[] data, byte[] search) {
+ for (int index = data.length - search.length; index >= 0; index--) {
+ if (compareByteArrays(data, index, search)) {
+ return index;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Compares the two byte arrays for equality.
+ *
+ * @param data
+ * The source array.
+ * @param index
+ * In index into the source array marking where the comparison should
+ * start.
+ * @param search
+ * The sought array.
+ * @return Returns true if the first search.length bytes of data+index and
+ * search match exactly. Returns false otherwise.
+ */
+ public static boolean compareByteArrays(final byte[] data, final int index, byte[] search) {
+ if (index < 0 || index >= data.length) {
+ throw new IndexOutOfBoundsException("The index " + index + " is out of bounds");
+ }
+
+ if (search.length > data.length) {
+ return false;
+ }
+
+ if (search.length > data.length - index) {
+ return false;
+ }
+
+ for (int i = 0; i < search.length; i++) {
+ if (data[index + i] != search[i]) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Checks, if the sought data byte is contained within the byte array.
+ *
+ * @param byte_array
+ * The byte array.
+ * @param data
+ * A data byte sought within the byte array.
+ * @return Returns true, if the data byte was found (at least once) in the
+ * byte array, false otherwise.
+ */
+ public static boolean contains(final byte[] byte_array, final byte data) {
+ for (int i = 0; i < byte_array.length; i++) {
+ byte b = byte_array[i];
+ if (b == data) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/ParseDocument.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/ParseDocument.java
new file mode 100644
index 0000000..fbaa4de
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/ParseDocument.java
@@ -0,0 +1,272 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: ParseDocument.java,v 1.1 2006/08/25 17:00:59 wprinz Exp $
+ */
+package at.knowcenter.wag.exactparser;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import at.knowcenter.wag.exactparser.parsing.PDFUtils;
+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.NameParseResult;
+import at.knowcenter.wag.exactparser.parsing.results.NumberParseResult;
+import at.knowcenter.wag.exactparser.parsing.results.ObjectParseResult;
+import at.knowcenter.wag.exactparser.parsing.results.StartXRefParseResult;
+import at.knowcenter.wag.exactparser.parsing.results.TrailerParseResult;
+import at.knowcenter.wag.exactparser.parsing.results.XRefSectionParseResult;
+
+
+/**
+ * Test class.
+ * @author wprinz
+ */
+public class ParseDocument
+{
+
+ public static final String DOCUMENT = "C:/wprinz/temp.pdf";
+
+ public static final byte[] EGIZ_DICT_NAME = { 'E', 'G', 'I', 'Z', 'S', 'i',
+ 'g', 'D', 'i', 'c', 't' };
+
+ public static final byte[] EGIZ_ODS_NAME = { 'O', 'D', 'S' };
+
+ public static final byte[] EGIZ_XOBJ_NAME = { 'S', 'i', 'g', 'X', 'O', 'b',
+ 'j', 'e', 'c', 't' };
+
+ /**
+ * @param args
+ */
+ public static void main(String[] args)
+ {
+
+ try
+ {
+ File in = new File(DOCUMENT);
+ FileInputStream fis = new FileInputStream(in);
+ byte[] pdf = new byte[(int) in.length()];
+ fis.read(pdf);
+ fis.close();
+ fis = null;
+
+ List blocks = parseDocument(pdf);
+
+ Iterator it = blocks.iterator();
+ while (it.hasNext())
+ {
+ FooterParseResult bpr = (FooterParseResult) it.next();
+
+ System.out.print("block from " + bpr.start_index + " to " + bpr.next_index);
+
+ if (bpr.tpr.root != null)
+ {
+ int root_index = PDFUtils.getObjectOffsetFromXRefByIndirectObjectReference(bpr.xpr, bpr.tpr.root.ior);
+ ObjectParseResult root_opr = PDFUtils.parseObject(pdf, root_index);
+ DictionaryParseResult root_dpr = (DictionaryParseResult) root_opr.object;
+
+ int egiz_index = PDFUtils.indexOfName(pdf, root_dpr.names, EGIZ_DICT_NAME);
+ if (egiz_index >= 0)
+ {
+ System.out.print(" == EGIZDict");
+ }
+ }
+
+ System.out.println();
+ }
+
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ public static List parseDocument(final byte[] pdf) throws IOException
+ {
+ //HeaderParseResult hpr = PDFUtils.parseHeader(pdf, 0);
+ //System.out.println("PDF-version = " + hpr.major + "." + hpr.minor);
+
+ List blocks = new ArrayList();
+
+ int last_start_xref = PDFUtils.findLastStartXRef(pdf);
+ StartXRefParseResult last_sxpr = PDFUtils.parseStartXRef(pdf, last_start_xref);
+ int xref_index = last_sxpr.xref_index;
+
+ for (;;)
+ {
+ FooterParseResult fpr = PDFUtils.parseFooter(pdf, xref_index);
+ blocks.add(0, fpr);
+
+ //System.out.println("tpr.has_predecessor = " + fpr.tpr.has_predecessor);
+ if (!fpr.tpr.has_predecessor)
+ {
+ // eventually parse the PDF header here.
+ break;
+ }
+
+ //System.out.println("tpr.prev = " + fpr.tpr.getPrev());
+
+ xref_index = fpr.tpr.getPrev();
+ }
+
+ return blocks;
+ }
+
+ // public static void parseEGIZ()
+ // {
+ //
+ // int root_index =
+ // PDFUtils.getObjectOffsetFromXRefByIndirectObjectReference(bpr.xpr,
+ // bpr.tpr.root.ior);
+ // ObjectParseResult root_opr = PDFUtils.parseObject(pdf, root_index);
+ // DictionaryParseResult root_dpr = (DictionaryParseResult) root_opr.object;
+ //
+ // int egiz_index = PDFUtils.indexOfName(pdf, root_dpr.names, EGIZ_DICT_NAME);
+ // if (egiz_index >= 0)
+ // {
+ // IndirectObjectReferenceParseResult egiz_iorpr =
+ // (IndirectObjectReferenceParseResult) root_dpr.values.get(egiz_index);
+ // System.out.println("EGIZ signature info at = " + egiz_iorpr);
+ //
+ // int egiz_dict_index =
+ // PDFUtils.getObjectOffsetFromXRefByIndirectObjectReference(bpr.xpr,
+ // egiz_iorpr.ior);
+ // ObjectParseResult opr = PDFUtils.parseObject(pdf, egiz_dict_index);
+ // DictionaryParseResult egiz_dict = (DictionaryParseResult) opr.object;
+ //
+ // for (int i = 0; i < egiz_dict.names.size(); i++)
+ // {
+ // NameParseResult npr = egiz_dict.names.get(i);
+ // int len = npr.next_index - npr.name_start_index;
+ // byte[] name = new byte[len];
+ // System.arraycopy(pdf, npr.name_start_index, name, 0, len);
+ // System.out.print(" " + new String(name, "US-ASCII") + " = ");
+ //
+ // System.out.println(egiz_dict.values.get(i));
+ // }
+ //
+ // // int key = PDFUtils.indexOfName(pdf, egiz_dict.names, new byte [] { 'K',
+ // // 'e', 'y'});
+ // // IndirectObjectReferenceParseResult key_iorpr =
+ // // (IndirectObjectReferenceParseResult) egiz_dict.values.get(key);
+ // // int key_offset =
+ // // PDFUtils.getObjectOffsetFromXRefByIndirectObjectReference(xpr,
+ // // key_iorpr.ior);
+ // // ObjectParseResult key_opr = PDFUtils.parseObject(pdf, key_offset);
+ // // StreamParseResult spr = (StreamParseResult) key_opr.object;
+ // // System.out.println(" key stream from " + spr.content_start_index + " to
+ // // " + spr.content_end_index);
+ // //
+ // // int data_len = spr.content_end_index - spr.content_start_index;
+ // // byte [] data = new byte[data_len];
+ // // System.arraycopy(pdf, spr.content_start_index, data, 0, data_len);
+ // // System.out.println(new String(data, "US-ASCII"));
+ //
+ // }
+ // else
+ // {
+ // System.out.println("No EGIZ block found.");
+ // }
+ //
+ // }
+
+ public static byte[] getOriginalDocument(final File file_name) throws IOException
+ {
+ FileInputStream fis = new FileInputStream(file_name);
+ byte[] pdf = new byte[(int) file_name.length()];
+ fis.read(pdf);
+ fis.close();
+ fis = null;
+
+ int last_start_xref = PDFUtils.findLastStartXRef(pdf);
+
+ StartXRefParseResult sxpr = PDFUtils.parseStartXRef(pdf, last_start_xref);
+
+ XRefSectionParseResult xpr = PDFUtils.parseXRefSection(pdf, sxpr.xref_index);
+
+ TrailerParseResult tpr = PDFUtils.parseTrailer(pdf, xpr.next_index);
+
+ System.out.println("tpr.info = " + tpr.info);
+ System.out.println("tpr.root = " + tpr.root);
+ System.out.println("tpr.size = " + tpr.size);
+
+ System.out.println("tpr.has_predecessor = " + tpr.has_predecessor);
+ if (tpr.has_predecessor)
+ {
+ System.out.println("tpr.prev = " + tpr.getPrev());
+ }
+
+ int root_index = PDFUtils.getObjectOffsetFromXRefByIndirectObjectReference(xpr, tpr.root.ior);
+ ObjectParseResult root_opr = PDFUtils.parseObject(pdf, root_index);
+ DictionaryParseResult root_dpr = (DictionaryParseResult) root_opr.object;
+
+ byte[] EGIZ_TYPE = new String("EGIZSigDict").getBytes("US-ASCII");
+ int egiz_index = PDFUtils.indexOfName(pdf, root_dpr.names, EGIZ_TYPE);
+ if (egiz_index >= 0)
+ {
+ System.out.println("The document is EGIZ-signed. ==> extract original document");
+
+ IndirectObjectReferenceParseResult egiz_iorpr = (IndirectObjectReferenceParseResult) root_dpr.values.get(egiz_index);
+ System.out.println("EGIZ signature info at = " + egiz_iorpr);
+
+ int egiz_dict_index = PDFUtils.getObjectOffsetFromXRefByIndirectObjectReference(xpr, egiz_iorpr.ior);
+ ObjectParseResult opr = PDFUtils.parseObject(pdf, egiz_dict_index);
+ DictionaryParseResult egiz_dict = (DictionaryParseResult) opr.object;
+
+ for (int i = 0; i < egiz_dict.names.size(); i++)
+ {
+ NameParseResult npr = (NameParseResult) egiz_dict.names.get(i);
+ int len = npr.next_index - npr.name_start_index;
+ byte[] name = new byte[len];
+ System.arraycopy(pdf, npr.name_start_index, name, 0, len);
+ System.out.print(" " + new String(name, "US-ASCII") + " = ");
+
+ System.out.println(egiz_dict.values.get(i));
+ }
+
+ // Original document size
+ int key = PDFUtils.indexOfName(pdf, egiz_dict.names, new byte[] { 'O',
+ 'D', 'S' });
+ NumberParseResult ods = (NumberParseResult) egiz_dict.values.get(key);
+
+ int original_document_size = ods.number;
+ System.out.println("Original Document Size = " + original_document_size);
+
+ byte[] original = new byte[original_document_size];
+ System.arraycopy(pdf, 0, original, 0, original_document_size);
+
+ return original;
+ }
+
+ System.out.println("No EGIZ block found. ==> the whold document is the original document");
+ return pdf;
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/IndirectObjectReference.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/IndirectObjectReference.java
new file mode 100644
index 0000000..2bfdf56
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/IndirectObjectReference.java
@@ -0,0 +1,57 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: IndirectObjectReference.java,v 1.1 2006/08/25 17:00:59 wprinz Exp $
+ */
+package at.knowcenter.wag.exactparser.parsing;
+
+/**
+ * The IndirectObjectReference class completely holds a so called object
+ * identifier of an indirect object.
+ *
+ * <p>
+ * An indirect object is an object not contained within another object. In
+ * accordance, a direct object is structurally part of another object. For
+ * example, a direct String object that is the value of some key in a dictionary
+ * object.
+ * </p>
+ * <p>
+ * An object identifier uniquely identifies a specific indirect object by the
+ * object number and the generation number. In PDF such an object identifier may
+ * be used to reference to the object.
+ * </p>
+ *
+ * @author wprinz
+ */
+public class IndirectObjectReference {
+
+ public int object_number;
+
+ public int generation_number;
+
+ //@Override
+ public String toString() {
+ return object_number + " " + generation_number;
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/PDFNames.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/PDFNames.java
new file mode 100644
index 0000000..0ee5863
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/PDFNames.java
@@ -0,0 +1,184 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: PDFNames.java,v 1.1 2006/08/25 17:00:59 wprinz Exp $
+ */
+package at.knowcenter.wag.exactparser.parsing;
+
+/**
+ * Abstract class that contains several frequently used PDF constants.
+ *
+ * <p>
+ * The PDF specification partitions the character set (ASCII) into three groups:
+ * </p>
+ * <ul>
+ * <li>Whitespace characters (space, tab, etc., but also newline and carriage
+ * return) used to separate tokens. Unless otherwise specified a group of
+ * consecutive whitespace characters behaves like a single whitespace character.</li>
+ * <li>Delimiter characters ('(', '<', etc., but also '/', which precedes the
+ * PDF Key Names in dictionaries) that are used to encircle semantic groups.
+ * <li>Regular characters are per definition the rest characters that are
+ * neither whitespaces nor delimiters.</li>
+ * </ul>
+ * <p>
+ * Newlines consist per default of CR and LF, but also LF and even CR alone are
+ * allowed. It seems that all variations of newlines may exist within a single
+ * document.
+ * </p>
+ *
+ * @author wprinz
+ */
+public abstract class PDFNames
+{
+
+ /**
+ * The standard encoding of PDF tokens and names.
+ *
+ * <p>
+ * PDF is usually an 8 bit format. Binary data etc. can be saves just as it
+ * is. Nevertheless all PDF tokens ('xref', 'obj', etc.) and PDF Names
+ * ('/Size', '/Pages', '/Type', etc.) must be in 7 bit ASCII US encoding.
+ * </p>
+ * <p>
+ * Therefor, whenever using Java Strings to convert e.g. numbers to such PDF
+ * tokens use this encoding constant.
+ * </p>
+ * <p>
+ * The same applies for PDF token/name byte arrays that are retransfromed to
+ * Java Strings.
+ * </p>
+ */
+ public static final String PDF_STANDARD_ENCODING = "US-ASCII";
+
+ // Whitespace characters
+
+ // TABLE 3.1 White-space characters
+ // DECIMAL HEXADECIMAL OCTAL NAME
+ // 0 00 000 Null (NUL)
+ // 9 09 011 Tab (HT)
+ // 10 0A 012 Line feed (LF)
+ // 12 0C 014 Form feed (FF)
+ // 13 0D 015 Carriage return
+ // 32 20 040 Space (SP)
+
+ public static final byte WHITESPACE_NUL = 0x00;
+
+ public static final byte WHITESPACE_HT = 0x09;
+
+ public static final byte WHITESPACE_LF = 0x0A;
+
+ public static final byte WHITESPACE_FF = 0x0C;
+
+ public static final byte WHITESPACE_CR = 0x0D;
+
+ public static final byte WHITESPACE_SP = 0x20;
+
+ public static final byte[] WHITESPACE_CHARACTERS = { WHITESPACE_NUL,
+ WHITESPACE_HT, WHITESPACE_LF, WHITESPACE_FF, WHITESPACE_CR, WHITESPACE_SP };
+
+ // comment character
+
+ public static final byte COMMENT = '%';
+
+ // PDF-version
+
+ public static final byte[] PDF_VERSION_STR = { 'P', 'D', 'F', '-' };
+
+ public static final byte PDF_VERSION_SEPARATOR = '.';
+
+ // delimiter characters
+
+ public static final byte DELIMITER_STRING_OPEN = '(';
+
+ public static final byte DELIMITER_STRING_CLOSE = ')';
+
+ public static final byte DELIMITER_HEXSTRING_OPEN = '<';
+
+ public static final byte DELIMITER_HEXSTRING_CLOSE = '>';
+
+ public static final byte DELIMITER_ARRAY_OPEN = '[';
+
+ public static final byte DELIMITER_ARRAY_CLOSE = ']';
+
+ public static final byte DELIMITER_CURLY_OPEN = '{';
+
+ public static final byte DELIMITER_CURLY_CLOSE = '}';
+
+ public static final byte DELIMITER_NAME = '/';
+
+ public static final byte[] DELIMITER_CHARACTERS = { DELIMITER_STRING_OPEN,
+ DELIMITER_STRING_CLOSE, DELIMITER_HEXSTRING_OPEN,
+ DELIMITER_HEXSTRING_CLOSE, DELIMITER_ARRAY_OPEN, DELIMITER_ARRAY_CLOSE,
+ DELIMITER_CURLY_OPEN, DELIMITER_CURLY_CLOSE, DELIMITER_NAME };
+
+ // Footer
+
+ public static final byte[] XREF_STR = { 'x', 'r', 'e', 'f' };
+
+ public static final byte[] TRAILER_STR = { 't', 'r', 'a', 'i', 'l', 'e', 'r' };
+
+ public static final byte[] STARTXREF_STR = { 's', 't', 'a', 'r', 't', 'x',
+ 'r', 'e', 'f' };
+
+ public static final byte[] EOF_STR = { '%', '%', 'E', 'O', 'F' };
+
+ // objects
+
+ public static final byte[] OBJ_STR = { 'o', 'b', 'j' };
+
+ public static final byte[] ENDOBJ_STR = { 'e', 'n', 'd', 'o', 'b', 'j' };
+
+ public static final byte[] DICT_START_STR = { DELIMITER_HEXSTRING_OPEN,
+ DELIMITER_HEXSTRING_OPEN };
+
+ public static final byte[] DICT_END_STR = { DELIMITER_HEXSTRING_CLOSE,
+ DELIMITER_HEXSTRING_CLOSE };
+
+ public static final byte[] STREAM_STR = { 's', 't', 'r', 'e', 'a', 'm' };
+
+ public static final byte[] ENDSTREAM_STR = { 'e', 'n', 'd', 's', 't', 'r',
+ 'e', 'a', 'm' };
+
+ public static final byte[] NULL_STR = { 'n', 'u', 'l', 'l' };
+
+ public static final byte[] TRUE_STR = { 't', 'r', 'u', 'e' };
+
+ public static final byte[] FALSE_STR = { 'f', 'a', 'l', 's', 'e' };
+
+ // indirect object references
+
+ public static final byte[] REFERENCE_STR = { 'R' };
+
+ // Dictionary keys
+
+ public static final byte[] SIZE_STR = { 'S', 'i', 'z', 'e' };
+
+ public static final byte[] PREV_STR = { 'P', 'r', 'e', 'v' };
+
+ public static final byte[] ROOT_STR = { 'R', 'o', 'o', 't' };
+
+ public static final byte[] INFO_STR = { 'I', 'n', 'f', 'o' };
+
+ public static final byte[] LENGTH_STR = { 'L', 'e', 'n', 'g', 't', 'h' };
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/PDFUtils.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/PDFUtils.java
new file mode 100644
index 0000000..de356c9
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/PDFUtils.java
@@ -0,0 +1,1405 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: PDFUtils.java,v 1.1 2006/08/25 17:00:59 wprinz Exp $
+ */
+package at.knowcenter.wag.exactparser.parsing;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import at.knowcenter.wag.exactparser.ByteArrayUtils;
+import at.knowcenter.wag.exactparser.parsing.results.ArrayParseResult;
+import at.knowcenter.wag.exactparser.parsing.results.BooleanParseResult;
+import at.knowcenter.wag.exactparser.parsing.results.DictionaryParseResult;
+import at.knowcenter.wag.exactparser.parsing.results.EOFParseResult;
+import at.knowcenter.wag.exactparser.parsing.results.FooterParseResult;
+import at.knowcenter.wag.exactparser.parsing.results.HeaderParseResult;
+import at.knowcenter.wag.exactparser.parsing.results.HexStringParseResult;
+import at.knowcenter.wag.exactparser.parsing.results.IndirectObjectReferenceParseResult;
+import at.knowcenter.wag.exactparser.parsing.results.IntegerParseResult;
+import at.knowcenter.wag.exactparser.parsing.results.LiteralStringParseResult;
+import at.knowcenter.wag.exactparser.parsing.results.NameParseResult;
+import at.knowcenter.wag.exactparser.parsing.results.NullParseResult;
+import at.knowcenter.wag.exactparser.parsing.results.NumberParseResult;
+import at.knowcenter.wag.exactparser.parsing.results.ObjectHeaderParseResult;
+import at.knowcenter.wag.exactparser.parsing.results.ObjectParseResult;
+import at.knowcenter.wag.exactparser.parsing.results.ParseResult;
+import at.knowcenter.wag.exactparser.parsing.results.StartXRefParseResult;
+import at.knowcenter.wag.exactparser.parsing.results.StreamParseResult;
+import at.knowcenter.wag.exactparser.parsing.results.TrailerParseResult;
+import at.knowcenter.wag.exactparser.parsing.results.XRefLineParseResult;
+import at.knowcenter.wag.exactparser.parsing.results.XRefSectionParseResult;
+import at.knowcenter.wag.exactparser.parsing.results.XRefSubSectionParseResult;
+
+
+
+/**
+ * Abstract class that contains several static utility methods for parsing and
+ * analyzing PDF documents on the lowest level.
+ *
+ * <p>
+ * Most operations require random access to the PDF data (mostly to verify the
+ * synthax). So the whole PDF document has to be provided as a byte array. The
+ * term "pdf+index" states a specific position index within this byte array.
+ * </p>
+ *
+ * @author wprinz
+ *
+ */
+public abstract class PDFUtils
+{
+ private static Logger log = Logger.getLogger(PDFUtils.class);
+
+ public static boolean isWhitespace(final byte data)
+ {
+ return ByteArrayUtils.contains(PDFNames.WHITESPACE_CHARACTERS, data);
+ }
+
+ public static boolean isDelimiter(final byte data)
+ {
+ return ByteArrayUtils.contains(PDFNames.DELIMITER_CHARACTERS, data);
+ }
+
+ protected static boolean isRegular(final byte data)
+ {
+ return !(isWhitespace(data) || isDelimiter(data));
+ }
+
+ /**
+ * Skips whitespace.
+ *
+ * <p>
+ * Skips all whitespace, which may be none, one or multiple whitespace
+ * characters.
+ * </p>
+ * <p>
+ * Note that this also skips newline characters (which belong to whitespace as
+ * well).
+ * </p>
+ *
+ * @param data
+ * The PDF data.
+ * @param index
+ * The index.
+ * @return Returns the index of the first non whitespace character. This may
+ * be equal to index if no whitespaces were skipped at all.
+ */
+ public static int skipWhitespace(final byte[] data, final int index)
+ {
+ int non_whitespace_index = index;
+ while (isWhitespace(data[non_whitespace_index]))
+ {
+ non_whitespace_index++;
+ }
+ return non_whitespace_index;
+ }
+
+ /**
+ * Skips bytes until whitespace is reached.
+ *
+ * <p>
+ * Skips all non whitespace characters, which may be none at all.
+ * </p>
+ *
+ * @param data
+ * The PDF data.
+ * @param index
+ * The index.
+ * @return Returns the index of the first whitespace character. This may be
+ * equal to index if no non whitespaces were skipped at all.
+ */
+ public static int skipToWhitespace(final byte[] data, final int index)
+ {
+ int whitespace_index = index;
+ while (!isWhitespace(data[whitespace_index]))
+ {
+ whitespace_index++;
+ }
+ return whitespace_index;
+ }
+
+ protected static final byte[] LINE_TERMINATOR_CRLF = {
+ PDFNames.WHITESPACE_CR, PDFNames.WHITESPACE_LF };
+
+ protected static final byte[] LINE_TERMINATOR_CRALONE = { PDFNames.WHITESPACE_CR };
+
+ protected static final byte[] LINE_TERMINATOR_LF = { PDFNames.WHITESPACE_LF };
+
+ public static boolean isNewline(final byte[] data, final int index)
+ {
+ if (ByteArrayUtils.compareByteArrays(data, index, LINE_TERMINATOR_LF))
+ {
+ return true;
+ }
+ if (ByteArrayUtils.compareByteArrays(data, index, LINE_TERMINATOR_CRLF))
+ {
+ return true;
+ }
+ // although not specified by PDF, some applications use the CR alone as line
+ // terminator
+ if (ByteArrayUtils.compareByteArrays(data, index, LINE_TERMINATOR_CRALONE))
+ {
+ return true;
+ }
+ return false;
+ }
+
+ public static int skipNewline(final byte[] data, final int index)
+ {
+ if (ByteArrayUtils.compareByteArrays(data, index, LINE_TERMINATOR_LF))
+ {
+ return index + LINE_TERMINATOR_LF.length;
+ }
+ if (ByteArrayUtils.compareByteArrays(data, index, LINE_TERMINATOR_CRLF))
+ {
+ return index + LINE_TERMINATOR_CRLF.length;
+ }
+ // although not specified by PDF, some applications use the CR alone as line
+ // terminator
+ if (ByteArrayUtils.compareByteArrays(data, index, LINE_TERMINATOR_CRALONE))
+ {
+ return index + LINE_TERMINATOR_CRALONE.length;
+ }
+
+ assert false : "don't call this if you don't expect a newline - call skipWhitespace instead";
+ return index;
+ }
+
+ public static int skipToNewline(final byte[] data, final int index)
+ {
+ int current_index = index;
+ for (;;)
+ {
+ if (ByteArrayUtils.compareByteArrays(data, current_index, LINE_TERMINATOR_LF))
+ {
+ return current_index + LINE_TERMINATOR_LF.length;
+ }
+ if (ByteArrayUtils.compareByteArrays(data, index, LINE_TERMINATOR_CRLF))
+ {
+ return index + LINE_TERMINATOR_CRLF.length;
+ }
+ // although not specified by PDF, some applications use the CR alone as
+ // line terminator
+ if (ByteArrayUtils.compareByteArrays(data, index, LINE_TERMINATOR_CRALONE))
+ {
+ return index + LINE_TERMINATOR_CRALONE.length;
+ }
+ current_index++;
+ }
+ }
+
+ /**
+ * Parses a boolean value.
+ *
+ * @param pdf
+ * The PDF data.
+ * @param index
+ * The index.
+ * @return Returns the result of the parsing operation.
+ */
+ public static BooleanParseResult parseBoolean(final byte[] pdf,
+ final int index)
+ {
+ BooleanParseResult bpr = new BooleanParseResult();
+ bpr.start_index = index;
+
+ if (ByteArrayUtils.compareByteArrays(pdf, bpr.start_index, PDFNames.TRUE_STR))
+ {
+ bpr.value = true;
+ bpr.next_index = bpr.start_index + PDFNames.TRUE_STR.length;
+
+ return bpr;
+ }
+ if (ByteArrayUtils.compareByteArrays(pdf, bpr.start_index, PDFNames.FALSE_STR))
+ {
+ bpr.value = false;
+ bpr.next_index = bpr.start_index + PDFNames.FALSE_STR.length;
+
+ return bpr;
+ }
+
+ throw new RuntimeException("Boolean couldn't be parsed at index " + index);
+ }
+
+ public static boolean isSign(final byte data)
+ {
+ return data == '+' || data == '-';
+ }
+
+ public static boolean isNumeric(final byte data)
+ {
+ return '0' <= data && data <= '9';
+ }
+
+ /**
+ * Reads the (positive integer) number from the data. The number must be
+ * terminated by the end of line.
+ *
+ * @param data
+ * The data.
+ * @param index
+ * The index.
+ * @return Returns the read number.
+ */
+ public static int readNumberFromByteArray(final byte[] data, final int index)
+ {
+ NumberParseResult npr = parseNumberFromByteArray(data, index);
+
+ assert npr.number >= 0;
+ return npr.number;
+ }
+
+ /**
+ * Parses an unsigned integer.
+ *
+ * <p>
+ * The integer must be a block of successive number characters. It must not be
+ * preceded by a sign (not even '+').
+ * </p>
+ *
+ * @param pdf
+ * The PDF data.
+ * @param index
+ * The index.
+ * @return Returns the result of the parsing operation.
+ */
+ public static IntegerParseResult parseUnsignedInteger(final byte[] pdf,
+ final int index)
+ {
+ assert isNumeric(pdf[index]);
+
+ String number = "";
+
+ int cur_index = index;
+ while (isNumeric(pdf[cur_index]))
+ {
+
+ number += (char) pdf[cur_index];
+
+ cur_index++;
+ }
+
+ // TODO: make better
+ int int_value = Integer.parseInt(number);
+
+ assert int_value >= 0;
+
+ IntegerParseResult ipr = new IntegerParseResult();
+ ipr.start_index = index;
+ ipr.next_index = cur_index;
+ ipr.number = int_value;
+ return ipr;
+ }
+
+ /**
+ * Parses a (potentially) signed integer.
+ *
+ * <p>
+ * The integer must be a block of successive number characters. It may be
+ * preceded by a sign character ('+' or '-').
+ * </p>
+ *
+ * @param pdf
+ * The PDF data.
+ * @param index
+ * The index.
+ * @return Returns the result of the parsing operation.
+ */
+ public static IntegerParseResult parseInteger(final byte[] pdf,
+ final int index)
+ {
+ assert isSign(pdf[index]) || isNumeric(pdf[index]);
+
+ int sign = +1;
+ int number_start = index;
+ if (pdf[index] == '+')
+ {
+ sign = +1;
+ number_start++;
+ }
+ else
+ {
+ if (pdf[index] == '-')
+ {
+ sign = -1;
+ number_start++;
+ }
+ else
+ {
+ assert isNumeric(pdf[index]);
+ }
+ }
+
+ IntegerParseResult ipr = parseUnsignedInteger(pdf, number_start);
+ ipr.start_index = index;
+ ipr.number *= sign;
+ return ipr;
+ }
+
+ /**
+ * Parses an arbitrary number;
+ *
+ * @param pdf
+ * The PDF data.
+ * @param index
+ * The index.
+ * @return Returns the result of the parsing operation.
+ */
+ public static NumberParseResult parseNumberFromByteArray(final byte[] pdf,
+ int index)
+ {
+ String number = "";
+
+ assert isSign(pdf[index]) || isNumeric(pdf[index]);
+
+ int sign = +1;
+ if (pdf[index] == '+')
+ {
+ sign = +1;
+ index++;
+ }
+ else
+ {
+ if (pdf[index] == '-')
+ {
+ sign = -1;
+ index++;
+ }
+ else
+ {
+ assert isNumeric(pdf[index]);
+ }
+ }
+
+ while (isNumeric(pdf[index]) || pdf[index] == '.')
+ {
+
+ char digit = (char) pdf[index];
+ number += digit;
+
+ index++;
+ }
+
+ NumberParseResult npr = new NumberParseResult();
+ npr.next_index = index;
+ // TODO: make better
+ try
+ {
+ npr.number = Integer.parseInt(number) * sign;
+ }
+ catch (NumberFormatException e)
+ {
+ npr.floating = Float.parseFloat(number) * sign;
+ }
+
+ return npr;
+ }
+
+ /**
+ * Searches the last occurrence of the "startxref" entry ... in other words
+ * starts the search from the end of the document and works reversely.
+ *
+ * @param pdf
+ * The complete PDF file data.
+ * @return Returns the offset (byte index) of the "startxref" entry.
+ */
+ public static int findLastStartXRef(final byte[] pdf)
+ {
+ return ByteArrayUtils.lastIndexOf(pdf, PDFNames.STARTXREF_STR);
+ }
+
+ /**
+ * Parses the xref section at pdf+index.
+ *
+ * <p>
+ * An xref section starts with 'xref' and contains one or more xref
+ * sub-sections.
+ * </p>
+ *
+ * @param pdf
+ * The PDF data.
+ * @param index
+ * The start index of the xref table.
+ * @return Returns the result of the parsing operation.
+ */
+ public static XRefSectionParseResult parseXRefSection(final byte[] pdf,
+ final int index)
+ {
+ at.knowcenter.wag.exactparser.parsing.results.XRefSectionParseResult xpr = new XRefSectionParseResult();
+ xpr.start_index = index;
+
+ assert ByteArrayUtils.compareByteArrays(pdf, xpr.start_index, PDFNames.XREF_STR);
+ assert isNewline(pdf, xpr.start_index + PDFNames.XREF_STR.length);
+
+ int cur_index = skipWhitespace(pdf, xpr.start_index + PDFNames.XREF_STR.length);
+ // skipNewline(pdf, xpr.start_index + PDFNames.XREF_STR.length);
+
+ for (;;)
+ {
+ // trailer ends the xref section.
+ if (ByteArrayUtils.compareByteArrays(pdf, cur_index, PDFNames.TRAILER_STR))
+ {
+ break;
+ }
+
+ // no trailer ==> another xref section
+
+ XRefSubSectionParseResult sspr = parseXRefSubSection(pdf, cur_index);
+ xpr.appendXRefSubSection(sspr);
+
+ cur_index = sspr.next_index;
+ }
+
+ xpr.next_index = cur_index;
+ assert ByteArrayUtils.compareByteArrays(pdf, xpr.next_index, PDFNames.TRAILER_STR);
+
+ return xpr;
+ }
+
+ /**
+ * Parses a xref sub-section.
+ *
+ * @param pdf
+ * The PDF data.
+ * @param index
+ * The index.
+ * @return Returns the result of the parsing operation.
+ */
+ public static XRefSubSectionParseResult parseXRefSubSection(final byte[] pdf,
+ final int index)
+ {
+ XRefSubSectionParseResult sspr = new XRefSubSectionParseResult();
+ sspr.start_index = index;
+
+ NumberParseResult start_obj_num_npr = parseNumberFromByteArray(pdf, sspr.start_index);
+ sspr.start_obj_number = start_obj_num_npr.number;
+ assert sspr.start_obj_number >= 0;
+
+ assert isWhitespace(pdf[start_obj_num_npr.next_index]);
+ int num_obj_index = skipWhitespace(pdf, start_obj_num_npr.next_index);
+
+ NumberParseResult num_obj_npr = parseNumberFromByteArray(pdf, num_obj_index);
+ sspr.num_objects = num_obj_npr.number;
+
+ // assert isNewline(pdf, num_obj_npr.next_index);
+ assert isWhitespace(pdf[num_obj_npr.next_index]);
+ int start_of_line = skipWhitespace(pdf, num_obj_npr.next_index);
+ // skipNewline(pdf, num_obj_npr.next_index);
+
+ for (int i = 0; i < sspr.num_objects; i++)
+ {
+ final int cur_object_number = sspr.start_obj_number + i;
+
+ XRefLineParseResult lpr = parseXrefLine(pdf, start_of_line);
+ sspr.appendXRefLine(lpr);
+
+ // System.out.println("xref line of object " + (oc.start_obj_number + i) +
+ // " at " + lpr.start_index + ": " + lpr.object_offset + " " +
+ // lpr.generation_number + " " + (char) lpr.object_usage);
+
+ if (lpr.object_usage == 'n')
+ {
+ // check the line - this simple check may make problems with object
+ // streams and xref streams
+ ObjectHeaderParseResult ohpr = parseObjectHeader(pdf, lpr.object_offset);
+ assert ohpr.object_number == cur_object_number;
+ assert ohpr.generation_number == lpr.generation_number;
+ }
+
+ start_of_line = lpr.next_index;
+ }
+
+ sspr.next_index = start_of_line;
+ return sspr;
+ }
+
+ /**
+ * Parses a single 20 bytes xref line at pdf+index.
+ *
+ * @param pdf
+ * The PDF data.
+ * @param index
+ * The index.
+ * @return Returns the result of the parsing operation.
+ */
+ public static XRefLineParseResult parseXrefLine(final byte[] pdf,
+ final int index)
+ {
+ XRefLineParseResult lpr = new XRefLineParseResult();
+
+ lpr.start_index = index;
+
+ IntegerParseResult object_offset_ipr = parseUnsignedInteger(pdf, lpr.start_index);
+ lpr.object_offset = object_offset_ipr.number;
+ assert lpr.object_offset >= 0;
+ assert lpr.object_offset < pdf.length;
+ assert object_offset_ipr.next_index == lpr.start_index + 10;
+
+ assert pdf[object_offset_ipr.next_index] == PDFNames.WHITESPACE_SP; // Standard
+ // explicitely
+ // says 1
+ // single
+ // SPACE
+ int generation_number_index = object_offset_ipr.next_index + 1;
+
+ IntegerParseResult generation_number_ipr = parseUnsignedInteger(pdf, generation_number_index);
+ lpr.generation_number = generation_number_ipr.number;
+ assert generation_number_ipr.next_index == lpr.start_index + 16;
+
+ assert pdf[generation_number_ipr.next_index] == PDFNames.WHITESPACE_SP;
+ int usage_index = generation_number_ipr.next_index + 1;
+
+ lpr.object_usage = pdf[usage_index];
+ assert lpr.object_usage == 'n' || lpr.object_usage == 'f';
+
+ if (pdf[usage_index + 1] == PDFNames.WHITESPACE_SP)
+ {
+ assert pdf[usage_index + 2] == PDFNames.WHITESPACE_CR || pdf[usage_index + 2] == PDFNames.WHITESPACE_LF;
+ }
+ else
+ {
+ assert pdf[usage_index + 1] == PDFNames.WHITESPACE_CR;
+ assert pdf[usage_index + 2] == PDFNames.WHITESPACE_LF;
+ }
+
+ lpr.next_index = usage_index + 3;
+
+ assert lpr.next_index == lpr.start_index + 20;
+
+ return lpr;
+ }
+
+ public static int indexOfName(final byte[] pdf, List names,
+ byte[] sought)
+ {
+ for (int i = 0; i < names.size(); i++)
+ {
+ NameParseResult name = (NameParseResult) names.get(i);
+ if (ByteArrayUtils.compareByteArrays(pdf, name.name_start_index, sought))
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public static TrailerParseResult parseTrailer(final byte[] pdf,
+ final int index)
+ {
+ TrailerParseResult tpr = new TrailerParseResult();
+ tpr.start_index = index;
+ tpr.has_predecessor = false;
+
+ assert ByteArrayUtils.compareByteArrays(pdf, tpr.start_index, PDFNames.TRAILER_STR);
+
+ // assert isWhitespace(pdf[tpr.start_index + PDFNames.TRAILER_STR.length]);
+ tpr.contents_index = skipWhitespace(pdf, tpr.start_index + PDFNames.TRAILER_STR.length);
+
+ int trailer_dict_index = skipWhitespace(pdf, tpr.contents_index);
+
+ assert ByteArrayUtils.compareByteArrays(pdf, trailer_dict_index, PDFNames.DICT_START_STR);
+
+ tpr.dpr = parseDictionary(pdf, trailer_dict_index);
+
+ int cur_index = tpr.dpr.next_index;
+
+ int info_index = indexOfName(pdf, tpr.dpr.names, PDFNames.INFO_STR);
+ if (info_index >= 0)
+ {
+ tpr.info = (IndirectObjectReferenceParseResult) tpr.dpr.values.get(info_index);
+ }
+
+ int root_index = indexOfName(pdf, tpr.dpr.names, PDFNames.ROOT_STR);
+ if (root_index >= 0)
+ {
+ tpr.root = (IndirectObjectReferenceParseResult) tpr.dpr.values.get(root_index);
+ }
+
+ tpr.size = ((NumberParseResult) tpr.dpr.values.get(indexOfName(pdf, tpr.dpr.names, PDFNames.SIZE_STR))).number;
+
+ int prev_index = indexOfName(pdf, tpr.dpr.names, PDFNames.PREV_STR);
+ if (prev_index >= 0)
+ {
+ tpr.has_predecessor = true;
+ tpr.setPrev(((NumberParseResult) tpr.dpr.values.get(prev_index)).number);
+ }
+
+ //
+ // int cur_index = skipWhitespace(pdf, trailer_dict_index +
+ // PDFNames.DICT_START_STR.length);
+ // for (;;) {
+ // if (ByteArrayUtils.compareByteArrays(pdf, cur_index,
+ // PDFNames.DICT_END_STR)) {
+ // cur_index += PDFNames.DICT_END_STR.length;
+ // break;
+ // }
+ //
+ // assert pdf[cur_index] == PDFNames.DELIMITER_NAME;
+ // cur_index++;
+ //
+ // if (ByteArrayUtils.compareByteArrays(pdf, cur_index, PDFNames.INFO_STR))
+ // {
+ // assert isWhitespace(pdf[cur_index + PDFNames.INFO_STR.length]);
+ // int ir_index = skipWhitespace(pdf, cur_index + PDFNames.INFO_STR.length);
+ //
+ // IndirectObjectReferenceParseResult iorpr =
+ // parseIndirectObjectReference(pdf, ir_index);
+ // tpr.info = iorpr;
+ //
+ // cur_index = skipWhitespace(pdf, iorpr.next_index);
+ // continue;
+ // }
+ //
+ // if (ByteArrayUtils.compareByteArrays(pdf, cur_index, PDFNames.ROOT_STR))
+ // {
+ // assert isWhitespace(pdf[cur_index + PDFNames.ROOT_STR.length]);
+ // int ir_index = skipWhitespace(pdf, cur_index + PDFNames.ROOT_STR.length);
+ //
+ // IndirectObjectReferenceParseResult iorpr =
+ // parseIndirectObjectReference(pdf, ir_index);
+ // tpr.root = iorpr;
+ //
+ // cur_index = skipWhitespace(pdf, iorpr.next_index);
+ // continue;
+ // }
+ //
+ // if (ByteArrayUtils.compareByteArrays(pdf, cur_index, PDFNames.SIZE_STR))
+ // {
+ // assert isWhitespace(pdf[cur_index + PDFNames.SIZE_STR.length]);
+ // int size_index = skipWhitespace(pdf, cur_index +
+ // PDFNames.SIZE_STR.length);
+ //
+ // NumberParseResult npr = parseNumberFromByteArray(pdf, size_index);
+ // tpr.size = npr.number;
+ // assert tpr.size > 0;
+ //
+ // cur_index = skipWhitespace(pdf, npr.next_index);
+ // continue;
+ // }
+ //
+ // if (ByteArrayUtils.compareByteArrays(pdf, cur_index, PDFNames.PREV_STR))
+ // {
+ // assert isWhitespace(pdf[cur_index + PDFNames.PREV_STR.length]);
+ // int prev_index = skipWhitespace(pdf, cur_index +
+ // PDFNames.PREV_STR.length);
+ //
+ // NumberParseResult npr = parseNumberFromByteArray(pdf, prev_index);
+ // tpr.has_predecessor = true;
+ // tpr.setPrev(npr.number);
+ // assert tpr.getPrev() >= 0;
+ // assert tpr.getPrev() < pdf.length;
+ //
+ // assert ByteArrayUtils.compareByteArrays(pdf, tpr.getPrev(),
+ // PDFNames.XREF_STR);
+ //
+ // cur_index = skipWhitespace(pdf, npr.next_index);
+ // continue;
+ // }
+ //
+ // // unrecognized type
+ // // skip to next delimiter
+ // // TODO: this will not work with nested dicts. - already deprecated
+ // while (pdf[cur_index] != PDFNames.DELIMITER_NAME) {
+ // cur_index++;
+ // }
+ // }
+
+ tpr.contents_end_index = cur_index;
+ tpr.next_index = skipWhitespace(pdf, tpr.contents_end_index);
+
+ assert ByteArrayUtils.compareByteArrays(pdf, tpr.next_index, PDFNames.STARTXREF_STR);
+ return tpr;
+ }
+
+ /**
+ * Parses the startxref section at pdf+index.
+ *
+ * @param pdf
+ * The complete PDF file data.
+ * @param index
+ * The index of the startxref section.
+ * @return Returns the retsult of the parsing operation.
+ */
+ public static StartXRefParseResult parseStartXRef(final byte[] pdf,
+ final int index)
+ {
+ StartXRefParseResult spr = new StartXRefParseResult();
+ spr.next_index = index;
+
+ assert ByteArrayUtils.compareByteArrays(pdf, index, PDFNames.STARTXREF_STR);
+ assert isNewline(pdf, index + PDFNames.STARTXREF_STR.length);
+
+ int index_of_number = skipWhitespace(pdf, index + PDFNames.STARTXREF_STR.length);
+ // skipNewline(pdf, index + PDFNames.STARTXREF_STR.length);
+ NumberParseResult npr = parseNumberFromByteArray(pdf, index_of_number);
+ spr.xref_index = npr.number;
+
+ assert isNewline(pdf, npr.next_index);
+ spr.next_index = skipWhitespace(pdf, npr.next_index);
+ // skipNewline(pdf, npr.next_index);
+
+ assert ByteArrayUtils.compareByteArrays(pdf, spr.next_index, PDFNames.EOF_STR);
+
+ assert spr.xref_index >= 0;
+ assert spr.xref_index < pdf.length;
+
+ // A linearized document sets the startxref value of the first page's footer
+ // to 0.
+ if (spr.xref_index != 0)
+ {
+ assert ByteArrayUtils.compareByteArrays(pdf, spr.xref_index, PDFNames.XREF_STR);
+ }
+
+ return spr;
+ }
+
+ /**
+ * Parses the End Of File (EOF) marker at pdf+index.
+ *
+ * @param pdf
+ * The PDF data.
+ * @param index
+ * The index where to start the parsing.
+ * @return Returns the result of the parsing operation.
+ */
+ public static EOFParseResult parseEOF(final byte[] pdf, final int index)
+ {
+ EOFParseResult eofpr = new EOFParseResult();
+ eofpr.start_index = index;
+
+ assert ByteArrayUtils.compareByteArrays(pdf, eofpr.start_index, PDFNames.EOF_STR);
+
+ eofpr.eof_end_index = eofpr.start_index + PDFNames.EOF_STR.length;
+
+ // Note: The EOF marker is not necessarily terminated with a
+ // newline.
+
+ // perhaps explicitely determine a newline.
+
+ eofpr.next_index = eofpr.eof_end_index;
+
+ return eofpr;
+ }
+
+ public static boolean isIndirectObjectReference(final byte[] pdf,
+ final int index)
+ {
+ IndirectObjectReferenceParseResult iorpr = new IndirectObjectReferenceParseResult();
+ iorpr.ior = new IndirectObjectReference();
+ iorpr.start_index = index;
+
+ if (!PDFUtils.isNumeric(pdf[iorpr.start_index]))
+ {
+ return false;
+ }
+ NumberParseResult object_number_npr = parseNumberFromByteArray(pdf, iorpr.start_index);
+ iorpr.ior.object_number = object_number_npr.number;
+ if (iorpr.ior.object_number <= 0)
+ {
+ return false;
+ }
+
+ if (!isWhitespace(pdf[object_number_npr.next_index]))
+ {
+ return false;
+ }
+ int generation_number_index = skipWhitespace(pdf, object_number_npr.next_index);
+
+ if (!PDFUtils.isNumeric(pdf[generation_number_index]))
+ {
+ return false;
+ }
+ NumberParseResult generation_number_npr = parseNumberFromByteArray(pdf, generation_number_index);
+ iorpr.ior.generation_number = generation_number_npr.number;
+ if (iorpr.ior.generation_number < 0)
+ {
+ return false;
+ }
+
+ if (!isWhitespace(pdf[generation_number_npr.next_index]))
+ {
+ return false;
+ }
+ int R_index = skipWhitespace(pdf, generation_number_npr.next_index);
+
+ if (!ByteArrayUtils.compareByteArrays(pdf, R_index, PDFNames.REFERENCE_STR))
+ {
+ return false;
+ }
+
+ iorpr.next_index = R_index + PDFNames.REFERENCE_STR.length;
+
+ return true;
+ }
+
+ /**
+ * Parses an indirect object reference.
+ *
+ * @param pdf
+ * The PDF data.
+ * @param index
+ * The index.
+ * @return Returns the result of the parsing operation.
+ */
+ public static IndirectObjectReferenceParseResult parseIndirectObjectReference(
+ final byte[] pdf, final int index)
+ {
+
+ assert isIndirectObjectReference(pdf, index);
+
+ IndirectObjectReferenceParseResult iorpr = new IndirectObjectReferenceParseResult();
+ iorpr.ior = new IndirectObjectReference();
+ iorpr.start_index = index;
+
+ NumberParseResult object_number_npr = parseNumberFromByteArray(pdf, iorpr.start_index);
+ iorpr.ior.object_number = object_number_npr.number;
+ assert iorpr.ior.object_number > 0;
+
+ assert isWhitespace(pdf[object_number_npr.next_index]);
+ int generation_number_index = skipWhitespace(pdf, object_number_npr.next_index);
+
+ NumberParseResult generation_number_npr = parseNumberFromByteArray(pdf, generation_number_index);
+ iorpr.ior.generation_number = generation_number_npr.number;
+ assert iorpr.ior.generation_number >= 0;
+
+ assert isWhitespace(pdf[generation_number_npr.next_index]);
+ int R_index = skipWhitespace(pdf, generation_number_npr.next_index);
+
+ assert ByteArrayUtils.compareByteArrays(pdf, R_index, PDFNames.REFERENCE_STR);
+
+ iorpr.next_index = R_index + PDFNames.REFERENCE_STR.length;
+
+ return iorpr;
+ }
+
+ /**
+ * Parses the object header at pdf+index.
+ *
+ * @param pdf
+ * The PDF data.
+ * @param index
+ * The index.
+ * @return Returns the result of the parsing operation.
+ */
+ public static ObjectHeaderParseResult parseObjectHeader(final byte[] pdf,
+ final int index)
+ {
+ ObjectHeaderParseResult ohpr = new ObjectHeaderParseResult();
+
+ ohpr.start_index = index;
+
+ NumberParseResult object_number_npr = parseNumberFromByteArray(pdf, ohpr.start_index);
+ ohpr.object_number = object_number_npr.number;
+ assert ohpr.object_number > 0;
+
+ assert isWhitespace(pdf[object_number_npr.next_index]);
+ int generation_number_index = skipWhitespace(pdf, object_number_npr.next_index);
+
+ NumberParseResult generation_number_npr = parseNumberFromByteArray(pdf, generation_number_index);
+ ohpr.generation_number = generation_number_npr.number;
+ assert ohpr.generation_number >= 0;
+
+ assert isWhitespace(pdf[generation_number_npr.next_index]);
+ int obj_index = skipWhitespace(pdf, generation_number_npr.next_index);
+
+ assert ByteArrayUtils.compareByteArrays(pdf, obj_index, PDFNames.OBJ_STR);
+
+ // not all pdfwriters make a newline after obj...
+ // assert isNewline(pdf, obj_index + PDFNames.OBJ_STR.length);
+ // ohpr.next_index = skipNewline(pdf, obj_index + PDFNames.OBJ_STR.length);
+ ohpr.next_index = skipWhitespace(pdf, obj_index + PDFNames.OBJ_STR.length);
+
+ return ohpr;
+ }
+
+ public static ObjectParseResult parseObject(final byte[] pdf, final int index)
+ {
+ ObjectParseResult opr = new ObjectParseResult();
+ opr.start_index = index;
+
+ opr.header = parseObjectHeader(pdf, opr.start_index);
+ opr.content_index = opr.header.next_index;
+
+ int cur_index = skipWhitespace(pdf, opr.content_index);
+
+ opr.object = parseUnknownObject(pdf, cur_index);
+
+ cur_index = skipWhitespace(pdf, opr.object.next_index);
+
+ opr.end_of_content_index = cur_index;
+ assert ByteArrayUtils.compareByteArrays(pdf, opr.end_of_content_index, PDFNames.ENDOBJ_STR);
+
+ cur_index = opr.end_of_content_index + PDFNames.ENDOBJ_STR.length;
+
+ opr.next_index = cur_index;
+ //assert isNewline(pdf, cur_index);
+ //opr.next_index = skipNewline(pdf, cur_index);
+
+ return opr;
+ }
+
+ public static ParseResult parseUnknownObject(final byte[] pdf, final int index)
+ {
+ if (ByteArrayUtils.compareByteArrays(pdf, index, PDFNames.DICT_START_STR))
+ {
+ DictionaryParseResult dpr = parseDictionary(pdf, index);
+
+ int possible_stream_index = skipWhitespace(pdf, dpr.next_index);
+ if (ByteArrayUtils.compareByteArrays(pdf, possible_stream_index, PDFNames.STREAM_STR))
+ {
+ return parseStream(pdf, possible_stream_index, dpr);
+ }
+
+ return dpr;
+ }
+
+ if (ByteArrayUtils.compareByteArrays(pdf, index, PDFNames.NULL_STR))
+ {
+ return parseNull(pdf, index);
+ }
+
+ if (ByteArrayUtils.compareByteArrays(pdf, index, PDFNames.TRUE_STR) || ByteArrayUtils.compareByteArrays(pdf, index, PDFNames.FALSE_STR))
+ {
+ return parseBoolean(pdf, index);
+ }
+
+ final byte first_byte = pdf[index];
+
+ if (isNumeric(first_byte) || isSign(first_byte))
+ {
+
+ // try to parse a Indirect reference first - if this fails, parse a number
+ if (isIndirectObjectReference(pdf, index))
+ {
+ return parseIndirectObjectReference(pdf, index);
+ }
+
+ return parseNumberFromByteArray(pdf, index);
+ }
+
+ ParseResult pr = null;
+
+ switch (first_byte)
+ {
+ case PDFNames.DELIMITER_STRING_OPEN:
+ pr = parseLiteralString(pdf, index);
+ break;
+ case PDFNames.DELIMITER_HEXSTRING_OPEN:
+ pr = parseHexString(pdf, index);
+ break;
+ case PDFNames.DELIMITER_ARRAY_OPEN:
+ pr = parseArray(pdf, index);
+ break;
+ case PDFNames.DELIMITER_NAME:
+ pr = parseName(pdf, index);
+ break;
+ default:
+ throw new RuntimeException("Unknown first_byte " + first_byte + "' when parsing an unknown object at index=" + index + ".");
+ // assert false : "nyi or invalid char";
+ }
+ assert pr != null;
+
+ return pr;
+ }
+
+ /**
+ * Parses a literal string.
+ *
+ * <p>
+ * A literal string is a string of ASCII characters enclosed by '(' and ')'.
+ * Balanced pairs of '(' and ')' are allowed within the string. Unbalanced '('
+ * or ')' must be escaped as '\(' or '\)'.
+ * </p>
+ *
+ * @param pdf
+ * The PDF data.
+ * @param index
+ * The index.
+ * @return Returns the result of the parsing operation.
+ */
+ public static LiteralStringParseResult parseLiteralString(final byte[] pdf,
+ final int index)
+ {
+ LiteralStringParseResult lspr = new LiteralStringParseResult();
+ lspr.start_index = index;
+
+ assert pdf[lspr.start_index] == PDFNames.DELIMITER_STRING_OPEN;
+
+ lspr.content_start_index = lspr.start_index + 1;
+
+ int cur_index = lspr.content_start_index;
+ int parenthesis_stack = 0;
+ for (;;)
+ {
+ if (pdf[cur_index] == '\\' && (pdf[cur_index + 1] == PDFNames.DELIMITER_STRING_CLOSE || pdf[cur_index + 1] == PDFNames.DELIMITER_STRING_OPEN))
+ {
+ cur_index += 2;
+ continue;
+ }
+ if (pdf[cur_index] == PDFNames.DELIMITER_STRING_OPEN)
+ {
+ parenthesis_stack++;
+ }
+ if (pdf[cur_index] == PDFNames.DELIMITER_STRING_CLOSE)
+ {
+ assert parenthesis_stack >= 0;
+
+ if (parenthesis_stack == 0)
+ {
+ break;
+ }
+
+ assert parenthesis_stack > 0;
+ parenthesis_stack--;
+
+ }
+
+ cur_index++;
+ }
+
+ lspr.content_end_index = cur_index;
+ assert pdf[lspr.content_end_index] == PDFNames.DELIMITER_STRING_CLOSE;
+
+ lspr.next_index = lspr.content_end_index + 1;
+
+ return lspr;
+ }
+
+ protected static boolean isHex(final byte data)
+ {
+ return isNumeric(data) || ('a' <= data && data <= 'f') || ('A' <= data && data <= 'f');
+ }
+
+ /**
+ * Parses a hexadecimal string.
+ *
+ * @param pdf
+ * The PDF data.
+ * @param index
+ * The index.
+ * @return Returns the result of the parsing operation.
+ */
+ public static HexStringParseResult parseHexString(final byte[] pdf,
+ final int index)
+ {
+ HexStringParseResult hspr = new HexStringParseResult();
+ hspr.start_index = index;
+
+ assert pdf[hspr.start_index] == PDFNames.DELIMITER_HEXSTRING_OPEN;
+
+ hspr.content_start_index = hspr.start_index + 1;
+
+ int cur_index = hspr.content_start_index;
+ while (isHex(pdf[cur_index]) || isWhitespace(pdf[cur_index]))
+ {
+ cur_index++;
+ }
+
+ hspr.content_end_index = cur_index;
+ assert pdf[hspr.content_end_index] == PDFNames.DELIMITER_HEXSTRING_CLOSE;
+
+ hspr.next_index = hspr.content_end_index + 1;
+
+ return hspr;
+ }
+
+ public static ArrayParseResult parseArray(final byte[] pdf, final int index)
+ {
+ ArrayParseResult apr = new ArrayParseResult();
+ apr.start_index = index;
+ assert pdf[apr.start_index] == PDFNames.DELIMITER_ARRAY_OPEN;
+
+ apr.content_start_index = apr.start_index + 1;
+
+ apr.elements = new ArrayList();
+
+ int cur_index = skipWhitespace(pdf, apr.content_start_index);
+ for (;;)
+ {
+ if (pdf[cur_index] == PDFNames.DELIMITER_ARRAY_CLOSE)
+ {
+ break;
+ }
+
+ ParseResult pr = parseUnknownObject(pdf, cur_index);
+ apr.elements.add(pr);
+
+ cur_index = skipWhitespace(pdf, pr.next_index);
+ }
+ assert pdf[cur_index] == PDFNames.DELIMITER_ARRAY_CLOSE;
+
+ apr.content_end_index = cur_index;
+ assert pdf[apr.content_end_index] == PDFNames.DELIMITER_ARRAY_CLOSE;
+
+ apr.next_index = apr.content_end_index + 1;
+ return apr;
+ }
+
+ /**
+ * Parses a PDF Name.
+ *
+ * @param pdf
+ * The PDF data.
+ * @param index
+ * The index.
+ * @return Returns the result of this parsing operation.
+ */
+ public static NameParseResult parseName(final byte[] pdf, final int index)
+ {
+ NameParseResult npr = new NameParseResult();
+ npr.start_index = index;
+
+ assert pdf[npr.start_index] == PDFNames.DELIMITER_NAME;
+
+ npr.name_start_index = npr.start_index + 1;
+
+ assert isRegular(pdf[npr.name_start_index]);
+
+ int cur_index = npr.name_start_index;
+ while (isRegular(pdf[cur_index]))
+ {
+ cur_index++;
+ }
+ assert !isRegular(pdf[cur_index]);
+
+ npr.next_index = cur_index;
+
+ return npr;
+ }
+
+ public static DictionaryParseResult parseDictionary(final byte[] pdf,
+ final int index)
+ {
+ DictionaryParseResult dpr = new DictionaryParseResult();
+ dpr.start_index = index;
+
+ assert ByteArrayUtils.compareByteArrays(pdf, index, PDFNames.DICT_START_STR);
+
+ dpr.content_start_index = dpr.start_index + PDFNames.DICT_START_STR.length;
+
+ dpr.names = new ArrayList();
+ dpr.values = new ArrayList();
+
+ int cur_index = skipWhitespace(pdf, dpr.content_start_index);
+ for (;;)
+ {
+ if (ByteArrayUtils.compareByteArrays(pdf, cur_index, PDFNames.DICT_END_STR))
+ {
+ break;
+ }
+
+ NameParseResult npr = parseName(pdf, cur_index);
+ dpr.names.add(npr);
+
+ cur_index = npr.next_index;
+ cur_index = skipWhitespace(pdf, cur_index);
+
+ ParseResult pr = parseUnknownObject(pdf, cur_index);
+ dpr.values.add(pr);
+
+ cur_index = pr.next_index;
+ cur_index = skipWhitespace(pdf, cur_index);
+ }
+
+ dpr.content_end_index = cur_index;
+ assert ByteArrayUtils.compareByteArrays(pdf, dpr.content_end_index, PDFNames.DICT_END_STR);
+ dpr.next_index = dpr.content_end_index + PDFNames.DICT_END_STR.length;
+
+ return dpr;
+ }
+
+ /**
+ * Parses a stream.
+ *
+ * @param pdf
+ * The PDF data.
+ * @param index
+ * The index.
+ * @param dpr
+ * The DictionaryParseResult of the stream's dictionary. This
+ * dictionary must precede the stream keyword. Usually this is
+ * provided in the stream object's dictionary via the /Length field.
+ * @return Returns the result of this parsing operation.
+ */
+ public static StreamParseResult parseStream(final byte[] pdf,
+ final int index, final DictionaryParseResult dpr)
+ {
+ StreamParseResult spr = new StreamParseResult();
+ spr.stream_dictionary = dpr;
+ spr.start_index = spr.stream_dictionary.start_index;
+ spr.stream_start_index = index;
+ assert ByteArrayUtils.compareByteArrays(pdf, index, PDFNames.STREAM_STR);
+
+ // assert that the provided dictionary really belongs to this stream
+ assert spr.stream_start_index == skipWhitespace(pdf, spr.stream_dictionary.next_index);
+
+ // see PDF Spec 1.4 chapter 3.2.7
+ assert pdf[spr.stream_start_index + PDFNames.STREAM_STR.length] == PDFNames.WHITESPACE_LF || (pdf[spr.stream_start_index + PDFNames.STREAM_STR.length] == PDFNames.WHITESPACE_CR && pdf[spr.stream_start_index + PDFNames.STREAM_STR.length + 1] == PDFNames.WHITESPACE_LF);
+ spr.content_start_index = skipNewline(pdf, spr.stream_start_index + PDFNames.STREAM_STR.length);
+
+ int length = -1;
+ for (int i = 0; i < spr.stream_dictionary.names.size(); i++)
+ {
+ NameParseResult name = (NameParseResult) spr.stream_dictionary.names.get(i);
+ if (ByteArrayUtils.compareByteArrays(pdf, name.name_start_index, PDFNames.LENGTH_STR))
+ {
+ ParseResult pr = (ParseResult) spr.stream_dictionary.values.get(i);
+ NumberParseResult npr = null;
+ if (pr instanceof IndirectObjectReferenceParseResult)
+ {
+ log.debug("An object stream with indirect length - cannot parse this instantly - parse later again.");
+ spr.content_end_index = -1;
+ spr.next_index = -1;
+ return spr;
+
+ }
+ else
+ {
+ npr = (NumberParseResult) pr;
+ }
+ assert npr != null;
+
+ length = npr.number;
+ break;
+ }
+
+ }
+ assert length >= 0;
+
+ spr.content_end_index = spr.content_start_index + length;
+
+ int endstr_index = spr.content_end_index;
+ if (isNewline(pdf, endstr_index))
+ {
+ endstr_index = skipWhitespace(pdf, endstr_index);
+ }
+ assert ByteArrayUtils.compareByteArrays(pdf, endstr_index, PDFNames.ENDSTREAM_STR);
+
+ spr.next_index = endstr_index + PDFNames.ENDSTREAM_STR.length;
+
+ return spr;
+ }
+
+ public static NullParseResult parseNull(final byte[] pdf, final int index)
+ {
+ NullParseResult npr = new NullParseResult();
+ npr.start_index = index;
+
+ assert ByteArrayUtils.compareByteArrays(pdf, npr.start_index, PDFNames.NULL_STR);
+
+ npr.next_index = npr.start_index + PDFNames.NULL_STR.length;
+
+ return npr;
+ }
+
+ public static int getObjectOffsetFromXRefByIndirectObjectReference(
+ XRefSectionParseResult xpr, IndirectObjectReference ior)
+ {
+ Iterator it = xpr.xref_subsections.iterator();
+ while (it.hasNext())
+ {
+ XRefSubSectionParseResult section = (XRefSubSectionParseResult) it.next();
+
+ for (int i = 0; i < section.xref_lines.size(); i++)
+ {
+ if (section.start_obj_number + i == ior.object_number)
+ {
+ XRefLineParseResult lpr = (XRefLineParseResult) section.xref_lines.get(i);
+ return lpr.object_offset;
+ }
+ }
+ }
+
+ return -1;
+ }
+
+ public static HeaderParseResult parseHeader(final byte[] pdf, final int index)
+ {
+ HeaderParseResult hpr = new HeaderParseResult();
+ hpr.start_index = index;
+
+ assert pdf[hpr.start_index] == PDFNames.COMMENT;
+
+ assert ByteArrayUtils.compareByteArrays(pdf, hpr.start_index + 1, PDFNames.PDF_VERSION_STR);
+
+ hpr.major_index = hpr.start_index + 1 + PDFNames.PDF_VERSION_STR.length;
+
+ IntegerParseResult major_ipr = parseUnsignedInteger(pdf, hpr.major_index);
+ hpr.major = major_ipr.number;
+ assert hpr.major >= 1;
+
+ assert pdf[major_ipr.next_index] == PDFNames.PDF_VERSION_SEPARATOR;
+
+ hpr.minor_index = major_ipr.next_index + 1;
+
+ IntegerParseResult minor_ipr = parseUnsignedInteger(pdf, hpr.minor_index);
+ hpr.minor = minor_ipr.number;
+ assert hpr.minor >= 0;
+
+ assert isWhitespace(pdf[minor_ipr.next_index]);
+ hpr.binary_characters_index = skipWhitespace(pdf, minor_ipr.next_index);
+
+ assert pdf[hpr.binary_characters_index] == PDFNames.COMMENT;
+
+ hpr.next_index = skipToNewline(pdf, hpr.binary_characters_index);
+ return hpr;
+ }
+
+ /**
+ * Parses a PDF footer.
+ *
+ * <p>
+ * A PDF footer starts with the xref, followed by the trailer, the startxref
+ * and the EOF marker.
+ * </p>
+ *
+ * @param pdf
+ * The PDF data.
+ * @param index
+ * The index.
+ * @return Returns the result of the parsing operation.
+ *
+ * @see FooterParseResult
+ */
+ public static FooterParseResult parseFooter(final byte[] pdf, final int index)
+ {
+ FooterParseResult fpr = new FooterParseResult();
+ fpr.start_index = index;
+
+ fpr.xpr = PDFUtils.parseXRefSection(pdf, fpr.start_index);
+
+ fpr.tpr = PDFUtils.parseTrailer(pdf, fpr.xpr.next_index);
+
+ fpr.sxpr = PDFUtils.parseStartXRef(pdf, fpr.tpr.next_index);
+
+ fpr.eofpr = PDFUtils.parseEOF(pdf, fpr.sxpr.next_index);
+
+ fpr.next_index = fpr.eofpr.next_index;
+ return fpr;
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/ArrayParseResult.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/ArrayParseResult.java
new file mode 100644
index 0000000..9d0a745
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/ArrayParseResult.java
@@ -0,0 +1,42 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: ArrayParseResult.java,v 1.1 2006/08/25 17:00:59 wprinz Exp $
+ */
+package at.knowcenter.wag.exactparser.parsing.results;
+
+import java.util.List;
+
+/**
+ * The result of parsing a hex string.
+ *
+ * @see at.knowcenter.wag.exactparser.parsing.results.LiteralStringParseResult
+ *
+ * @author wprinz
+ */
+public class ArrayParseResult extends ContainerParseResult {
+
+ public List elements = null;
+
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/BooleanParseResult.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/BooleanParseResult.java
new file mode 100644
index 0000000..e0bc276
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/BooleanParseResult.java
@@ -0,0 +1,38 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: BooleanParseResult.java,v 1.1 2006/08/25 17:00:59 wprinz Exp $
+ */
+package at.knowcenter.wag.exactparser.parsing.results;
+
+/**
+ * Parse result of parsing a boolean value.
+ *
+ * @author wprinz
+ */
+public class BooleanParseResult extends ParseResult
+{
+
+ public boolean value = false;
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/ContainerParseResult.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/ContainerParseResult.java
new file mode 100644
index 0000000..1974ade
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/ContainerParseResult.java
@@ -0,0 +1,45 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: ContainerParseResult.java,v 1.1 2006/08/25 17:00:59 wprinz Exp $
+ */
+package at.knowcenter.wag.exactparser.parsing.results;
+
+/**
+ * Base class of container parse results.
+ *
+ * <p>
+ * Containers are types that include some content.
+ * E.g. literal strings include string data as content,
+ * arrays include elements as content etc.
+ * </p>
+ *
+ * @author wprinz
+ */
+public class ContainerParseResult extends ParseResult {
+
+ public int content_start_index = -1;
+ public int content_end_index = -1;
+
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/DictionaryParseResult.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/DictionaryParseResult.java
new file mode 100644
index 0000000..47101e0
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/DictionaryParseResult.java
@@ -0,0 +1,41 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: DictionaryParseResult.java,v 1.1 2006/08/25 17:00:59 wprinz Exp $
+ */
+package at.knowcenter.wag.exactparser.parsing.results;
+
+import java.util.List;
+
+/**
+ * The result of parsing a dictionary.
+ *
+ * @author wprinz
+ */
+public class DictionaryParseResult extends ContainerParseResult
+{
+
+ public List names = null;
+
+ public List values = null;
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/EOFParseResult.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/EOFParseResult.java
new file mode 100644
index 0000000..dea1d22
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/EOFParseResult.java
@@ -0,0 +1,47 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: EOFParseResult.java,v 1.1 2006/08/25 17:00:59 wprinz Exp $
+ */
+package at.knowcenter.wag.exactparser.parsing.results;
+
+/**
+ * The result of parsing the End Of File marker.
+ *
+ * @author wprinz
+ */
+public class EOFParseResult extends ParseResult
+{
+
+ /**
+ * The index of the byte after the EOF marker.
+ *
+ * <p>
+ * A newline is not necessary after the EOF marker, but if it is present it will be considered
+ * as part of it.
+ * So eof_end_index marks this newline.
+ * If eof_end_index == next_index, then no new line is present.
+ * </p>
+ */
+ public int eof_end_index = -1;
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/FooterParseResult.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/FooterParseResult.java
new file mode 100644
index 0000000..2a52aa6
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/FooterParseResult.java
@@ -0,0 +1,53 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: FooterParseResult.java,v 1.1 2006/08/25 17:00:59 wprinz Exp $
+ */
+package at.knowcenter.wag.exactparser.parsing.results;
+
+
+/**
+ * The result of parsing a PDF footer block.
+ *
+ * <p>
+ * A PDF footer block starts with the xref table followed by the trailer, the
+ * startxref and finally the EOF marker. Usually the footer should be at the end
+ * of the file. All object offsets in the footer's xref table should be before
+ * the footer itself. Nevertheless, there are PDF Writers (e.g. Microsoft Word)
+ * that put the footer at the beginning of the document so that all indirect
+ * objects are after the EOF marker.
+ * </p>
+ *
+ * @author wprinz
+ */
+public class FooterParseResult extends ParseResult
+{
+
+ public StartXRefParseResult sxpr = null;
+
+ public EOFParseResult eofpr = null;
+
+ public XRefSectionParseResult xpr = null;
+
+ public TrailerParseResult tpr = null;
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/HeaderParseResult.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/HeaderParseResult.java
new file mode 100644
index 0000000..3befda3
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/HeaderParseResult.java
@@ -0,0 +1,48 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: HeaderParseResult.java,v 1.1 2006/08/25 17:00:59 wprinz Exp $
+ */
+package at.knowcenter.wag.exactparser.parsing.results;
+
+/**
+ * The result of parsing the PDF header.
+ *
+ * <p>
+ * The header contains the PDF version and is usually followed by some binary
+ * characers.
+ * </p>
+ *
+ * @author wprinz
+ */
+public class HeaderParseResult extends ParseResult
+{
+ public int major_index = -1;
+ public int minor_index = -1;
+
+ public int major = -1;
+ public int minor = -1;
+
+ public int binary_characters_index = -1;
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/HexStringParseResult.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/HexStringParseResult.java
new file mode 100644
index 0000000..27dbf70
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/HexStringParseResult.java
@@ -0,0 +1,36 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: HexStringParseResult.java,v 1.1 2006/08/25 17:00:59 wprinz Exp $
+ */
+package at.knowcenter.wag.exactparser.parsing.results;
+
+/**
+ * The result of parsing a hex string.
+ *
+ * @see at.knowcenter.wag.exactparser.parsing.results.LiteralStringParseResult
+ *
+ * @author wprinz
+ */
+public class HexStringParseResult extends ContainerParseResult {
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/IndirectObjectReferenceParseResult.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/IndirectObjectReferenceParseResult.java
new file mode 100644
index 0000000..797678e
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/IndirectObjectReferenceParseResult.java
@@ -0,0 +1,44 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: IndirectObjectReferenceParseResult.java,v 1.1 2006/08/25 17:00:59 wprinz Exp $
+ */
+package at.knowcenter.wag.exactparser.parsing.results;
+
+import at.knowcenter.wag.exactparser.parsing.IndirectObjectReference;
+
+/**
+ * The ParseResult of parsing an indirect object reference.
+ *
+ * @author wprinz
+ */
+public class IndirectObjectReferenceParseResult extends ParseResult {
+
+ public IndirectObjectReference ior;
+
+ //@Override
+ public String toString()
+ {
+ return ior.toString() + " R";
+ }
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/IntegerParseResult.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/IntegerParseResult.java
new file mode 100644
index 0000000..48ea7d2
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/IntegerParseResult.java
@@ -0,0 +1,36 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: IntegerParseResult.java,v 1.1 2006/08/25 17:00:59 wprinz Exp $
+ */
+package at.knowcenter.wag.exactparser.parsing.results;
+
+/**
+ * @author wprinz
+ */
+public class IntegerParseResult extends ParseResult
+{
+
+ public int number;
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/LiteralStringParseResult.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/LiteralStringParseResult.java
new file mode 100644
index 0000000..60fc277
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/LiteralStringParseResult.java
@@ -0,0 +1,37 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: LiteralStringParseResult.java,v 1.1 2006/08/25 17:00:59 wprinz Exp $
+ */
+package at.knowcenter.wag.exactparser.parsing.results;
+
+/**
+ * The result of parsing a simple string (ASCII string).
+ *
+ * @see at.knowcenter.wag.exactparser.parsing.results.HexStringParseResult
+ *
+ * @author wprinz
+ */
+public class LiteralStringParseResult extends ContainerParseResult {
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/NameParseResult.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/NameParseResult.java
new file mode 100644
index 0000000..e564285
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/NameParseResult.java
@@ -0,0 +1,35 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: NameParseResult.java,v 1.1 2006/08/25 17:00:59 wprinz Exp $
+ */
+package at.knowcenter.wag.exactparser.parsing.results;
+
+/**
+ * @author wprinz
+ */
+public class NameParseResult extends ParseResult {
+
+ public int name_start_index = -1;
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/NullParseResult.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/NullParseResult.java
new file mode 100644
index 0000000..49d9dfb
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/NullParseResult.java
@@ -0,0 +1,34 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: NullParseResult.java,v 1.1 2006/08/25 17:00:59 wprinz Exp $
+ */
+package at.knowcenter.wag.exactparser.parsing.results;
+
+/**
+ * The result of parsing a "null".
+ *
+ * @author wprinz
+ */
+public class NullParseResult extends ParseResult {
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/NumberParseResult.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/NumberParseResult.java
new file mode 100644
index 0000000..e88596c
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/NumberParseResult.java
@@ -0,0 +1,41 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: NumberParseResult.java,v 1.1 2006/08/25 17:00:59 wprinz Exp $
+ */
+package at.knowcenter.wag.exactparser.parsing.results;
+
+/**
+ * The ParseResult of parsing an integer number.
+ *
+ * @author wprinz
+ */
+public class NumberParseResult extends ParseResult {
+ /**
+ * The (signed) integer number.
+ */
+ public int number;
+
+ // TODO: make better
+ public float floating;
+} \ No newline at end of file
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/ObjectHeaderParseResult.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/ObjectHeaderParseResult.java
new file mode 100644
index 0000000..0729108
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/ObjectHeaderParseResult.java
@@ -0,0 +1,51 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: ObjectHeaderParseResult.java,v 1.1 2006/08/25 17:00:59 wprinz Exp $
+ */
+package at.knowcenter.wag.exactparser.parsing.results;
+
+/**
+ * The ParseResult of a parsing an object header.
+ *
+ * <p>
+ * Note that this information regards only the object header and not the
+ * contents of the object itself. (meaning: next points to the contents and not
+ * to the end of the whole object)
+ * </p>
+ *
+ * @author Administrator
+ */
+public class ObjectHeaderParseResult extends ParseResult {
+
+ /**
+ * The object's object number.
+ */
+ public int object_number = -1;
+
+ /**
+ * The object's generation number.
+ */
+ public int generation_number = -1;
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/ObjectParseResult.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/ObjectParseResult.java
new file mode 100644
index 0000000..2fdde34
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/ObjectParseResult.java
@@ -0,0 +1,50 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: ObjectParseResult.java,v 1.1 2006/08/25 17:00:59 wprinz Exp $
+ */
+package at.knowcenter.wag.exactparser.parsing.results;
+
+
+/**
+ * The ParseResult of parsing an indirect object.
+ * @author wprinz
+ */
+public class ObjectParseResult extends ParseResult {
+
+ public int content_index = -1;
+ public int end_of_content_index = -1;
+
+ public ObjectHeaderParseResult header = null;
+
+/* enum ObjectType
+ {
+ UNKNOWN_TO_PARSER,
+ OBJ_DICTIONARY
+ };
+
+ public ObjectType object_type = ObjectType.UNKNOWN_TO_PARSER;
+ */
+ public ParseResult object = null;
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/ParseResult.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/ParseResult.java
new file mode 100644
index 0000000..12c4b19
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/ParseResult.java
@@ -0,0 +1,50 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: ParseResult.java,v 1.1 2006/08/25 17:00:59 wprinz Exp $
+ */
+package at.knowcenter.wag.exactparser.parsing.results;
+
+/**
+ * Base class of all parse results.
+ *
+ * @author wprinz
+ */
+public class ParseResult {
+
+ /**
+ * The start index, where the parser started its work and where the parsed
+ * entity begins.
+ */
+ public int start_index = -1;
+
+ /**
+ * The index of the next entity following the currently parsed entity.
+ *
+ * <p>
+ * This is the index of the first byte not belonging to this entity anymore.
+ * </p>
+ */
+ public int next_index = -1;
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/StartXRefParseResult.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/StartXRefParseResult.java
new file mode 100644
index 0000000..a1f6792
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/StartXRefParseResult.java
@@ -0,0 +1,36 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: StartXRefParseResult.java,v 1.1 2006/08/25 17:00:59 wprinz Exp $
+ */
+package at.knowcenter.wag.exactparser.parsing.results;
+
+
+/**
+ * The ParseResult of parsing a startxref entry.
+ * @author wprinz
+ */
+public class StartXRefParseResult extends ParseResult {
+
+ public int xref_index;
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/StreamParseResult.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/StreamParseResult.java
new file mode 100644
index 0000000..16da12a
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/StreamParseResult.java
@@ -0,0 +1,41 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: StreamParseResult.java,v 1.1 2006/08/25 17:00:59 wprinz Exp $
+ */
+package at.knowcenter.wag.exactparser.parsing.results;
+
+
+/**
+ * The result of parsing a hex string.
+ *
+ * @see at.knowcenter.wag.exactparser.parsing.results.LiteralStringParseResult
+ *
+ * @author wprinz
+ */
+public class StreamParseResult extends ContainerParseResult {
+
+ public DictionaryParseResult stream_dictionary = null;
+
+ public int stream_start_index = -1;
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/TrailerParseResult.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/TrailerParseResult.java
new file mode 100644
index 0000000..4589ee8
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/TrailerParseResult.java
@@ -0,0 +1,84 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: TrailerParseResult.java,v 1.1 2006/08/25 17:00:59 wprinz Exp $
+ */
+package at.knowcenter.wag.exactparser.parsing.results;
+
+/**
+ * The ParseResult of parsing the trailer.
+ *
+ * @author wprinz
+ */
+public class TrailerParseResult extends ParseResult {
+
+ public int contents_index = -1;
+ public int contents_end_index = -1;
+
+ public DictionaryParseResult dpr = null;
+
+ public IndirectObjectReferenceParseResult info;
+
+ public IndirectObjectReferenceParseResult root;
+
+ /**
+ * The content of the "/Size" entry.
+ */
+ public int size;
+
+ /**
+ * Tells, if this PDF footer has a predecessor (as specified by
+ * the /Prev entry).
+ */
+ public boolean has_predecessor = false;
+
+ /**
+ * The index of the predecessor.
+ *
+ * <p>
+ * Only valid if has_predecessor is true.
+ * </p>
+ * <p>
+ * Use getPrev and setPrev to access this member variable.
+ * </p>
+ *
+ * @see #getPrev()
+ * @see #setPrev(int)
+ */
+ private int prev = -1;
+
+ public int getPrev() {
+ assert has_predecessor;
+ return prev;
+ }
+
+ public void setPrev(int prev) {
+ assert has_predecessor : "Set has_predecessor to true first.";
+ this.prev = prev;
+ }
+
+
+
+
+
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/XRefLineParseResult.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/XRefLineParseResult.java
new file mode 100644
index 0000000..8039153
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/XRefLineParseResult.java
@@ -0,0 +1,40 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: XRefLineParseResult.java,v 1.1 2006/08/25 17:00:59 wprinz Exp $
+ */
+package at.knowcenter.wag.exactparser.parsing.results;
+
+/**
+ * The ParseResult of parsing a single xref line.
+ *
+ * @author wprinz
+ */
+public class XRefLineParseResult extends ParseResult {
+
+ public int object_offset;
+
+ public int generation_number;
+
+ public byte object_usage;
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/XRefSectionParseResult.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/XRefSectionParseResult.java
new file mode 100644
index 0000000..eedea81
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/XRefSectionParseResult.java
@@ -0,0 +1,66 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: XRefSectionParseResult.java,v 1.1 2006/08/25 17:00:59 wprinz Exp $
+ */
+package at.knowcenter.wag.exactparser.parsing.results;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The ParseResult of an xref parsing operation.
+ *
+ * <p>
+ * This contains one whole xref table section. An xref section starts with the
+ * word xref and contains one or more xref sub-sections.
+ * </p>
+ * <p>
+ * Due to Incremental Updates, there may be more than one xref section in a
+ * document. All xref section together are called the xref table. Using this
+ * aggregated xref table, an application has the full access to all indirect
+ * objects in the document.
+ * </p>
+ * <p>
+ * In many PDF libraries and applications one xref section is also informally
+ * called xref table.
+ * </p>
+ *
+ * @author wprinz
+ */
+public class XRefSectionParseResult extends ParseResult
+{
+
+ public List xref_subsections = new ArrayList();
+
+ /**
+ * Appends another cross-reference (xref) sub-section to the xref table.
+ *
+ * @param xref_section
+ * The xref section to be appended.
+ */
+ public void appendXRefSubSection(XRefSubSectionParseResult xref_section)
+ {
+ xref_subsections.add(xref_section);
+ }
+}
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/XRefSubSectionParseResult.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/XRefSubSectionParseResult.java
new file mode 100644
index 0000000..ec19004
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/exactparser/parsing/results/XRefSubSectionParseResult.java
@@ -0,0 +1,59 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: XRefSubSectionParseResult.java,v 1.1 2006/08/25 17:00:59 wprinz Exp $
+ */
+package at.knowcenter.wag.exactparser.parsing.results;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Contains an xref sub-section.
+ *
+ * <p>
+ * An xref sub-section is an ordered list of xref lines. The object numbers of the
+ * corresponding objects are numbered incrementally.
+ * </p>
+ * <p>
+ * xref sections are important in Incremental Updates because they allow to
+ * specify explicitely which objects (object numbers) are contained in the xref.
+ * </p>
+ *
+ * @author wprinz
+ */
+public class XRefSubSectionParseResult extends ParseResult {
+
+ public int start_obj_number;
+
+ public int num_objects;
+
+ public List xref_lines = new ArrayList();
+
+ public void appendXRefLine(XRefLineParseResult xref_line) {
+ assert xref_lines.size() < num_objects;
+
+ xref_lines.add(xref_line);
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/demo/ExtractNonTextualObjectsDemo.java b/pdf-as-lib/src/main/java/demo/ExtractNonTextualObjectsDemo.java
new file mode 100644
index 0000000..ee35f26
--- /dev/null
+++ b/pdf-as-lib/src/main/java/demo/ExtractNonTextualObjectsDemo.java
@@ -0,0 +1,83 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package demo;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
+
+import at.gv.egiz.pdfas.api.analyze.NonTextObjectInfo;
+import at.gv.egiz.pdfas.api.io.DataSource;
+import at.gv.egiz.pdfas.impl.api.commons.PdfDataSourceAdapter;
+import at.gv.egiz.pdfas.io.FileBasedDataSource;
+import at.knowcenter.wag.egov.egiz.PdfAS;
+
+public class ExtractNonTextualObjectsDemo {
+
+ /**
+ * Disable instantiation.
+ */
+ private ExtractNonTextualObjectsDemo() {
+ }
+
+ /**
+ * Starts a demo that extracts non-textual elements from a document.
+ *
+ * @param args
+ * The parameter(s).
+ */
+ public static void main(String[] args) {
+
+ if (args == null || args.length == 0) {
+ System.err.println("Please provide path of file to be analyzed.");
+ System.exit(1);
+ }
+
+ File testFile = new File(args[0]);
+
+ try {
+
+ // set source
+ DataSource dataSource = new FileBasedDataSource(testFile, "application/pdf");
+
+ List nonTextualObjects = PdfAS.extractNonTextualObjects(new PdfDataSourceAdapter(dataSource));
+ if (nonTextualObjects != null && !nonTextualObjects.isEmpty()) {
+ System.out.println(nonTextualObjects.size() + " non-textual object(s) found.");
+ Iterator noit = nonTextualObjects.iterator();
+ while (noit.hasNext()) {
+ NonTextObjectInfo info = (NonTextObjectInfo) noit.next();
+ System.out.println(" -> " + info.toString());
+ }
+ } else {
+ System.out.println("No non-textual objects found.");
+ }
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/demo/SignatureCreationDemo.java b/pdf-as-lib/src/main/java/demo/SignatureCreationDemo.java
new file mode 100644
index 0000000..06e454e
--- /dev/null
+++ b/pdf-as-lib/src/main/java/demo/SignatureCreationDemo.java
@@ -0,0 +1,130 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package demo;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Iterator;
+
+import at.gv.egiz.pdfas.PdfAsFactory;
+import at.gv.egiz.pdfas.api.PdfAs;
+import at.gv.egiz.pdfas.api.analyze.NonTextObjectInfo;
+import at.gv.egiz.pdfas.api.commons.Constants;
+import at.gv.egiz.pdfas.api.exceptions.PdfAsException;
+import at.gv.egiz.pdfas.api.io.DataSource;
+import at.gv.egiz.pdfas.api.sign.SignParameters;
+import at.gv.egiz.pdfas.api.sign.SignResult;
+import at.gv.egiz.pdfas.api.sign.pos.SignaturePositioning;
+import at.gv.egiz.pdfas.io.FileBasedDataSink;
+import at.gv.egiz.pdfas.io.FileBasedDataSource;
+
+public class SignatureCreationDemo {
+
+ /**
+ * Disable instantiation.
+ */
+ private SignatureCreationDemo() {
+ }
+
+ /**
+ * Starts a demo that signs a document.
+ *
+ * @param args
+ * The parameter(s).
+ */
+ public static void main(String[] args) {
+
+ if (args == null || args.length == 0) {
+ System.err.println("Please provide path of file to be signed.");
+ System.exit(1);
+ }
+
+ File configdir = new File("./work");
+ File unsignedFile = new File(args[0]);
+ File signedFile = new File(args[0] + "_signed.pdf");
+
+ try {
+
+ // instantiate api
+ PdfAs pdfasAPI = PdfAsFactory.createPdfAs(configdir);
+
+ // set source
+ DataSource dataSource = new FileBasedDataSource(unsignedFile, "application/pdf");
+
+ // set output
+ FileBasedDataSink dataSink = new FileBasedDataSink(signedFile);
+
+ // configure signature
+ SignParameters signParameters = new SignParameters();
+ signParameters.setDocument(dataSource);
+ signParameters.setOutput(dataSink);
+ signParameters.setSignatureDevice(Constants.SIGNATURE_DEVICE_MOA); // Constants.SIGNATURE_DEVICE_BKU
+ signParameters.setSignaturePositioning(new SignaturePositioning("x:100;y:200;w:500;p:1;f:80"));
+ signParameters.setCheckForPlaceholder(true);
+ // standard signature
+ signParameters.setSignatureType(Constants.SIGNATURE_TYPE_TEXTUAL);
+ signParameters.setSignatureProfileId("SIGNATURBLOCK_DE");
+
+ // --- enable in case of BAIK SIGNATURE ---
+ /*
+ signParameters.setSignatureType(Constants.SIGNATURE_TYPE_BINARY);
+ // signParameters.setSignatureProfileId("BAIK_URKUNDE_SIGNATUR");
+ signParameters.setSignatureProfileId("BAIK_ARCHIV_SIGNATUR");
+ // use BAIK TimeStamp
+ signParameters.setTimeStamperImpl(new DummyTimeStamper());
+ */
+
+ // dynamic adjustment of signature profile values
+ // warning: inconsiderate modifications might lead to signatures that can't be validated
+ // based on default configuration
+ // note: any modifications are bound to the SignParameters object instance.
+ // It is not possible to permanently change profile configuration.
+ signParameters.setProfileOverrideValue("SIG_NAME", "Max Mustermann"); // you may use expressions here like ${subject.EMAIL}
+ signParameters.setProfileOverrideValue("SIG_META", "This is a modified note.");
+
+ // sign
+ System.out.println("Signing...");
+ SignResult signResult = pdfasAPI.sign(signParameters);
+ System.out.println("Successfully signed.");
+
+ // check if non textual elements have been detected
+ if (signResult.hasNonTextualObjects()) {
+ System.out.println("\nWARNING: " + signResult.getNonTextualObjects().size() + " non textual object(s) detected.");
+ Iterator noit = signResult.getNonTextualObjects().iterator();
+ while (noit.hasNext()) {
+ NonTextObjectInfo info = (NonTextObjectInfo) noit.next();
+ System.out.println(" -> " + info.toString());
+ }
+ System.out.println();
+ }
+
+ } catch (PdfAsException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/demo/SignatureCreationWithDynamicProfilesDemo.java b/pdf-as-lib/src/main/java/demo/SignatureCreationWithDynamicProfilesDemo.java
new file mode 100644
index 0000000..a065854
--- /dev/null
+++ b/pdf-as-lib/src/main/java/demo/SignatureCreationWithDynamicProfilesDemo.java
@@ -0,0 +1,140 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package demo;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Iterator;
+
+import at.gv.egiz.pdfas.PdfAsFactory;
+import at.gv.egiz.pdfas.api.PdfAs;
+import at.gv.egiz.pdfas.api.analyze.NonTextObjectInfo;
+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.exceptions.PdfAsException;
+import at.gv.egiz.pdfas.api.io.DataSource;
+import at.gv.egiz.pdfas.api.sign.SignParameters;
+import at.gv.egiz.pdfas.api.sign.SignResult;
+import at.gv.egiz.pdfas.api.sign.pos.SignaturePositioning;
+import at.gv.egiz.pdfas.io.FileBasedDataSink;
+import at.gv.egiz.pdfas.io.FileBasedDataSource;
+
+public class SignatureCreationWithDynamicProfilesDemo {
+
+ /**
+ * Disable instantiation.
+ */
+ private SignatureCreationWithDynamicProfilesDemo() {
+ }
+
+ /**
+ * Starts a demo that signs a document.
+ *
+ * @param args
+ * The parameter(s).
+ */
+ public static void main(String[] args) {
+
+ if (args == null || args.length == 0) {
+ System.err.println("Please provide path of file to be signed.");
+ System.exit(1);
+ }
+
+ File configdir = new File("./work");
+ File unsignedFile = new File(args[0]);
+ File signedFile = new File(args[0] + "_signed.pdf");
+
+ try {
+
+ // instantiate api
+ PdfAs pdfasAPI = PdfAsFactory.createPdfAs(configdir);
+
+ // set source
+ DataSource dataSource = new FileBasedDataSource(unsignedFile, "application/pdf");
+
+ // set output
+ FileBasedDataSink dataSink = new FileBasedDataSink(signedFile);
+
+ // configure signature
+ SignParameters signParameters = new SignParameters();
+ signParameters.setDocument(dataSource);
+ signParameters.setOutput(dataSink);
+ signParameters.setSignatureDevice(Constants.SIGNATURE_DEVICE_MOA);
+ signParameters.setSignaturePositioning(new SignaturePositioning("x:auto;y:auto;w:auto;p:auto;f:80"));
+ // standard signature
+ signParameters.setSignatureType(Constants.SIGNATURE_TYPE_TEXTUAL);
+
+ // set signature profile (note: this setting is being overwritten if the optional settings (below) are used
+ signParameters.setSignatureProfileId("SIGNATURBLOCK_DE");
+
+ // OPTIONAL[start]: adjust fixed signature profile dynamically according to your needs
+
+ // create dynamic signature profile, take values from profile SIGNATURBLOCK_DE
+ DynamicSignatureProfile dsp = pdfasAPI.createDynamicSignatureProfile(
+ "SIGNATURBLOCK_DE",
+ DynamicSignatureLifetimeEnum.AUTO // auto lifetime for one sign process
+ );
+
+ // simple access for everyone
+ // can also be done by using signParameters.setProfileOverrideValue("SIG_META", "New note value.");
+ dsp.setFieldValue("SIG_META", "New note value.");
+
+ // full control - USE THIS ONLY IF YOU REALLY KNOW WHAT YOU ARE DOING
+ // inconsiderate use may lead to non verifiable signatures
+ dsp.setPropertyRaw("table.main.Style.halign", "right");
+
+ // mandatory: register the profile
+ dsp.apply();
+
+ // set dynamic sign profile
+ signParameters.setSignatureProfileId(dsp.getName());
+
+ // OPTIONAL[end]
+
+ // sign
+ System.out.println("Signing...");
+ SignResult signResult = pdfasAPI.sign(signParameters);
+ System.out.println("Successfully signed.");
+
+ // check if non textual elements have been detected
+ if (signResult.hasNonTextualObjects()) {
+ System.out.println("\nWARNING: " + signResult.getNonTextualObjects().size() + " non textual object(s) detected.");
+ Iterator noit = signResult.getNonTextualObjects().iterator();
+ while (noit.hasNext()) {
+ NonTextObjectInfo info = (NonTextObjectInfo) noit.next();
+ System.out.println(" -> " + info.toString());
+ }
+ System.out.println();
+ }
+
+ } catch (PdfAsException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ }
+
+}
diff --git a/pdf-as-lib/src/main/java/demo/SignatureVerificationDemo.java b/pdf-as-lib/src/main/java/demo/SignatureVerificationDemo.java
new file mode 100644
index 0000000..878ff08
--- /dev/null
+++ b/pdf-as-lib/src/main/java/demo/SignatureVerificationDemo.java
@@ -0,0 +1,265 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package demo;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Iterator;
+import java.util.List;
+
+import at.gv.egiz.pdfas.PdfAsFactory;
+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.analyze.NonTextObjectInfo;
+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.io.DataSource;
+import at.gv.egiz.pdfas.api.verify.VerifyAfterAnalysisParameters;
+import at.gv.egiz.pdfas.api.verify.VerifyAfterReconstructXMLDsigParameters;
+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.ReconstructXMLDsigResult;
+import at.gv.egiz.pdfas.api.xmldsig.XMLDsigData;
+import at.gv.egiz.pdfas.commandline.Main;
+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.FileBasedDataSource;
+
+public class SignatureVerificationDemo {
+
+ /**
+ * Starts a demo that verifies a document.
+ *
+ * @param args
+ * The parameter(s).
+ */
+ public static void main(String[] args) {
+
+ if (args == null || args.length == 0) {
+ System.err.println("Please provide path of file to be verified.");
+ System.exit(1);
+ }
+
+ File configdir = new File("./work");
+ File signedFile = new File(args[0]);
+
+ AnalyzeResult analyzeResult = null;
+
+ try {
+
+ // instantiate api
+ PdfAs pdfasAPI = PdfAsFactory.createPdfAs(configdir);
+
+ // set source
+ DataSource dataSource = new FileBasedDataSource(signedFile, "application/pdf");
+
+ // evaluate settings
+ VerificationFilterParameters parameters = SettingsHelper.readVerificationFilterParametersFromSettings();
+ String verifyMode = Constants.VERIFY_MODE_FULL_CONSERVATIVE;
+
+ 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;
+ }
+
+ // configure analyze parameters
+ AnalyzeParameters analyzeParameters = new AnalyzeParameters();
+ analyzeParameters.setDocument(dataSource);
+ analyzeParameters.setVerifyMode(verifyMode);
+ analyzeParameters.setReturnNonTextualObjects(true);
+
+ // analyze
+ System.out.println("Analyzing...");
+ analyzeResult = pdfasAPI.analyze(analyzeParameters);
+ System.out.println("Successfully analyzed.");
+
+ // information on non-textual objects can be used after analysis step and/or after verification
+ List signatures = analyzeResult.getSignatures();
+ if (signatures != null && !signatures.isEmpty()) {
+ int counter = 0;
+ Iterator sigIterator = signatures.iterator();
+ while (sigIterator.hasNext()) {
+ counter++;
+ SignatureInformation sigInfo = (SignatureInformation) sigIterator.next();
+ System.out.println("\n------------------------ SIGNATURE #" + counter + " ------------------------");
+ if (sigInfo.hasNonTextualObjects()) {
+ System.out.println("\nWARNING: " + sigInfo.getNonTextualObjects().size() + " non textual object(s) detected for this signature.");
+ Iterator noit = sigInfo.getNonTextualObjects().iterator();
+ while (noit.hasNext()) {
+ NonTextObjectInfo info = (NonTextObjectInfo) noit.next();
+ System.out.println(" -> " + info.toString());
+ }
+ System.out.println();
+
+ } else {
+ System.out.println("\nNo non-textual objects detected for this signature.");
+ }
+ }
+ } else {
+ if (analyzeResult != null && analyzeResult.hasBeenCorrected()) {
+ System.err.println("The document could not been processed, maybe due to modification by third party tools. An attempt to correct the document was successful but no verifiable signatures could be found. This/these signature(s) - if any - might got lost.");
+ } else {
+ System.err.println("No signatures found.");
+ }
+ System.exit(1);
+ }
+
+ // retrieve reconstructed signature
+ ReconstructXMLDsigAfterAnalysisParameters recstrParams = new ReconstructXMLDsigAfterAnalysisParameters();
+ recstrParams.setAnalyzeResult(analyzeResult);
+ recstrParams.setSignatureDevice(Constants.SIGNATURE_DEVICE_MOA);
+ ReconstructXMLDsigResult recstrResult = pdfasAPI.reconstructXMLDSIG(recstrParams);
+
+ // it is now possible to retrieve the reconstructed XMLDSig and the underlying signed
+ // data without invoking signature verification. Just enable the following block
+ /*
+ List extSigInfoList = recstrResult.getExtendedSignatures();
+ if (extSigInfoList != null && !extSigInfoList.isEmpty()) {
+ Iterator it = extSigInfoList.iterator();
+ while (it.hasNext()) {
+ ExtendedSignatureInformation extSigInfo = (ExtendedSignatureInformation) it.next();
+ SignatureInformation sigInfo = extSigInfo.getSignatureInformation();
+ XMLDsigData xmlDSigData = extSigInfo.getXmlDsigData();
+ // output XMLDSIG somewhere: xmlDSigData.getXmlDsig()
+ if (xmlDSigData.isDetached()) {
+ DataSource signedDataSource = sigInfo.getSignedData();
+ // output signed data somewhere: signedDataSource.getAsByteArray()
+ }
+ }
+ }
+ */
+
+ // setup verification
+
+ // verification without intermediate step of reconstruction
+ /*
+ VerifyAfterAnalysisParameters vaap = new VerifyAfterAnalysisParameters();
+ vaap.setAnalyzeResult(analyzeResult);
+ vaap.setReturnHashInputData(true);
+ vaap.setSignatureDevice(Constants.SIGNATURE_DEVICE_MOA);
+ vaap.setVerificationTime(null);
+ // try to validate all signatures (do not throw exceptions while validating single signatures)
+ // use result.isVerificationDone() in order to find out if a signatures was successfully verified
+ vaap.setSuppressVerifyExceptions(true);
+ */
+
+ // verification with intermediate step of reconstruction
+ VerifyAfterReconstructXMLDsigParameters varp = new VerifyAfterReconstructXMLDsigParameters();
+ varp.setReconstructXMLDsigResult(recstrResult);
+ varp.setReturnHashInputData(true);
+ // not needed since already set in recstrParams (the reconstruction step)
+ // varp.setSignatureDevice(Constants.SIGNATURE_DEVICE_MOA);
+ varp.setVerificationTime(null);
+ // try to validate all signatures (do not throw exceptions while validating single signatures)
+ // use result.isVerificationDone() in order to find out if a signatures was successfully verified
+ varp.setSuppressVerifyExceptions(true);
+
+ // invoke verification
+ System.out.println("Verifying...");
+
+ // without intermediate step of reconstruction
+ /*
+ VerifyResults verifyResults = pdfasAPI.verify(vaap);
+ */
+
+ // with intermediate step of reconstruction
+ VerifyResults verifyResults = pdfasAPI.verify(varp);
+
+ // retrieve results
+ List verifyResultList = verifyResults.getResults();
+ System.out.println("Verification complete.\n");
+
+ // iterate over results
+ PrintWriter out = new PrintWriter(System.out);
+ Iterator it = verifyResultList.iterator();
+ int counter = 0;
+ while (it.hasNext()) {
+ counter++;
+ VerifyResult result = (VerifyResult) it.next();
+ out.println("\n------------------------ SIGNATURE #" + counter + " ------------------------\n");
+
+ // check if signature verification of the current signature was successfully completed (independent from result)
+ if (!result.isVerificationDone()) {
+ PdfAsException ex = result.getVerificationException();
+ out.println(ErrorCodeHelper.formErrorMessage(ex));
+ continue;
+ }
+
+ Main.formatVerifyResult(result, out);
+ XMLDsigData xmlDSigData = result.getReconstructedXMLDsig();
+ if (xmlDSigData != null) {
+ out.println("\n --- XMLDSIG start ---");
+ out.println(" " + xmlDSigData.getXmlDsig());
+ out.println(" --- XMLDSIG end ---");
+ // fetch data
+ // either use result.getHashInputData() (provided varp.setReturnHashInputData(...) has been set true
+ // or use
+ byte[] data = result.getSignedData().getAsByteArray();
+ out.println("\n Signed Data: " + data.length + " bytes (" + result.getSignatureType() + ")");
+ }
+
+ // check if there are timestamps
+ if (result.getTimeStampValue() != null) {
+ out.println("\n TimeStamp value available for this signature");
+ }
+
+ // check if non textual elements have been detected for this signature
+ if (result.hasNonTextualObjects()) {
+ out.println("\n WARNING: " + result.getNonTextualObjects().size() + " non textual object(s) detected for this signature");
+ Iterator noit = result.getNonTextualObjects().iterator();
+ while (noit.hasNext()) {
+ NonTextObjectInfo info = (NonTextObjectInfo) noit.next();
+ out.println(" -> " + info.toString());
+ }
+ out.println();
+
+ } else {
+ out.println("\n No non-textual objects detected for this signature.");
+ }
+ }
+ out.flush();
+
+ } catch (PdfAsException e) {
+ if (ErrorCode.DOCUMENT_NOT_SIGNED == e.getErrorCode() && analyzeResult != null && analyzeResult.hasBeenCorrected()) {
+ System.err.println("\nThe document could not been processed, maybe due to modification by third party tools. An attempt to correct the document was successful but no verifiable signatures could be found. This/these signature(s) - if any - might got lost.");
+ } else {
+ e.printStackTrace();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ }
+
+}
diff --git a/pdf-as-lib/src/main/resources/DefaultConfiguration.zip b/pdf-as-lib/src/main/resources/DefaultConfiguration.zip
new file mode 100644
index 0000000..688babd
--- /dev/null
+++ b/pdf-as-lib/src/main/resources/DefaultConfiguration.zip
Binary files differ
diff --git a/pdf-as-lib/src/main/resources/at/gv/egiz/pdfas/algorithmSuite/supportedAlgorithms.txt b/pdf-as-lib/src/main/resources/at/gv/egiz/pdfas/algorithmSuite/supportedAlgorithms.txt
new file mode 100644
index 0000000..9fc8807
--- /dev/null
+++ b/pdf-as-lib/src/main/resources/at/gv/egiz/pdfas/algorithmSuite/supportedAlgorithms.txt
@@ -0,0 +1,32 @@
+# pdf-as supported signature methods and digest algorithms
+
+# signature methods
+http://www.w3.org/2000/09/xmldsig#dsa-sha1
+http://www.w3.org/2000/09/xmldsig#hmac-sha1
+http://www.w3.org/2000/09/xmldsig#rsa-sha1
+http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1
+http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha224
+http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256
+http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384
+http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512
+http://www.w3.org/2001/04/xmldsig-more#hmac-md5
+http://www.w3.org/2001/04/xmldsig-more#hmac-ripemd160
+http://www.w3.org/2001/04/xmldsig-more#hmac-sha224
+http://www.w3.org/2001/04/xmldsig-more#hmac-sha256
+http://www.w3.org/2001/04/xmldsig-more#hmac-sha384
+http://www.w3.org/2001/04/xmldsig-more#hmac-sha512
+http://www.w3.org/2001/04/xmldsig-more#rsa-md5
+http://www.w3.org/2001/04/xmldsig-more#rsa-ripemd160
+http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
+http://www.w3.org/2001/04/xmldsig-more#rsa-sha384
+http://www.w3.org/2001/04/xmldsig-more#rsa-sha512
+http://www.w3.org/2007/05/xmldsig-more#ecdsa-ripemd160
+
+# digest algorithms
+http://www.w3.org/2000/09/xmldsig#sha1
+http://www.w3.org/2001/04/xmldsig-more#md5
+http://www.w3.org/2001/04/xmldsig-more#sha224
+http://www.w3.org/2001/04/xmldsig-more#sha384
+http://www.w3.org/2001/04/xmlenc#ripemd160
+http://www.w3.org/2001/04/xmlenc#sha256
+http://www.w3.org/2001/04/xmlenc#sha512 \ No newline at end of file
diff --git a/pdf-as-lib/src/main/resources/at/gv/egiz/pdfas/itext/DejaVuSansCondensed.ttf b/pdf-as-lib/src/main/resources/at/gv/egiz/pdfas/itext/DejaVuSansCondensed.ttf
new file mode 100644
index 0000000..988aa1b
--- /dev/null
+++ b/pdf-as-lib/src/main/resources/at/gv/egiz/pdfas/itext/DejaVuSansCondensed.ttf
Binary files differ
diff --git a/pdf-as-lib/src/main/resources/at/gv/egiz/pdfas/itext/srgb.profile b/pdf-as-lib/src/main/resources/at/gv/egiz/pdfas/itext/srgb.profile
new file mode 100644
index 0000000..7f9d18d
--- /dev/null
+++ b/pdf-as-lib/src/main/resources/at/gv/egiz/pdfas/itext/srgb.profile
Binary files differ
diff --git a/pdf-as-lib/src/main/resources/at/gv/egiz/pdfas/placeholder/empty.jpg b/pdf-as-lib/src/main/resources/at/gv/egiz/pdfas/placeholder/empty.jpg
new file mode 100644
index 0000000..7913177
--- /dev/null
+++ b/pdf-as-lib/src/main/resources/at/gv/egiz/pdfas/placeholder/empty.jpg
Binary files differ
diff --git a/pdf-as-lib/src/main/resources/at/gv/egiz/pdfas/placeholder/pdfbox-reader.properties b/pdf-as-lib/src/main/resources/at/gv/egiz/pdfas/placeholder/pdfbox-reader.properties
new file mode 100644
index 0000000..a3decc9
--- /dev/null
+++ b/pdf-as-lib/src/main/resources/at/gv/egiz/pdfas/placeholder/pdfbox-reader.properties
@@ -0,0 +1,23 @@
+BT = org.apache.pdfbox.util.operator.BeginText
+cm = org.apache.pdfbox.util.operator.Concatenate
+Do = org.apache.pdfbox.util.operator.Invoke
+ET = org.apache.pdfbox.util.operator.EndText
+gs = org.apache.pdfbox.util.operator.SetGraphicsStateParameters
+q = org.apache.pdfbox.util.operator.GSave
+Q = org.apache.pdfbox.util.operator.GRestore
+T* = org.apache.pdfbox.util.operator.NextLine
+Tc = org.apache.pdfbox.util.operator.SetCharSpacing
+Td = org.apache.pdfbox.util.operator.MoveText
+TD = org.apache.pdfbox.util.operator.MoveTextSetLeading
+Tf = org.apache.pdfbox.util.operator.SetTextFont
+Tj = org.apache.pdfbox.util.operator.ShowText
+TJ = org.apache.pdfbox.util.operator.ShowTextGlyph
+TL = org.apache.pdfbox.util.operator.SetTextLeading
+Tm = org.apache.pdfbox.util.operator.SetMatrix
+Tr = org.apache.pdfbox.util.operator.SetTextRenderingMode
+Ts = org.apache.pdfbox.util.operator.SetTextRise
+Tw = org.apache.pdfbox.util.operator.SetWordSpacing
+Tz = org.apache.pdfbox.util.operator.SetHorizontalTextScaling
+w = org.apache.pdfbox.util.operator.SetLineWidth
+\' = org.apache.pdfbox.util.operator.MoveAndShow
+\" = org.apache.pdfbox.util.operator.SetMoveAndShow \ No newline at end of file
diff --git a/pdf-as-lib/src/main/resources/config/help_text.properties b/pdf-as-lib/src/main/resources/config/help_text.properties
new file mode 100644
index 0000000..e3cc17e
--- /dev/null
+++ b/pdf-as-lib/src/main/resources/config/help_text.properties
@@ -0,0 +1,102 @@
+#ErrorCodeException
+error.code.0=Externer Fehler
+error.code.1=Das Dokument kann nicht signiert werden.
+error.code.2=Die Signatur für das Dokument kann nicht überprüft werden.
+error.code.3=Es wurde kein Dokument zur Signierung angegeben oder das Dokument konnte nicht gespeichert werden.
+error.code.4=Es wurde kein Dokument zur Überprüfung angegeben oder das Dokument konnte nicht gespeichert werden.
+error.code.5=Zum Signieren eines Dokmentes müssen Sie authentifiziert sein.
+error.code.6=Unbekannter/interner Fehler
+error.code.7=Das Dokument konnte nicht verarbeitet werden, da unzureichend Speicher zu Verfügung steht.
+
+error.code.10=Das System kann nicht initialisiert werden. Bitte wenden Sie sich an einen Systemadministrator.
+
+#SettingNotFoundException
+error.code.100=Der Konfigurationsschlüssel konnte nicht gefunden werden.
+error.code.101=Die Konfigurationsdatei konnte nicht geladen werden.
+error.code.102=Das Signaturprofil enthält keinen Bericht für die Kennzeichnung.
+error.code.103=Für den PDA/A Modus muss eine einbettbare TrueType-Schrift konfiguriert sein.
+error.code.104=Die Konfiguration der SignaturLayout-Implementierung fehlt oder ist ungültig.
+error.code.105=Es ist nicht möglich, den Typ der Bürgerkartenumgebung zu ermitteln. Die Antwort der Bürgerkartenumgebung war unvollständig.
+
+#PDFDocumentException
+error.code.201=Das PDF Dokument kann nicht gelesen werden, oder die Datei hat ein falsches Format.
+error.code.202=Der Text konnte nicht extrahiert werden.
+error.code.203=Die PDF Library konnte nicht geladen werden.
+error.code.204=Das Dokument ist bereits signiert.
+error.code.205=Das PDF Dokument kann nicht erstellt werden. Der Zugriff auf das Dokument ist blockiert.
+error.code.206=Das Dokument ist nicht signiert.
+error.code.210=Das Dokument kann nicht geschlossen werden.
+error.code.220=Die Bildmarke für die Signatur kann nicht geladen werden.
+error.code.221=Die Referenz für die Bildmarke der Signatur ist ungültig.
+error.code.222=Der Zugriff auf die Bildmarke der Signatur ist nicht möglich.
+error.code.223=Es ist keine Signaturtabelle definiert.
+error.code.224=Die angegebene Signatur Position ist ungültig.
+error.code.225=Die angegebene Seite in der absoluten Position darf nicht kleiner als 1 sein.
+error.code.226=Der angegebene Wert für die Breite in der absoluten Position darf nicht kleiner gleich 0 sein.
+error.code.227=Der angegebene Wert für die Seitennummer im Positionsparameter ist zu groß.
+error.code.228=Der angegebene Wert für die x-Position in der absoluten Position darf nicht kleiner gleich 0 sein.
+error.code.229=Der angegebene Wert für die y-Position in der absoluten Position darf nicht kleiner gleich 0 sein.
+error.code.230=Die Schriftart konnte nicht geladen werden.
+error.code.231=Das Dokument kann nicht verarbeitet werden, da es geschützt ist.
+error.code.232=Die Signatur konnte nicht überprüft werden, da das Dokument unvollständige Signaturinformationen enthält.
+error.code.233=Es konnte kein passender Platzhalter gefunden werden (STRICT mode).
+
+error.code.250=Das angegebene Dokument ist leer.
+error.code.251=Das angegebene Dokument enthält keinen extrahierbaren Text. Falls sich der Inhalt ausschließlich aus Bildern zusammensetzt, wird die Verwendung einer binären Signatur empfohlen.
+
+#SignatureException
+error.code.300=Die Signatur kann nicht erstellt werden.
+error.code.301=Die Signatur kann nicht erstellt werden. Das zu signierende Dokument enthält keinen Text.
+error.code.302=Die Signatur kann nicht erstellt werden. Der Signaturtyp ist nicht definiert.
+error.code.303=Die Signatur kann nicht erstellt werden. Die Seriennummer ist ungültig.
+error.code.304=Die Signatur kann nicht erstellt werden. Das Signatur Zertifikat kann nicht gelesen werden.
+error.code.305=Die Signatur kann nicht erstellt werden. Das gewählte Signaturprofil ist nicht für die Textsignatur geeignet, da es nicht alle notwendigen Signaturfelder sichtbar definiert. Bitte wählen Sie ein anderes Signaturprofil oder führen Sie eine Binärsignatur durch.
+
+error.code.310=Die Signatur konnte nicht verifiziert werden.
+error.code.311=Der zu prüfende Text ist nicht definiert.
+error.code.312=Die zu prüfende Signatur ist nicht definiert.
+error.code.313=Das Zertifikat (Seriennummer oder Aussteller) ist unbekannt oder kann nicht zugeordnet werden.
+error.code.314=Beim Auffinden der Signaturen ist ein Fehler aufgetreten. Es wurden mehrere passende Signaturprofile gefunden, die aber nicht semantisch äquivalent sind. Daher kann die Applikation nicht entscheiden welches Signaturprofil zur Prüfung herangezogen werden muss.
+error.code.315=Beim Auffinden der Signaturen ist ein Fehler aufgetreten. Obwohl mehrere passende Signaturprofile gefunden wurden kann die Applikation auf Grund deren Beschaffenheit nicht eindeutig entscheiden welches Signaturprofil zur Prüfung herangezogen werden muss.
+
+# added by tzefferer
+error.code.316=Das Dokument wurde nach erfolgter Signierung verändert.
+error.code.317=Das Dokument enthält nicht-binäre Signaturen.
+
+error.code.318=Die binäre Signatur kann nicht geprüft werden. Die Signatur enthält nicht unterstützte /replaces-Namen.
+error.code.319=Die Signatur konnte nicht verifiziert werden, da diese auf einer nicht unterstützten Signaturmethode bzw. einem unbekannten Signaturparameter basiert. Bitte aktualisieren Sie Ihre PDF-AS Software.
+
+error.code.320=Es kann keine Verbindung zur Bürgerkartenumgebung hergestellt werden.
+error.code.330=Es kann keine Verbindung zu MOA hergestellt werden oder MOA hat den Request zurückgewiesen.
+error.code.340=Die Antwort des Signaturgeräts enthielt weder eine Signatur noch ein Verifikationsergebnis.
+
+# TODO remove this when MOA detached is ready
+error.code.370=Eine detached Signature kann zur Zeit mit MOA nicht überprüft werden.
+
+# Für die Online-BKU: Signatur-Prüfung wird nicht unterstützt werden.
+error.code.371=Dieses Signaturgerät unterstützt keine Signatur-Prüfung.
+
+# Workaround for ITS(Mac/Linux) bug concerning the signing time.
+error.code.372=Der Signaturzeitpunkt ist ungültig. Stellen Sie bitte sicher, dass die Systemzeit sowie die Zeitzoneneinstellung Ihres Rechners korrekt sind sowie dass Sie die aktuellste Version Ihrer Bürgerkartenumgebung verwenden.
+
+# Unsupported BKU
+error.code.373=Dieses Signaturgerät wird nicht unterstützt.
+
+#NormalizeException
+error.code.400=Das Normalisierungsmodul kann nicht initialisiert werden.
+
+#LDAPException
+error.code.500=Das Zertifikat konnte nicht auf dem LDAP Server gefunden werden.
+
+#Session exception
+error.code.600=Die Sitzung ist entweder ungültig oder wurde bereits beendet.
+
+#PlaceholderException
+error.code.700=Der Platzhalter für einen Wert wurde zu kurz gewählt. Es konnte nicht der gesamte Wert in die Signatur eingefügt werden. Bitte vergrößern Sie die Länge des entsprechenden Platzhalters im Signaturprofil.
+#CaptionNotFoundException
+error.code.701=Die Überschrift (Caption/Label) konnte nicht eindeutig wiedergefunden werden. Dies geschieht gewöhnlich wenn bei der (häufig absoluten) Positionierung zu wenig Platz für die Überschrift (Caption/Label) vorhanden ist und diese ungünstig umgebrochen werden muss. Bitte stellen Sie dieser Überschrift mehr Platz im Signaturblock zur Verfügung oder entfernen Sie aus dieser alle Leerzeichen.
+
+#CorrectorException
+error.code.800=Fehler beim Parsen der binären Signatur.
+error.code.801=Das Dokument konnte nicht korrigiert werden.
+error.code.802=Die externe Korrektur konnte nicht innerhalb des festgesetzten Timeouts fertiggestellt werden.
diff --git a/pdf-as-lib/src/main/resources/config/pdf-as.properties b/pdf-as-lib/src/main/resources/config/pdf-as.properties
new file mode 100644
index 0000000..cad47f4
--- /dev/null
+++ b/pdf-as-lib/src/main/resources/config/pdf-as.properties
@@ -0,0 +1,294 @@
+###############################################################################
+# PDF-AS system properties
+###############################################################################
+
+normalizer.version=V01
+
+# default cert algorithms
+cert.alg.rsa=http://www.w3.org/2000/09/xmldsig#rsa-sha1
+cert.alg.ecdsa=http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1
+
+# BKU Algorithm - Kennzeichnung
+default.bku.algorithm.id=etsi-bka-1.0
+
+# MOA Algorithm - Kennzeichnung
+default.moa.algorithm.id=etsi-bka-moa-1.0
+
+# MOCCA Algorithm - Kennzeichnung
+default.moc.algorithm.id=etsi-moc-1.0
+
+# SIGNATURE LAYOUTS
+# signature layout for mocca without any signature layout declaration
+signaturelayout.pattern.moc.none=^((citizen-card-environment/1\\.2 MOCCA(?!.*SignatureLayout/).*)|(Jetty\\(6\\.1\\.10\\)))$
+signaturelayout.implementation.moc.none=at.knowcenter.wag.egov.egiz.sig.signaturelayout.mocca.OldMOCCASignatureLayoutHandler
+
+# signature layout 1.0 for mocca
+signaturelayout.pattern.moc.10=^citizen-card-environment/1\\.2 MOCCA/.*SignatureLayout/1\\.0.*$
+signaturelayout.implementation.moc.10=at.knowcenter.wag.egov.egiz.sig.signaturelayout.mocca.MOCCASignatureLayout10Handler
+
+# signature layout for supported trustDesk basic versions
+signaturelayout.pattern.tdb=^citizen-card-environment/1\\.2 trustDeskbasic((-OSX)|(-Linux))?/((2\\.7\\.\\d)|(2\\.8\\.\\d)|(3\\.0\\.\\d))$
+signaturelayout.implementation.tdb=at.knowcenter.wag.egov.egiz.sig.signaturelayout.td.TrustDeskSignatureLayoutHandler
+
+# signature layout for supported hotSign
+# currently disabled since there are still problems
+#signaturelayout.pattern.hotsign=^citizen-card-environment/1\\.2 hotSign/2\\.0\\.0$
+#signaturelayout.implementation.hotsign=at.knowcenter.wag.egov.egiz.sig.signaturelayout.mocca.MOCCASignatureLayout10Handler
+
+# signature layouts for supported A-Trust CCS
+
+#for web also a-trust CCS 1.3.0 is ok
+#signaturelayout.pattern.atrust130=^citizen-card-environment/1\\.2 asignSecurityLayer/1\\.3\\.0$
+#signaturelayout.implementation.atrust130=at.knowcenter.wag.egov.egiz.sig.signaturelayout.atrust.ATrustSignatureLayoutHandler
+
+signaturelayout.pattern.atrust133<=^citizen-card-environment/1\\.2 asignSecurityLayer?/((1\\.3\\.3)|(1\\.([4-9]|[1-9][0-9]{1,3})\\.{0,1}(?=[0-9])(?<=\\.)[0-9]{0,3}\\.{0,1}(?=[0-9])(?<=\\.)[0-9]{0,3})|(([2-9]|[1-9][0-9]{1,4})\\.{0,1}(?=[0-9])(?<=\\.)[0-9]{0,3}\\.{0,1}(?=[0-9])(?<=\\.)[0-9]{0,3}\\.{0,1}(?=[0-9])(?<=\\.)[0-9]{0,3}))
+signaturelayout.implementation.atrust133<=at.knowcenter.wag.egov.egiz.sig.signaturelayout.atrust.ATrustSignatureLayoutHandler
+
+# A-Trust Mobile BKU 1.1.0
+signaturelayout.pattern.atrustmobile=^citizen-card-environment/1\\.2 asignMobileBku/1\\.1\\.0$
+signaturelayout.implementation.atrustmobile=at.knowcenter.wag.egov.egiz.sig.signaturelayout.atrust.ATrustSignatureLayoutHandler
+
+# A-Trust Mobile BKU Test
+signaturelayout.pattern.atrustmobiletest=^citizen-card-environment/1\\.2 atrustHandyBku/1\\.1\\.0$
+signaturelayout.implementation.atrustmobiletest=at.knowcenter.wag.egov.egiz.sig.signaturelayout.atrust.ATrustSignatureLayoutHandler
+
+# A-Trust Mobile BKU 1.1.0 (Bridge PDF-OVER)
+signaturelayout.pattern.atrustmobilebridge=^Microsoft-IIS/6\\.0$
+signaturelayout.implementation.atrustmobilebridge=at.knowcenter.wag.egov.egiz.sig.signaturelayout.atrust.ATrustSignatureLayoutHandler
+
+#############################################
+# Signaturdienste
+
+# BKU settings
+
+# default bku enveloping sign template file
+bku.sign.request.base64=/templates/default.bku.sign.enveloping.xml
+
+# default bku detached sign template file
+bku.sign.request.detached=/templates/default.bku.sign.detached.xml
+
+bku.verify.template.base64old=/templates/default.bku.verify.template.enveloping.old.xml
+
+# default bku enveloping verify template files
+bku.verify.request.base64=/templates/default.bku.verify.request.enveloping.xml
+bku.verify.template.base64=/templates/default.bku.verify.template.enveloping.xml
+
+# default bku detached verify template files
+bku.verify.request.detached=/templates/default.bku.verify.request.detached.xml
+bku.verify.template.detached=/templates/default.bku.verify.template.detached.xml
+
+# MOCCA settings
+
+# default MOCCA signature template
+moc.sign.request.detached=/templates/default.moc.sign.detached.xml
+
+# MOCCA verification
+# default MOCCA verify template
+moc.verify.template.detached=/templates/default.moc.verify.template.detached.xml
+
+# A1 settings
+
+a1.available_for_web=false
+a1.available_for_commandline=false
+
+a1.sign.url=https://signatur.a1.net/http-security-layer-request
+a1.sign.request=/templates/BKUSignRequestB64.xml
+a1.sign.KeyboxIdentifier=SecureSignatureKeypair
+
+a1.verify.url=https://signatur.a1.net/http-security-layer-request
+a1.verify.request=/templates/BKUVerifyRequest.xml
+a1.verify.template=/templates/BKUVerifyTemplateB64.xml
+a1.verify.template.SP=/templates/BKUVerifyTemplateSP.xml
+
+# MOA Settings
+
+# default moa enveloping sign template file
+moa.sign.request.base64=/templates/default.moa.sign.enveloping.xml
+# default moa detached sign template file
+moa.sign.request.detached=/templates/default.moa.sign.detached.xml
+
+# default moa enveloping verify template files
+moa.verify.request.base64=/templates/default.moa.verify.request.enveloping.xml
+moa.verify.template.base64=/templates/default.moa.verify.template.enveloping.xml
+
+# default moa detached verify template files
+moa.verify.request.detached=/templates/default.moa.verify.request.detached.xml
+moa.verify.template.detached=/templates/default.moa.verify.template.detached.xml
+
+# atrust verify template files
+atrust.verify.template.detached=/templates/etsi-bka-atrust-1.0.verify.template.detached.xml
+
+#############################################
+# Responsemeldungen der Signaturdienste
+
+signature.response.certificateCheckInfo.0=Eine formal korrekte Zertifikatskette vom Signatorzertifikat zu einem vertrauenswürdigen Wurzelzertifikat konnte konstruiert werden. Jedes Zertifikat dieser Kette ist zum in der Anfrage angegebenen Prüfzeitpunkt gültig.
+signature.response.certificateCheckInfo.1=Es konnte keine formal korrekte Zertifikatskette vom Signatorzertifikat zu einem vertrauenswürdigen Wurzelzertifikat konstruiert werden.
+signature.response.certificateCheckInfo.2=Eine formal korrekte Zertifikatskette vom Signatorzertifikat zu einem vertrauenswürdigen Wurzelzertifikat konnte konstruiert werden. Für zumindest ein Zertifikat dieser Kette fällt der Prüfzeitpunkt nicht in das Gültigkeitsintervall.
+signature.response.certificateCheckInfo.3=Eine formal korrekte Zertifikatskette vom Signatorzertifikat zu einem vertrauenswürdigen Wurzelzertifikat konnte konstruiert werden. Für alle Zertifikate dieser Kette fällt der Prüfzeitpunkt in das jeweilige Gültigkeitsintervall. Für zumindest ein Zertifikat konnte der Zertifikatstatus nicht festgestellt werden.
+signature.response.certificateCheckInfo.4=Eine formal korrekte Zertifikatskette vom Signatorzertifikat zu einem vertrauenswürdigen Wurzelzertifikat konnte konstruiert werden. Für alle Zertifikate dieser Kette fällt der Prüfzeitpunkt in das jeweilige Gültigkeitsintervall. Zumindest ein Zertifikat ist zum Prüfzeitpunkt widerrufen.
+signature.response.certificateCheckInfo.5=Eine formal korrekte Zertifikatskette vom Signatorzertifikat zu einem vertrauenswürdigen Wurzelzertifikat konnte konstruiert werden. Für alle Zertifikate dieser Kette fällt der Prüfzeitpunkt in das jeweilige Gültigkeitsintervall. Kein Zertifikat dieser Kette ist zum Prüfzeitpunkt widerrufen. Zumindest ein Zertifikat ist zum Prüfzeitpunkt gesperrt.
+signature.response.certificateCheckInfo.99=Die Prüfung der Signaturprüfdaten wurde nicht durchgeführt, da bei der Prüfung der Gültigkeit der Signatur ein Fehler aufgetreten ist.
+
+signature.response.signatureCheckInfo.0=Die Überprüfung der Hash-Werte und des Werts der Signatur konnte erfolgreich durchgeführt werden.
+signature.response.signatureCheckInfo.1=Bei der Überprüfung des Hash-Werts zumindest einer dsig:Reference der Signatur ist ein Fehler aufgetreten. Der Wert der Signatur wurde nicht überprüft.
+signature.response.signatureCheckInfo.2=Die Überprüfung der Hash-Werte konnte erfolgreich durchgeführt werden. Beim Überprüfen des Werts der Signatur ist jedoch ein Fehler aufgetreten.
+
+signature.response.signatureManifestCheckInfo.0=Für diese Signatur ist kein Signaturmanifest notwendig.
+signature.response.signatureManifestCheckInfo.1=Die Signatur enthält keine Referenz auf das notwendige Signaturmanifest.
+signature.response.signatureManifestCheckInfo.2=Die Signatur enthält zwar eine Referenz auf das Signaturmanifest, dieses entspricht vom Umfang her jedoch nicht den Anforderungen dieser Spezifikation. Die Hash-Werte der im Signaturmanifest vorhandenen dsig:Reference-Elemente wurden nicht überprüft.
+signature.response.signatureManifestCheckInfo.3=Die Signatur enthält eine Referenz auf das Signaturmanifest. Das Signaturmanifest entspricht vom Umfang her den Anforderungen dieser Spezifikation. Bei der Überprüfung des Hash-Werts zumindest einer dsig:Reference des Signaturmanifests ist jedoch ein Fehler aufgetreten.
+signature.response.signatureManifestCheckInfo.99=Die Prüfung des Signaturmanifests wurde nicht durchgeführt, da bei der Prüfung der Gültigkeit der Signatur ein Fehler aufgetreten ist.
+
+
+#############################################
+# Anzeige von OID Feldern eines Zertifikats im Prüfergebnis
+
+oid.root=1.2.40.0.10
+oid.1_2_40_0_10_1_1_1=Verwaltungseigenschaft
+oid.1_2_40_0_10_1_1_2=Dienstleistereigenschaft
+
+
+#############################################
+# start LDAP-Mappings
+# note: ldap_mapping.xxx.serial_attr may be omitted if value is "eidCertificateSerialNumber"
+
+# A-Trust
+ldap_mapping.asign_prem_sig01.issuer_name=CN=a-sign-Premium-Sig-01,OU=a-sign-Premium-Sig-01,O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH,C=AT
+ldap_mapping.asign_prem_sig01.url=ldap://ldap.a-trust.at/ou=a-sign-Premium-Sig-01,o=A-Trust,c=at
+ldap_mapping.asign_prem_sig01.serial_attr=eidCertificateSerialNumber
+
+ldap_mapping.asign_prem_sig02.issuer_name=CN=a-sign-Premium-Sig-02,OU=a-sign-Premium-Sig-02,O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH,C=AT
+ldap_mapping.asign_prem_sig02.url=ldap://ldap.a-trust.at/ou=a-sign-Premium-Sig-02,o=A-Trust,c=at
+ldap_mapping.asign_prem_sig02.serial_attr=eidCertificateSerialNumber
+
+ldap_mapping.asign_prem_test_sig01.issuer_name=CN=a-sign-Premium-Test-Sig-01,OU=a-sign-Premium-Test-Sig-01,O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH,C=AT
+ldap_mapping.asign_prem_test_sig01.url=ldap://ldap-test.a-trust.at/ou=a-sign-Premium-Test-Sig-01,o=A-Trust,c=at
+ldap_mapping.asign_prem_test_sig01.serial_attr=eidCertificateSerialNumber
+
+ldap_mapping.asign_prem_test_sig02.issuer_name=CN=a-sign-Premium-Test-Sig-02,OU=a-sign-Premium-Test-Sig-02,O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH,C=AT
+ldap_mapping.asign_prem_test_sig02.url=ldap://ldap-test.a-trust.at/ou=a-sign-Premium-Test-Sig-02,o=A-Trust,c=at
+ldap_mapping.asign_prem_test_sig02.serial_attr=eidCertificateSerialNumber
+
+ldap_mapping.asign_prem_test_sig03.issuer_name=CN=a-sign-Premium-Test-Sig-03,OU=a-sign-Premium-Test-Sig-03,O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH,C=AT
+ldap_mapping.asign_prem_test_sig03.url=ldap://ldap-test.a-trust.at/ou=a-sign-Premium-Test-Sig-03,o=A-Trust,c=at
+ldap_mapping.asign_prem_test_sig03.serial_attr=eidCertificateSerialNumber
+
+ldap_mapping.asign_prem_enc01.issuer_name=CN=a-sign-Premium-Enc-01,OU=a-sign-Premium-Enc-01,O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH,C=AT
+ldap_mapping.asign_prem_enc01.url=ldap://ldap.a-trust.at/ou=a-sign-Premium-Enc-01,o=A-Trust,c=at
+ldap_mapping.asign_prem_enc01.serial_attr=eidCertificateSerialNumber
+
+ldap_mapping.asign_prem_enc02.issuer_name=CN=a-sign-Premium-Enc-02,OU=a-sign-Premium-Enc-02,O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH,C=AT
+ldap_mapping.asign_prem_enc02.url=ldap://ldap.a-trust.at/ou=a-sign-Premium-Enc-02,o=A-Trust,c=at
+ldap_mapping.asign_prem_enc02.serial_attr=eidCertificateSerialNumber
+
+ldap_mapping.asign_token_sig02.issuer_name=CN=a-sign-Token-Sig-02,OU=a-sign-Token-Sig-02,O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH,C=AT
+ldap_mapping.asign_token_sig02.url=ldap://ldap.a-trust.at/ou=a-sign-Token-Sig-02,o=A-Trust,c=at
+ldap_mapping.asign_token_sig02.serial_attr=eidCertificateSerialNumber
+
+ldap_mapping.asign_token_enc02.issuer_name=CN=a-sign-Token-Enc-02,OU=a-sign-Token-Enc-02,O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH,C=AT
+ldap_mapping.asign_token_enc02.url=ldap://ldap.a-trust.at/ou=a-sign-Token-Enc-02,o=A-Trust,c=at
+ldap_mapping.asign_token_enc02.serial_attr=eidCertificateSerialNumber
+
+ldap_mapping.asign_token_sig01.issuer_name=CN=a-sign-Token-Sig-01,OU=a-sign-Token-Sig-01,O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH,C=AT
+ldap_mapping.asign_token_sig01.url=ldap://ldap.a-trust.at/ou=a-sign-Token-Sig-01,o=A-Trust,c=at
+ldap_mapping.asign_token_sig01.serial_attr=eidCertificateSerialNumber
+
+ldap_mapping.asign_token_enc01.issuer_name=CN=a-sign-Token-Enc-01,OU=a-sign-Token-Enc-01,O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH,C=AT
+ldap_mapping.asign_token_enc01.url=ldap://ldap.a-trust.at/ou=a-sign-Token-Enc-01,o=A-Trust,c=at
+ldap_mapping.asign_token_enc01.serial_attr=eidCertificateSerialNumber
+
+ldap_mapping.asign_corp_light01.issuer_name=CN=a-sign-corporate-light-01,OU=a-sign-corporate-light-01,O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH,C=AT
+ldap_mapping.asign_corp_light01.url=ldap://ldap.a-trust.at/ou=a-sign-corporate-light-01,o=A-Trust,c=at
+ldap_mapping.asign_corp_light01.serial_attr=eidCertificateSerialNumber
+
+ldap_mapping.asign_corp_light02.issuer_name=CN=a-sign-corporate-light-02,OU=a-sign-corporate-light-02,O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH,C=AT
+ldap_mapping.asign_corp_light02.url=ldap://ldap.a-trust.at/ou=a-sign-corporate-light-02,o=A-Trust,c=at
+ldap_mapping.asign_corp_light02.serial_attr=eidCertificateSerialNumber
+
+ldap_mapping.asign_corp_light03.issuer_name=CN=a-sign-corporate-light-03,OU=a-sign-corporate-light-03,O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH,C=AT
+ldap_mapping.asign_corp_light03.url=ldap://ldap.a-trust.at/ou=a-sign-corporate-light-03,o=A-Trust,c=at
+ldap_mapping.asign_corp_light03.serial_attr=eidCertificateSerialNumber
+
+ldap_mapping.asign_prem_mob03.issuer_name=CN=a-sign-premium-mobile-03,OU=a-sign-premium-mobile-03,O=A-TrustGes. f. Sicherheitssysteme im elektr. Datenverkehr GmbH,C=AT
+ldap_mapping.asign_prem_mob03.url=ldap://ldap.a-trust.at/ou=a-sign-premium-mobile-03,o=A-Trust,c=AT
+ldap_mapping.asign_prem_mob03.serial_attr=eidCertificateSerialNumber
+
+
+# Hauptverband
+ldap_mapping.ecard_vs_ca02.issuer_name=C=AT,O=Hauptverband österr. Sozialvers.,CN=VSig CA 2
+ldap_mapping.ecard_vs_ca02.url=ldap://ldap.ecard.sozialversicherung.at/ou=VSig CA 2,o=Hauptverband österr. Sozialvers.,c=at
+ldap_mapping.ecard_vs_ca02.serial_attr=serialNumber
+
+# A-CERT
+ldap_mapping.acert_freecert.issuer_name=EMAIL=-,CN=FREECERT,O=ARGE DATEN - Oesterreichische Gesellschaft fuer Datenschutz,L=Wien,ST=-,C=AT
+ldap_mapping.acert_freecert.url=ldap://ldap.a-cert.at/ou=A-CERT FREECERT,o=A-CERT,c=AT
+ldap_mapping.acert_freecert.serial_attr=serialNumber
+
+ldap_mapping.acert_globaltrust_neu.issuer_name=EMAIL=info@a-cert.at,CN=A-CERT GLOBALTRUST,O=ARGE DATEN - Austrian Society for Data Protection and Privacy,L=Vienna,ST=-,C=AT
+ldap_mapping.acert_globaltrust_neu.url=ldap://ldap.a-cert.at/ou=A-CERT GLOBALTRUST NEU,o=A-CERT,c=AT
+ldap_mapping.acert_globaltrust_neu.serial_attr=serialNumber
+
+ldap_mapping.acert_government.issuer_name=EMAIL=a-cert@a-cert.at,CN=A-CERT GOVERNMENT,O=ARGE DATEN - Österreichische Gesellschaft für Datenschutz,L=Wien,ST=Wien,C=AT
+ldap_mapping.acert_government.url=ldap://ldap.a-cert.at/ou=A-CERT GOVERNMENT,o=A-CERT,c=AT
+ldap_mapping.acert_government.serial_attr=serialNumber
+
+ldap_mapping.acert_advanced.issuer_name=EMAIL=info@a-cert.at,CN=A-CERT ADVANCED,OU=A-CERT Certification Service,O=ARGE DATEN - Austrian Society for Data Protection,L=Vienna,ST=Austria,C=AT
+ldap_mapping.acert_advanced.url=ldap://ldap.a-cert.at/ou=A-CERT ADVANCED,o=A-CERT,c=AT
+ldap_mapping.acert_advanced.serial_attr=serialNumber
+
+ldap_mapping.acert_globaltrust.issuer_name=EMAIL=a-cert@argedaten.at,O=Arge Daten Oesterreichische Gesellschaft fuer Datenschutz,L=Vienna,ST=Austria,C=AT
+ldap_mapping.acert_globaltrust.url=ldap://ldap.a-cert.at/ou=A-CERT GLOBALTRUST,o=A-CERT,c=AT
+ldap_mapping.acert_globaltrust.serial_attr=serialNumber
+
+ldap_mapping.acert_company.issuer_name=EMAIL=info@a-cert.at,CN=A-CERT ADVANCED,OU=A-CERT Certification Service,O=ARGE DATEN - Austrian Society for Data Protection,L=Vienna,ST=Austria,C=AT
+ldap_mapping.acert_company.url=ldap://ldap.a-cert.at/ou=A-CERT COMPANY,o=A-CERT,c=AT
+ldap_mapping.acert_company.serial_attr=serialNumber
+
+ldap_mapping.globaltrust.issuer_name=EMAIL=info@globaltrust.info,CN=GLOBALTRUST,OU=GLOBALTRUST Certification Service,O=ARGE DATEN - Austrian Society for Data Protection,ST=Austria,L=Vienna,C=AT
+ldap_mapping.globaltrust.url=ldap://ldap.a-cert.at/ou=GLOBALTRUST,o=A-CERT,c=AT
+ldap_mapping.globaltrust.serial_attr=serialNumber
+
+ldap_mapping.acert_client.issuer_name=EMAIL=a-cert@a-cert.at,CN=A-CERT CLIENT,O=ARGE DATEN - Oesterreichische Gesellschaft fuer Datenschutz,L=Wien,ST=Wien,C=AT
+ldap_mapping.acert_client.url=ldap://ldap.a-cert.at/ou=A-CERT CLIENT,o=A-CERT,c=AT
+ldap_mapping.acert_client.serial_attr=serialNumber
+
+ldap_mapping.globaltrust_demointern.issuer_name=EMAIL=a-cert@a-cert.at,CN=GLOBALTRUST DEMOINTERN,O=ARGE DATEN - Österreichische Gesellschaft für Datenschutz,L=Wien,ST=Wien,C=AT
+ldap_mapping.globaltrust_demointern.url=ldap://ldap.a-cert.at/ou=GLOBALTRUST DEMOINTERN,o=A-CERT,c=AT
+ldap_mapping.globaltrust_demointern.serial_attr=serialNumber
+
+ldap_mapping.acert_government2.issuer_name=EMAIL=a-cert@a-cert.at,CN=A-CERT GOVERNMENT,O=ARGE DATEN - Österreichische Gesellschaft für Datenschutz,L=Wien,ST=Wien,C=AT
+ldap_mapping.acert_government2.url=ldap://ldap.a-cert.at/ou=A-CERT GOVERNMENT 2,o=A-CERT,c=AT
+ldap_mapping.acert_government2.serial_attr=serialNumber
+
+ldap_mapping.acert_company2.issuer_name=EMAIL=info@globaltrust.info,CN=GLOBALTRUST,OU=GLOBALTRUST Certification Service,O=ARGE DATEN - Austrian Society for Data Protection,ST=Austria,L=Vienna,C=AT
+ldap_mapping.acert_company2.url=ldap://ldap.a-cert.at/ou=A-CERT COMPANY 2,o=A-CERT,c=AT
+ldap_mapping.acert_company2.serial_attr=serialNumber
+
+ldap_mapping.acert_government3.issuer_name=EMAIL=info@globaltrust.eu,CN=A-CERT GOVERNMENT,O=ARGE DATEN - Österreichische Gesellschaft für Datenschutz,L=Wien,ST=Wien,C=AT
+ldap_mapping.acert_government3.url=ldap://ldap.a-cert.at/ou=A-CERT GOVERNMENT 3,o=A-CERT,c=AT
+ldap_mapping.acert_government3.serial_attr=serialNumber
+
+ldap_mapping.acert_advanced2.issuer_name=EMAIL=info@globaltrust.eu,CN=A-CERT ADVANCED,O=e-commerce monitoring GmbH,L=Wien,C=AT
+ldap_mapping.acert_advanced2.url=ldap://ldap.a-cert.at/ou=A-CERT ADVANCED 2,o=A-CERT,c=AT
+ldap_mapping.acert_advanced2.serial_attr=serialNumber
+
+ldap_mapping.acert_client2.issuer_name=EMAIL=info@globaltrust.eu,CN=A-CERT CLIENT,O=e-commerce monitoring GmbH,L=Wien,C=AT
+ldap_mapping.acert_client2.url=ldap://ldap.a-cert.at/ou=A-CERT CLIENT 2,o=A-CERT,c=AT
+ldap_mapping.acert_client2.serial_attr=serialNumber
+
+ldap_mapping.acert_advanced3.issuer_name=EMAIL=info@globaltrust.eu,CN=A-CERT ADVANCED,O=ARGE DATEN - Austrian Society for Data Protection and Privacy,L=Vienna,C=AT
+ldap_mapping.acert_advanced3.url=ldap://ldap.a-cert.at/ou=A-CERT ADVANCED 3,o=A-CERT,c=AT
+ldap_mapping.acert_advanced3.serial_attr=serialNumber
+
+ldap_mapping.acert_client3.issuer_name=EMAIL=info@globaltrust.eu,CN=A-CERT CLIENT,O=ARGE DATEN - Austrian Society for Data Protection and Privacy,L=Vienna,C=AT
+ldap_mapping.acert_client3.url=ldap://ldap.a-cert.at/ou=A-CERT CLIENT 3,o=A-CERT,c=AT
+ldap_mapping.acert_client3.serial_attr=serialNumber
+
+ldap_mapping.dtrust_qual.issuer_name=CN=D-TRUST Qualified CA 3 2007:PN,O=D-Trust GmbH,C=DE
+ldap_mapping.dtrust_qual.url=ldap://directory.d-trust.net:389/cn=D-TRUST Qualified CA 3 2007:PN,o=D-Trust GmbH,c=DE
+ldap_mapping.dtrust_qual.serial_attr=uid
+
+
+# end LDAP-Mappings
+#############################################
+
diff --git a/pdf-as-lib/src/main/resources/config/templates/default.bku.sign.detached.xml b/pdf-as-lib/src/main/resources/config/templates/default.bku.sign.detached.xml
new file mode 100644
index 0000000..94c8f27
--- /dev/null
+++ b/pdf-as-lib/src/main/resources/config/templates/default.bku.sign.detached.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<sl:CreateXMLSignatureRequest xmlns:sl="http://www.buergerkarte.at/namespaces/securitylayer/1.2#">
+<sl:KeyboxIdentifier>KeyboxIdentifierReplace</sl:KeyboxIdentifier>
+<sl:DataObjectInfo Structure="detached">
+<sl:DataObject Reference="urn:Document">
+<sl:LocRefContent>LocRefContentReplace</sl:LocRefContent>
+</sl:DataObject>
+<sl:TransformsInfo>
+<sl:FinalDataMetaInfo>
+<sl:MimeType>MimeTypeReplace</sl:MimeType>
+</sl:FinalDataMetaInfo>
+</sl:TransformsInfo>
+</sl:DataObjectInfo>
+</sl:CreateXMLSignatureRequest> \ No newline at end of file
diff --git a/pdf-as-lib/src/main/resources/config/templates/default.bku.sign.enveloping.xml b/pdf-as-lib/src/main/resources/config/templates/default.bku.sign.enveloping.xml
new file mode 100644
index 0000000..4cebb0e
--- /dev/null
+++ b/pdf-as-lib/src/main/resources/config/templates/default.bku.sign.enveloping.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<sl:CreateXMLSignatureRequest xmlns:sl="http://www.buergerkarte.at/namespaces/securitylayer/1.2#">
+<sl:KeyboxIdentifier>KeyboxIdentifierReplace</sl:KeyboxIdentifier>
+<sl:DataObjectInfo Structure="enveloping">
+<sl:DataObject>
+<sl:Base64Content>Base64ContentReplace</sl:Base64Content>
+</sl:DataObject>
+<sl:TransformsInfo>
+<sl:FinalDataMetaInfo>
+<sl:MimeType>text/plain</sl:MimeType>
+</sl:FinalDataMetaInfo>
+</sl:TransformsInfo>
+</sl:DataObjectInfo>
+</sl:CreateXMLSignatureRequest> \ No newline at end of file
diff --git a/pdf-as-lib/src/main/resources/config/templates/default.bku.verify.request.detached.xml b/pdf-as-lib/src/main/resources/config/templates/default.bku.verify.request.detached.xml
new file mode 100644
index 0000000..5c0e173
--- /dev/null
+++ b/pdf-as-lib/src/main/resources/config/templates/default.bku.verify.request.detached.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<sl:VerifyXMLSignatureRequest xmlns:sl="http://www.buergerkarte.at/namespaces/securitylayer/1.2#" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
+DateTimeReplace
+<sl:SignatureInfo>
+<sl:SignatureEnvironment>
+<sl:XMLContent>XMLContentReplace</sl:XMLContent>
+</sl:SignatureEnvironment>
+<sl:SignatureLocation>/dsig:Signature</sl:SignatureLocation>
+</sl:SignatureInfo>
+<sl:Supplement>
+<sl:Content Reference="urn:Document">
+<sl:LocRefContent>LocRefContentReplace</sl:LocRefContent>
+</sl:Content>
+</sl:Supplement>
+</sl:VerifyXMLSignatureRequest> \ No newline at end of file
diff --git a/pdf-as-lib/src/main/resources/config/templates/default.bku.verify.request.enveloping.xml b/pdf-as-lib/src/main/resources/config/templates/default.bku.verify.request.enveloping.xml
new file mode 100644
index 0000000..e232e51
--- /dev/null
+++ b/pdf-as-lib/src/main/resources/config/templates/default.bku.verify.request.enveloping.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<sl:VerifyXMLSignatureRequest xmlns:sl="http://www.buergerkarte.at/namespaces/securitylayer/1.2#" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
+<sl:SignatureInfo>
+<sl:SignatureEnvironment>
+<sl:XMLContent>XMLContentReplace</sl:XMLContent>
+</sl:SignatureEnvironment>
+<sl:SignatureLocation>/dsig:Signature</sl:SignatureLocation>
+</sl:SignatureInfo>
+</sl:VerifyXMLSignatureRequest> \ No newline at end of file
diff --git a/pdf-as-lib/src/main/resources/config/templates/default.bku.verify.template.detached.xml b/pdf-as-lib/src/main/resources/config/templates/default.bku.verify.template.detached.xml
new file mode 100644
index 0000000..8948ea2
--- /dev/null
+++ b/pdf-as-lib/src/main/resources/config/templates/default.bku.verify.template.detached.xml
@@ -0,0 +1,13 @@
+<dsig:Signature xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" Id="signature-SigIdReplace">
+<dsig:SignedInfo>
+<dsig:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
+<dsig:SignatureMethod Algorithm="CertAlgReplace"/>
+<dsig:Reference Id="signed-data-reference-SigDataRefReplace" URI="urn:Document">
+<dsig:DigestMethod Algorithm="DataDigestReplace"/>
+<dsig:DigestValue>DigestValueSignedDataReplace</dsig:DigestValue>
+</dsig:Reference>
+<dsig:Reference Id="etsi-data-reference-EtsiDataRefReplace" Type="http://uri.etsi.org/01903/v1.1.1#SignedProperties" URI="#xmlns(etsi=http://uri.etsi.org/01903/v1.1.1%23)%20xpointer(id('etsi-data-object-EtsiDataObjURIReplace')/child::etsi:QualifyingProperties/child::etsi:SignedProperties)"><dsig:DigestMethod Algorithm="PropertiesDigestReplace"/><dsig:DigestValue>DigestValueSignedPropertiesReplace</dsig:DigestValue></dsig:Reference></dsig:SignedInfo>
+<dsig:SignatureValue>SignatureValueReplace</dsig:SignatureValue>
+<dsig:KeyInfo><dsig:X509Data><dsig:X509Certificate>X509CertificateReplace</dsig:X509Certificate></dsig:X509Data></dsig:KeyInfo>
+<dsig:Object Id="etsi-data-object-EtsiDataObjURIReplace"><etsi:QualifyingProperties xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:etsi="http://uri.etsi.org/01903/v1.1.1#" Target="#signature-SigIdReplace"><etsi:SignedProperties xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:etsi="http://uri.etsi.org/01903/v1.1.1#"><etsi:SignedSignatureProperties><etsi:SigningTime>SigningTimeReplace</etsi:SigningTime><etsi:SigningCertificate><etsi:Cert><etsi:CertDigest><etsi:DigestMethod Algorithm="CertDigestReplace"></etsi:DigestMethod><etsi:DigestValue>DigestValueX509CertificateReplace</etsi:DigestValue></etsi:CertDigest><etsi:IssuerSerial><dsig:X509IssuerName>X509IssuerNameReplace</dsig:X509IssuerName><dsig:X509SerialNumber>X509SerialNumberReplace</dsig:X509SerialNumber></etsi:IssuerSerial></etsi:Cert></etsi:SigningCertificate><etsi:SignaturePolicyIdentifier><etsi:SignaturePolicyImplied></etsi:SignaturePolicyImplied></etsi:SignaturePolicyIdentifier></etsi:SignedSignatureProperties><etsi:SignedDataObjectProperties><etsi:DataObjectFormat ObjectReference="#signed-data-reference-SigDataRefReplace"><etsi:MimeType>MimeTypeReplace</etsi:MimeType></etsi:DataObjectFormat></etsi:SignedDataObjectProperties></etsi:SignedProperties></etsi:QualifyingProperties></dsig:Object>
+</dsig:Signature> \ No newline at end of file
diff --git a/pdf-as-lib/src/main/resources/config/templates/default.bku.verify.template.enveloping.old.xml b/pdf-as-lib/src/main/resources/config/templates/default.bku.verify.template.enveloping.old.xml
new file mode 100644
index 0000000..cf64b3b
--- /dev/null
+++ b/pdf-as-lib/src/main/resources/config/templates/default.bku.verify.template.enveloping.old.xml
@@ -0,0 +1,6 @@
+<dsig:Signature xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" Id="signature-SigIdReplace"><dsig:SignedInfo><dsig:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/><dsig:SignatureMethod Algorithm="CertAlgReplace"/><dsig:Reference Id="signed-data-reference-SigDataRefReplace" URI="#signed-data-object-SigDataObjURIReplace"><dsig:Transforms><dsig:Transform Algorithm="http://www.w3.org/2002/06/xmldsig-filter2"><xpf:XPath xmlns:xpf="http://www.w3.org/2002/06/xmldsig-filter2" Filter="intersect">id('signed-data-object-SigDataObjURIReplace')/node()</xpf:XPath></dsig:Transform><dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#base64"/></dsig:Transforms><dsig:DigestMethod Algorithm="DataDigestReplace"/><dsig:DigestValue>DigestValueSignedDataReplace</dsig:DigestValue></dsig:Reference><dsig:Reference Id="etsi-data-reference-EtsiDataRefReplace" Type="http://uri.etsi.org/01903/v1.1.1#SignedProperties" URI="#etsi-data-object-EtsiDataObjURIReplace"><dsig:Transforms><dsig:Transform Algorithm="http://www.w3.org/2002/06/xmldsig-filter2"><xpf:XPath xmlns:xpf="http://www.w3.org/2002/06/xmldsig-filter2" Filter="intersect">id('etsi-data-object-EtsiDataObjURIReplace')/node()</xpf:XPath></dsig:Transform></dsig:Transforms><dsig:DigestMethod Algorithm="PropertiesDigestReplace"/><dsig:DigestValue>DigestValueSignedPropertiesReplace</dsig:DigestValue></dsig:Reference></dsig:SignedInfo>
+<dsig:SignatureValue>SignatureValueReplace</dsig:SignatureValue>
+<dsig:KeyInfo><dsig:X509Data><dsig:X509Certificate>X509CertificateReplace</dsig:X509Certificate></dsig:X509Data></dsig:KeyInfo>
+<dsig:Object Id="signed-data-object-SigDataObjURIReplace"><sl:Base64Content>Base64ContentReplace</sl:Base64Content></dsig:Object>
+<dsig:Object Id="etsi-data-object-EtsiDataObjURIReplace"><etsi:QualifyingProperties xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:etsi="http://uri.etsi.org/01903/v1.1.1#" Target="#signature-SigIdReplace"><etsi:SignedProperties><etsi:SignedSignatureProperties><etsi:SigningTime>SigningTimeReplace</etsi:SigningTime><etsi:SigningCertificate><etsi:Cert><etsi:CertDigest><etsi:DigestMethod Algorithm="CertDigestReplace"></etsi:DigestMethod><etsi:DigestValue>DigestValueX509CertificateReplace</etsi:DigestValue></etsi:CertDigest><etsi:IssuerSerial><dsig:X509IssuerName>X509IssuerNameReplace</dsig:X509IssuerName><dsig:X509SerialNumber>X509SerialNumberReplace</dsig:X509SerialNumber></etsi:IssuerSerial></etsi:Cert></etsi:SigningCertificate><etsi:SignaturePolicyIdentifier><etsi:SignaturePolicyImplied></etsi:SignaturePolicyImplied></etsi:SignaturePolicyIdentifier></etsi:SignedSignatureProperties><etsi:SignedDataObjectProperties><etsi:DataObjectFormat ObjectReference="#signed-data-reference-SigDataRefReplace"><etsi:MimeType>text/plain</etsi:MimeType></etsi:DataObjectFormat></etsi:SignedDataObjectProperties></etsi:SignedProperties></etsi:QualifyingProperties></dsig:Object>
+</dsig:Signature> \ No newline at end of file
diff --git a/pdf-as-lib/src/main/resources/config/templates/default.bku.verify.template.enveloping.xml b/pdf-as-lib/src/main/resources/config/templates/default.bku.verify.template.enveloping.xml
new file mode 100644
index 0000000..bd30d70
--- /dev/null
+++ b/pdf-as-lib/src/main/resources/config/templates/default.bku.verify.template.enveloping.xml
@@ -0,0 +1,6 @@
+<dsig:Signature xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" Id="signature-SigIdReplace"><dsig:SignedInfo><dsig:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/><dsig:SignatureMethod Algorithm="CertAlgReplace"/><dsig:Reference Id="signed-data-reference-SigDataRefReplace" URI="#signed-data-object-SigDataObjURIReplace"><dsig:Transforms><dsig:Transform Algorithm="http://www.w3.org/2002/06/xmldsig-filter2"><xpf:XPath xmlns:xpf="http://www.w3.org/2002/06/xmldsig-filter2" Filter="intersect">id('signed-data-object-SigDataObjURIReplace')/node()</xpf:XPath></dsig:Transform><dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#base64"/></dsig:Transforms><dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><dsig:DigestValue>DigestValueSignedDataReplace</dsig:DigestValue></dsig:Reference><dsig:Reference Id="etsi-data-reference-EtsiDataRefReplace" Type="http://uri.etsi.org/01903/v1.1.1#SignedProperties" URI="#xmlns(etsi=http://uri.etsi.org/01903/v1.1.1%23)%20xpointer(id('etsi-data-object-EtsiDataObjURIReplace')/child::etsi:QualifyingProperties/child::etsi:SignedProperties)"><dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><dsig:DigestValue>DigestValueSignedPropertiesReplace</dsig:DigestValue></dsig:Reference></dsig:SignedInfo>
+<dsig:SignatureValue>SignatureValueReplace</dsig:SignatureValue>
+<dsig:KeyInfo><dsig:X509Data><dsig:X509Certificate>X509CertificateReplace</dsig:X509Certificate></dsig:X509Data></dsig:KeyInfo>
+<dsig:Object Id="signed-data-object-SigDataObjURIReplace"><dsig:Base64Content>Base64ContentReplace</dsig:Base64Content></dsig:Object>
+<dsig:Object Id="etsi-data-object-EtsiDataObjURIReplace"><etsi:QualifyingProperties xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:etsi="http://uri.etsi.org/01903/v1.1.1#" Target="#signature-SigIdReplace"><etsi:SignedProperties xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:etsi="http://uri.etsi.org/01903/v1.1.1#"><etsi:SignedSignatureProperties><etsi:SigningTime>SigningTimeReplace</etsi:SigningTime><etsi:SigningCertificate><etsi:Cert><etsi:CertDigest><etsi:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></etsi:DigestMethod><etsi:DigestValue>DigestValueX509CertificateReplace</etsi:DigestValue></etsi:CertDigest><etsi:IssuerSerial><dsig:X509IssuerName>X509IssuerNameReplace</dsig:X509IssuerName><dsig:X509SerialNumber>X509SerialNumberReplace</dsig:X509SerialNumber></etsi:IssuerSerial></etsi:Cert></etsi:SigningCertificate><etsi:SignaturePolicyIdentifier><etsi:SignaturePolicyImplied></etsi:SignaturePolicyImplied></etsi:SignaturePolicyIdentifier></etsi:SignedSignatureProperties><etsi:SignedDataObjectProperties><etsi:DataObjectFormat ObjectReference="#signed-data-reference-SigDataRefReplace"><etsi:MimeType>text/plain</etsi:MimeType></etsi:DataObjectFormat></etsi:SignedDataObjectProperties></etsi:SignedProperties></etsi:QualifyingProperties></dsig:Object>
+</dsig:Signature> \ No newline at end of file
diff --git a/pdf-as-lib/src/main/resources/config/templates/default.moa.sign.detached.xml b/pdf-as-lib/src/main/resources/config/templates/default.moa.sign.detached.xml
new file mode 100644
index 0000000..4bf42cf
--- /dev/null
+++ b/pdf-as-lib/src/main/resources/config/templates/default.moa.sign.detached.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CreateXMLSignatureRequest xmlns="http://reference.e-government.gv.at/namespace/moa/20020822#" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
+<KeyIdentifier>KeyIdentifierReplace</KeyIdentifier>
+<SingleSignatureInfo SecurityLayerConformity="true">
+<DataObjectInfo Structure="detached">
+<DataObject Reference="urn:Document">
+ <LocRefContent>LocRefContentReplace</LocRefContent>
+</DataObject>
+<CreateTransformsInfoProfile>
+<CreateTransformsInfo>
+<FinalDataMetaInfo>
+<MimeType>MimeTypeReplace</MimeType>
+</FinalDataMetaInfo>
+</CreateTransformsInfo>
+</CreateTransformsInfoProfile>
+</DataObjectInfo>
+</SingleSignatureInfo>
+</CreateXMLSignatureRequest>
+
diff --git a/pdf-as-lib/src/main/resources/config/templates/default.moa.sign.enveloping.xml b/pdf-as-lib/src/main/resources/config/templates/default.moa.sign.enveloping.xml
new file mode 100644
index 0000000..3c08c9e
--- /dev/null
+++ b/pdf-as-lib/src/main/resources/config/templates/default.moa.sign.enveloping.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CreateXMLSignatureRequest xmlns="http://reference.e-government.gv.at/namespace/moa/20020822#" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
+<KeyIdentifier>KeyIdentifierReplace</KeyIdentifier>
+<SingleSignatureInfo SecurityLayerConformity="true">
+<DataObjectInfo Structure="enveloping">
+<DataObject>
+<Base64Content>Base64ContentReplace</Base64Content>
+</DataObject>
+<CreateTransformsInfoProfile>
+<CreateTransformsInfo>
+<FinalDataMetaInfo>
+<MimeType>text/plain</MimeType>
+</FinalDataMetaInfo>
+</CreateTransformsInfo>
+</CreateTransformsInfoProfile>
+</DataObjectInfo>
+</SingleSignatureInfo>
+</CreateXMLSignatureRequest>
+
diff --git a/pdf-as-lib/src/main/resources/config/templates/default.moa.verify.request.detached.xml b/pdf-as-lib/src/main/resources/config/templates/default.moa.verify.request.detached.xml
new file mode 100644
index 0000000..4d7a759
--- /dev/null
+++ b/pdf-as-lib/src/main/resources/config/templates/default.moa.verify.request.detached.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<VerifyXMLSignatureRequest xmlns:sl="http://www.buergerkarte.at/namespaces/securitylayer/1.2#" xmlns="http://reference.e-government.gv.at/namespace/moa/20020822#">
+ DateTimeReplace
+ <VerifySignatureInfo>
+ <VerifySignatureEnvironment>
+ <XMLContent>XMLContentReplace</XMLContent>
+ </VerifySignatureEnvironment>
+ <VerifySignatureLocation xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">/dsig:Signature</VerifySignatureLocation>
+ </VerifySignatureInfo>
+ <SupplementProfile>
+ <Content Reference="urn:Document">
+ <LocRefContent>LocRefContentReplace</LocRefContent>
+ </Content>
+ </SupplementProfile>
+ ReturnHashInputDataReplace
+ <TrustProfileID>TrustProfileIDReplace</TrustProfileID>
+</VerifyXMLSignatureRequest> \ No newline at end of file
diff --git a/pdf-as-lib/src/main/resources/config/templates/default.moa.verify.request.enveloping.xml b/pdf-as-lib/src/main/resources/config/templates/default.moa.verify.request.enveloping.xml
new file mode 100644
index 0000000..81e581f
--- /dev/null
+++ b/pdf-as-lib/src/main/resources/config/templates/default.moa.verify.request.enveloping.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<VerifyXMLSignatureRequest xmlns:sl="http://www.buergerkarte.at/namespaces/securitylayer/1.2#" xmlns="http://reference.e-government.gv.at/namespace/moa/20020822#">
+DateTimeReplace
+<VerifySignatureInfo>
+<VerifySignatureEnvironment>
+<XMLContent>XMLContentReplace</XMLContent>
+</VerifySignatureEnvironment>
+<VerifySignatureLocation xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">/dsig:Signature</VerifySignatureLocation>
+</VerifySignatureInfo>
+ReturnHashInputDataReplace
+<TrustProfileID>TrustProfileIDReplace</TrustProfileID>
+</VerifyXMLSignatureRequest> \ No newline at end of file
diff --git a/pdf-as-lib/src/main/resources/config/templates/default.moa.verify.template.detached.xml b/pdf-as-lib/src/main/resources/config/templates/default.moa.verify.template.detached.xml
new file mode 100644
index 0000000..0141de3
--- /dev/null
+++ b/pdf-as-lib/src/main/resources/config/templates/default.moa.verify.template.detached.xml
@@ -0,0 +1 @@
+<dsig:Signature Id="signature-1-1" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"><dsig:SignedInfo><dsig:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/><dsig:SignatureMethod Algorithm="CertAlgReplace"/><dsig:Reference Id="reference-1-1" URI="urn:Document"><dsig:DigestMethod Algorithm="DataDigestReplace"/><dsig:DigestValue>DigestValueSignedDataReplace</dsig:DigestValue></dsig:Reference><dsig:Reference Type="http://uri.etsi.org/01903/v1.1.1#SignedProperties" URI="#xmlns(etsi=http://uri.etsi.org/01903/v1.1.1%23)%20xpointer(id(&apos;etsi-signed-1-1&apos;)/child::etsi:QualifyingProperties/child::etsi:SignedProperties)"><dsig:DigestMethod Algorithm="PropertiesDigestReplace"/><dsig:DigestValue>DigestValueSignedPropertiesReplace</dsig:DigestValue></dsig:Reference></dsig:SignedInfo><dsig:SignatureValue>SignatureValueReplace</dsig:SignatureValue><dsig:KeyInfo><dsig:X509Data><dsig:X509Certificate>X509CertificateReplace</dsig:X509Certificate></dsig:X509Data></dsig:KeyInfo><dsig:Object Id="etsi-signed-1-1"><etsi:QualifyingProperties Target="#signature-1-1" xmlns:etsi="http://uri.etsi.org/01903/v1.1.1#"><etsi:SignedProperties xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:etsi="http://uri.etsi.org/01903/v1.1.1#"><etsi:SignedSignatureProperties><etsi:SigningTime>SigningTimeReplace</etsi:SigningTime><etsi:SigningCertificate><etsi:Cert><etsi:CertDigest><etsi:DigestMethod Algorithm="CertDigestReplace"></etsi:DigestMethod><etsi:DigestValue>DigestValueX509CertificateReplace</etsi:DigestValue></etsi:CertDigest><etsi:IssuerSerial><dsig:X509IssuerName>X509IssuerNameReplace</dsig:X509IssuerName><dsig:X509SerialNumber>X509SerialNumberReplace</dsig:X509SerialNumber></etsi:IssuerSerial></etsi:Cert></etsi:SigningCertificate><etsi:SignaturePolicyIdentifier><etsi:SignaturePolicyImplied></etsi:SignaturePolicyImplied></etsi:SignaturePolicyIdentifier></etsi:SignedSignatureProperties><etsi:SignedDataObjectProperties><etsi:DataObjectFormat ObjectReference="#reference-1-1"><etsi:MimeType>MimeTypeReplace</etsi:MimeType></etsi:DataObjectFormat></etsi:SignedDataObjectProperties></etsi:SignedProperties></etsi:QualifyingProperties></dsig:Object></dsig:Signature> \ No newline at end of file
diff --git a/pdf-as-lib/src/main/resources/config/templates/default.moa.verify.template.enveloping.xml b/pdf-as-lib/src/main/resources/config/templates/default.moa.verify.template.enveloping.xml
new file mode 100644
index 0000000..0d4b3db
--- /dev/null
+++ b/pdf-as-lib/src/main/resources/config/templates/default.moa.verify.template.enveloping.xml
@@ -0,0 +1,11 @@
+<dsig:Signature Id="signature-1-1" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
+<dsig:SignedInfo xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"><dsig:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/><dsig:SignatureMethod Algorithm="CertAlgReplace"/><dsig:Reference Id="reference-1-1" URI="#xpointer(id('signed-data-1-1-1')/node())"><dsig:Transforms><dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#base64"></dsig:Transform></dsig:Transforms><dsig:DigestMethod Algorithm="DataDigestReplace"/><dsig:DigestValue>DigestValueSignedDataReplace</dsig:DigestValue></dsig:Reference><dsig:Reference Type="http://uri.etsi.org/01903/v1.1.1#SignedProperties" URI="#xmlns(etsi=http://uri.etsi.org/01903/v1.1.1%23)%20xpointer(id('etsi-signed-1-1')/child::etsi:QualifyingProperties/child::etsi:SignedProperties)"><dsig:DigestMethod Algorithm="PropertiesDigestReplace"></dsig:DigestMethod><dsig:DigestValue>DigestValueSignedPropertiesReplace</dsig:DigestValue></dsig:Reference></dsig:SignedInfo>
+<dsig:SignatureValue>SignatureValueReplace</dsig:SignatureValue>
+<dsig:KeyInfo>
+<dsig:X509Data>
+<dsig:X509Certificate>X509CertificateReplace</dsig:X509Certificate>
+</dsig:X509Data>
+</dsig:KeyInfo>
+<dsig:Object Id="signed-data-1-1-1"><Base64Content>Base64ContentReplace</Base64Content></dsig:Object>
+<dsig:Object Id="etsi-signed-1-1"><etsi:QualifyingProperties Target="#signature-1-1" xmlns:etsi="http://uri.etsi.org/01903/v1.1.1#"><etsi:SignedProperties xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:etsi="http://uri.etsi.org/01903/v1.1.1#"><etsi:SignedSignatureProperties><etsi:SigningTime>SigningTimeReplace</etsi:SigningTime><etsi:SigningCertificate><etsi:Cert><etsi:CertDigest><etsi:DigestMethod Algorithm="CertDigestReplace"></etsi:DigestMethod><etsi:DigestValue>DigestValueX509CertificateReplace</etsi:DigestValue></etsi:CertDigest><etsi:IssuerSerial><dsig:X509IssuerName>X509IssuerNameReplace</dsig:X509IssuerName><dsig:X509SerialNumber>X509SerialNumberReplace</dsig:X509SerialNumber></etsi:IssuerSerial></etsi:Cert></etsi:SigningCertificate><etsi:SignaturePolicyIdentifier><etsi:SignaturePolicyImplied></etsi:SignaturePolicyImplied></etsi:SignaturePolicyIdentifier></etsi:SignedSignatureProperties><etsi:SignedDataObjectProperties><etsi:DataObjectFormat ObjectReference="#reference-1-1"><etsi:MimeType>text/plain</etsi:MimeType></etsi:DataObjectFormat></etsi:SignedDataObjectProperties></etsi:SignedProperties></etsi:QualifyingProperties></dsig:Object>
+</dsig:Signature> \ No newline at end of file
diff --git a/pdf-as-lib/src/main/resources/config/templates/default.moc.sign.detached.xml b/pdf-as-lib/src/main/resources/config/templates/default.moc.sign.detached.xml
new file mode 100644
index 0000000..c8252da
--- /dev/null
+++ b/pdf-as-lib/src/main/resources/config/templates/default.moc.sign.detached.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<sl:CreateXMLSignatureRequest xmlns:sl="http://www.buergerkarte.at/namespaces/securitylayer/1.2#">
+<sl:KeyboxIdentifier>KeyboxIdentifierReplace</sl:KeyboxIdentifier>
+<sl:DataObjectInfo Structure="detached">
+<sl:DataObject Reference="urn:Document">
+<sl:LocRefContent>LocRefContentReplace</sl:LocRefContent>
+</sl:DataObject>
+<sl:TransformsInfo>
+<sl:FinalDataMetaInfo>
+<sl:MimeType>MimeTypeReplace</sl:MimeType>
+</sl:FinalDataMetaInfo>
+</sl:TransformsInfo>
+</sl:DataObjectInfo>
+</sl:CreateXMLSignatureRequest>
diff --git a/pdf-as-lib/src/main/resources/config/templates/default.moc.verify.template.detached.xml b/pdf-as-lib/src/main/resources/config/templates/default.moc.verify.template.detached.xml
new file mode 100644
index 0000000..38d96a9
--- /dev/null
+++ b/pdf-as-lib/src/main/resources/config/templates/default.moc.verify.template.detached.xml
@@ -0,0 +1 @@
+<dsig:Signature xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" Id="Signature-SigIdReplace-1"><dsig:SignedInfo Id="SignedInfo-SigIdReplace-1"><dsig:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><dsig:SignatureMethod Algorithm="CertAlgReplace"/><dsig:Reference Id="Reference-SigIdReplace-1" URI="urn:Document"><dsig:DigestMethod Algorithm="DataDigestReplace"></dsig:DigestMethod><dsig:DigestValue>DigestValueSignedDataReplace</dsig:DigestValue></dsig:Reference><dsig:Reference Id="Reference-SigIdReplace-2" Type="http://uri.etsi.org/01903/v1.1.1#SignedProperties" URI="#xmlns(xades=http://uri.etsi.org/01903/v1.1.1%23)%20xpointer(id('Object-SigIdReplace-1')/child::xades:QualifyingProperties/child::xades:SignedProperties)"><dsig:DigestMethod Algorithm="PropertiesDigestReplace"/><dsig:DigestValue>DigestValueSignedPropertiesReplace</dsig:DigestValue></dsig:Reference></dsig:SignedInfo><dsig:SignatureValue Id="SignatureValue-SigIdReplace-1">SignatureValueReplace</dsig:SignatureValue><dsig:KeyInfo><dsig:X509Data><dsig:X509Certificate>X509CertificateReplace</dsig:X509Certificate></dsig:X509Data></dsig:KeyInfo><dsig:Object Id="Object-SigIdReplace-1"><QualifyingProperties xmlns="http://uri.etsi.org/01903/v1.1.1#" xmlns:ns2="http://www.w3.org/2000/09/xmldsig#"><SignedProperties xmlns="http://uri.etsi.org/01903/v1.1.1#" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:ns2="http://www.w3.org/2000/09/xmldsig#" Id="SignedProperties-SigIdReplace-1"><SignedSignatureProperties><SigningTime>SigningTimeReplace</SigningTime><SigningCertificate><Cert><CertDigest><DigestMethod Algorithm="CertDigestReplace"></DigestMethod><DigestValue>DigestValueX509CertificateReplace</DigestValue></CertDigest><IssuerSerial><ns2:X509IssuerName>X509IssuerNameReplace</ns2:X509IssuerName><ns2:X509SerialNumber>X509SerialNumberReplace</ns2:X509SerialNumber></IssuerSerial></Cert></SigningCertificate><SignaturePolicyIdentifier><SignaturePolicyImplied></SignaturePolicyImplied></SignaturePolicyIdentifier></SignedSignatureProperties><SignedDataObjectProperties><DataObjectFormat ObjectReference="#Reference-SigIdReplace-1"><MimeType>MimeTypeReplace</MimeType></DataObjectFormat></SignedDataObjectProperties></SignedProperties></QualifyingProperties></dsig:Object></dsig:Signature> \ No newline at end of file
diff --git a/pdf-as-lib/src/main/resources/config/templates/etsi-bka-atrust-1.0.verify.template.detached.xml b/pdf-as-lib/src/main/resources/config/templates/etsi-bka-atrust-1.0.verify.template.detached.xml
new file mode 100644
index 0000000..093fd0a
--- /dev/null
+++ b/pdf-as-lib/src/main/resources/config/templates/etsi-bka-atrust-1.0.verify.template.detached.xml
@@ -0,0 +1 @@
+<dsig:Signature Id="signature-1-1" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"><dsig:SignedInfo><dsig:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" /><dsig:SignatureMethod Algorithm="CertAlgReplace" /><dsig:Reference Id="reference-1-1" URI="urn:Document"><dsig:DigestMethod Algorithm="DataDigestReplace" /><dsig:DigestValue>DigestValueSignedDataReplace</dsig:DigestValue></dsig:Reference><dsig:Reference Id="etsi-data-reference-1-1" Type="http://uri.etsi.org/01903/v1.1.1#SignedProperties" URI="" ><dsig:Transforms><dsig:Transform Algorithm="http://www.w3.org/2002/06/xmldsig-filter2"><xpf:XPath Filter="intersect" xmlns:etsi="http://uri.etsi.org/01903/v1.1.1#" xmlns:xpf="http://www.w3.org/2002/06/xmldsig-filter2">//*[@Id='etsi-signed-1-1']/etsi:QualifyingProperties/etsi:SignedProperties</xpf:XPath></dsig:Transform></dsig:Transforms><dsig:DigestMethod Algorithm="PropertiesDigestReplace" /><dsig:DigestValue>DigestValueSignedPropertiesReplace</dsig:DigestValue></dsig:Reference></dsig:SignedInfo><dsig:SignatureValue>SignatureValueReplace</dsig:SignatureValue><dsig:KeyInfo><dsig:X509Data><dsig:X509Certificate>X509CertificateReplace</dsig:X509Certificate></dsig:X509Data></dsig:KeyInfo><dsig:Object Id="etsi-signed-1-1"><etsi:QualifyingProperties Target="#signature-1-1" xmlns:etsi="http://uri.etsi.org/01903/v1.1.1#"><etsi:SignedProperties xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:etsi="http://uri.etsi.org/01903/v1.1.1#"><etsi:SignedSignatureProperties><etsi:SigningTime>SigningTimeReplace</etsi:SigningTime><etsi:SigningCertificate><etsi:Cert><etsi:CertDigest><etsi:DigestMethod Algorithm="CertDigestReplace"></etsi:DigestMethod><etsi:DigestValue>DigestValueX509CertificateReplace</etsi:DigestValue></etsi:CertDigest><etsi:IssuerSerial><dsig:X509IssuerName>X509IssuerNameReplace</dsig:X509IssuerName><dsig:X509SerialNumber>X509SerialNumberReplace</dsig:X509SerialNumber></etsi:IssuerSerial></etsi:Cert></etsi:SigningCertificate><etsi:SignaturePolicyIdentifier><etsi:SignaturePolicyImplied></etsi:SignaturePolicyImplied></etsi:SignaturePolicyIdentifier></etsi:SignedSignatureProperties><etsi:SignedDataObjectProperties><etsi:DataObjectFormat ObjectReference="#reference-1-1"><etsi:MimeType>MimeTypeReplace</etsi:MimeType></etsi:DataObjectFormat></etsi:SignedDataObjectProperties></etsi:SignedProperties></etsi:QualifyingProperties></dsig:Object></dsig:Signature> \ No newline at end of file
diff --git a/pdf-as-lib/src/main/resources/config/templates/moc.etsi-moc-1.0.sign.request.xml b/pdf-as-lib/src/main/resources/config/templates/moc.etsi-moc-1.0.sign.request.xml
new file mode 100644
index 0000000..c8252da
--- /dev/null
+++ b/pdf-as-lib/src/main/resources/config/templates/moc.etsi-moc-1.0.sign.request.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<sl:CreateXMLSignatureRequest xmlns:sl="http://www.buergerkarte.at/namespaces/securitylayer/1.2#">
+<sl:KeyboxIdentifier>KeyboxIdentifierReplace</sl:KeyboxIdentifier>
+<sl:DataObjectInfo Structure="detached">
+<sl:DataObject Reference="urn:Document">
+<sl:LocRefContent>LocRefContentReplace</sl:LocRefContent>
+</sl:DataObject>
+<sl:TransformsInfo>
+<sl:FinalDataMetaInfo>
+<sl:MimeType>MimeTypeReplace</sl:MimeType>
+</sl:FinalDataMetaInfo>
+</sl:TransformsInfo>
+</sl:DataObjectInfo>
+</sl:CreateXMLSignatureRequest>
diff --git a/pdf-as-lib/src/main/resources/config/templates/moc.etsi-moc-1.0.verify.template.xml b/pdf-as-lib/src/main/resources/config/templates/moc.etsi-moc-1.0.verify.template.xml
new file mode 100644
index 0000000..38d96a9
--- /dev/null
+++ b/pdf-as-lib/src/main/resources/config/templates/moc.etsi-moc-1.0.verify.template.xml
@@ -0,0 +1 @@
+<dsig:Signature xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" Id="Signature-SigIdReplace-1"><dsig:SignedInfo Id="SignedInfo-SigIdReplace-1"><dsig:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><dsig:SignatureMethod Algorithm="CertAlgReplace"/><dsig:Reference Id="Reference-SigIdReplace-1" URI="urn:Document"><dsig:DigestMethod Algorithm="DataDigestReplace"></dsig:DigestMethod><dsig:DigestValue>DigestValueSignedDataReplace</dsig:DigestValue></dsig:Reference><dsig:Reference Id="Reference-SigIdReplace-2" Type="http://uri.etsi.org/01903/v1.1.1#SignedProperties" URI="#xmlns(xades=http://uri.etsi.org/01903/v1.1.1%23)%20xpointer(id('Object-SigIdReplace-1')/child::xades:QualifyingProperties/child::xades:SignedProperties)"><dsig:DigestMethod Algorithm="PropertiesDigestReplace"/><dsig:DigestValue>DigestValueSignedPropertiesReplace</dsig:DigestValue></dsig:Reference></dsig:SignedInfo><dsig:SignatureValue Id="SignatureValue-SigIdReplace-1">SignatureValueReplace</dsig:SignatureValue><dsig:KeyInfo><dsig:X509Data><dsig:X509Certificate>X509CertificateReplace</dsig:X509Certificate></dsig:X509Data></dsig:KeyInfo><dsig:Object Id="Object-SigIdReplace-1"><QualifyingProperties xmlns="http://uri.etsi.org/01903/v1.1.1#" xmlns:ns2="http://www.w3.org/2000/09/xmldsig#"><SignedProperties xmlns="http://uri.etsi.org/01903/v1.1.1#" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:ns2="http://www.w3.org/2000/09/xmldsig#" Id="SignedProperties-SigIdReplace-1"><SignedSignatureProperties><SigningTime>SigningTimeReplace</SigningTime><SigningCertificate><Cert><CertDigest><DigestMethod Algorithm="CertDigestReplace"></DigestMethod><DigestValue>DigestValueX509CertificateReplace</DigestValue></CertDigest><IssuerSerial><ns2:X509IssuerName>X509IssuerNameReplace</ns2:X509IssuerName><ns2:X509SerialNumber>X509SerialNumberReplace</ns2:X509SerialNumber></IssuerSerial></Cert></SigningCertificate><SignaturePolicyIdentifier><SignaturePolicyImplied></SignaturePolicyImplied></SignaturePolicyIdentifier></SignedSignatureProperties><SignedDataObjectProperties><DataObjectFormat ObjectReference="#Reference-SigIdReplace-1"><MimeType>MimeTypeReplace</MimeType></DataObjectFormat></SignedDataObjectProperties></SignedProperties></QualifyingProperties></dsig:Object></dsig:Signature> \ No newline at end of file
diff --git a/pdf-as-lib/src/main/resources/config/templates/moc.etsi-moc-1.1.verify.template.xml b/pdf-as-lib/src/main/resources/config/templates/moc.etsi-moc-1.1.verify.template.xml
new file mode 100644
index 0000000..a801653
--- /dev/null
+++ b/pdf-as-lib/src/main/resources/config/templates/moc.etsi-moc-1.1.verify.template.xml
@@ -0,0 +1 @@
+<dsig:Signature Id="Signature-SigIdReplace-1" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"><dsig:SignedInfo Id="SignedInfo-SigIdReplace-1"><dsig:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><dsig:SignatureMethod Algorithm="CertAlgReplace"/><dsig:Reference Id="Reference-SigIdReplace-1" URI="urn:Document"><dsig:DigestMethod Algorithm="DataDigestReplace"/><dsig:DigestValue>DigestValueSignedDataReplace</dsig:DigestValue></dsig:Reference><dsig:Reference Id="Reference-SigIdReplace-2" Type="http://uri.etsi.org/01903/v1.1.1#SignedProperties" URI="#xmlns(xades=http://uri.etsi.org/01903/v1.1.1%23)%20xpointer(id('Object-SigIdReplace-1')/child::xades:QualifyingProperties/child::xades:SignedProperties)"><dsig:DigestMethod Algorithm="PropertiesDigestReplace"/><dsig:DigestValue>DigestValueSignedPropertiesReplace</dsig:DigestValue></dsig:Reference></dsig:SignedInfo><dsig:SignatureValue Id="SignatureValue-SigIdReplace-1">SignatureValueReplace</dsig:SignatureValue><dsig:KeyInfo><dsig:X509Data><dsig:X509Certificate>X509CertificateReplace</dsig:X509Certificate></dsig:X509Data></dsig:KeyInfo><dsig:Object Id="Object-SigIdReplace-1"><xades:QualifyingProperties Target="#Signature-SigIdReplace-1" xmlns:xades="http://uri.etsi.org/01903/v1.1.1#" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:sl="http://www.buergerkarte.at/namespaces/securitylayer/1.2#"><xades:SignedProperties xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:sl="http://www.buergerkarte.at/namespaces/securitylayer/1.2#" xmlns:xades="http://uri.etsi.org/01903/v1.1.1#" Id="SignedProperties-SigIdReplace-1"><xades:SignedSignatureProperties><xades:SigningTime>SigningTimeReplace</xades:SigningTime><xades:SigningCertificate><xades:Cert><xades:CertDigest><xades:DigestMethod Algorithm="CertDigestReplace"></xades:DigestMethod><xades:DigestValue>DigestValueX509CertificateReplace</xades:DigestValue></xades:CertDigest><xades:IssuerSerial><dsig:X509IssuerName>X509IssuerNameReplace</dsig:X509IssuerName><dsig:X509SerialNumber>X509SerialNumberReplace</dsig:X509SerialNumber></xades:IssuerSerial></xades:Cert></xades:SigningCertificate><xades:SignaturePolicyIdentifier><xades:SignaturePolicyImplied></xades:SignaturePolicyImplied></xades:SignaturePolicyIdentifier></xades:SignedSignatureProperties><xades:SignedDataObjectProperties><xades:DataObjectFormat ObjectReference="#Reference-SigIdReplace-1"><xades:MimeType>MimeTypeReplace</xades:MimeType></xades:DataObjectFormat></xades:SignedDataObjectProperties></xades:SignedProperties></xades:QualifyingProperties></dsig:Object></dsig:Signature> \ No newline at end of file