aboutsummaryrefslogtreecommitdiff
path: root/pdf-as-lib/src/main/java/at
diff options
context:
space:
mode:
Diffstat (limited to 'pdf-as-lib/src/main/java/at')
-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
339 files changed, 61661 insertions, 0 deletions
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);
+ }
+
+}