From db52e4d66d60184d53a27ba4d6772461daacc03d Mon Sep 17 00:00:00 2001 From: tknall Date: Fri, 22 Mar 2013 08:57:51 +0000 Subject: Maintenance update (bugfixes, new features, cleanup...) Refer to /dok/RELEASE_NOTES-3.3.txt for further information. git-svn-id: https://joinup.ec.europa.eu/svn/pdf-as/pdf-as/trunk@931 7b5415b0-85f9-ee4d-85bd-d5d0c3b42d1c --- .../at/gv/egiz/pdfas/impl/api/PdfAsObject.java | 441 +++++++++++++++------ .../pdfas/impl/api/commons/DataSinkAdapter.java | 6 +- .../impl/api/commons/SignatureProfileImpl.java | 49 ++- .../impl/input/correction/InternalCorrector.java | 9 +- .../impl/signator/binary/BinarySignator_1_0_0.java | 16 +- .../detached/DetachedTextualSignator_1_0_0.java | 7 +- .../pdfas/impl/vfilter/VerificationFilterImpl.java | 218 +++++----- .../helper/VerificationFilterBinaryHelper.java | 19 +- 8 files changed, 500 insertions(+), 265 deletions(-) (limited to 'pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl') diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/PdfAsObject.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/PdfAsObject.java index eda94c0..a2bcd15 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/PdfAsObject.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/PdfAsObject.java @@ -33,6 +33,7 @@ import java.util.Properties; import java.util.Vector; import org.apache.commons.lang.math.NumberUtils; +import org.apache.commons.lang.time.StopWatch; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -66,6 +67,9 @@ import at.gv.egiz.pdfas.framework.DataSourceHolder; import at.gv.egiz.pdfas.framework.config.SettingsHelper; import at.gv.egiz.pdfas.framework.input.ExtractionStage; import at.gv.egiz.pdfas.framework.input.PdfDataSource; +import at.gv.egiz.pdfas.framework.logging.StatisticData; +import at.gv.egiz.pdfas.framework.logging.StatisticLogFactory; +import at.gv.egiz.pdfas.framework.logging.StatisticLogger; import at.gv.egiz.pdfas.framework.signator.Signator; import at.gv.egiz.pdfas.framework.signator.SignatorInformation; import at.gv.egiz.pdfas.framework.vfilter.VerificationFilterParameters; @@ -87,6 +91,7 @@ import at.gv.egiz.pdfas.placeholder.SignaturePlaceholderContext; import at.gv.egiz.pdfas.placeholder.SignaturePlaceholderData; import at.gv.egiz.pdfas.placeholder.SignaturePlaceholderExtractor; import at.gv.egiz.pdfas.utils.ConfigUtils; +import at.gv.egiz.pdfas.utils.PDFASUtils; import at.knowcenter.wag.egov.egiz.PdfAS; import at.knowcenter.wag.egov.egiz.PdfASID; import at.knowcenter.wag.egov.egiz.cfg.OverridePropertyHolder; @@ -111,12 +116,13 @@ import at.knowcenter.wag.egov.egiz.sig.SignatureDataImpl; import at.knowcenter.wag.egov.egiz.sig.SignatureResponse; import at.knowcenter.wag.egov.egiz.sig.SignatureTypeDefinition; import at.knowcenter.wag.egov.egiz.sig.SignatureTypes; +import at.knowcenter.wag.egov.egiz.sig.SignatureTypes.State; import at.knowcenter.wag.egov.egiz.sig.connectors.Connector; import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject; /** * Implementation of the {@link PdfAs} interface. - * + * * @author wprinz */ public class PdfAsObject implements PdfAs @@ -127,25 +133,26 @@ public class PdfAsObject implements PdfAs * The log. */ private static Log log = LogFactory.getLog(PdfAsObject.class); - + private static StatisticLogger statLog = StatisticLogFactory.getLog(Constants.STATISTIC_LOGGER_NAME); + private static final String ENABLE_PLACEHOLDER_SEARCH_KEY = "enable_placeholder_search"; - + /** * Configuration key for minimal signature block width threshold. Any width below this certain value will lead to a warning log entry." */ private static final String SIGNATURE_BLOCK_WIDTH_THRESHOLD_FOR_WARNING_KEY = "signature_block_width_warning_threshold"; - + /** * Minimal signature block width. If a width below that value is defined (by parameter, by placeholder or by configuration) a warning log entry is created. */ public static final float DEFAULT_SIGNATURE_BLOCK_WIDTH_THRESHOLD = 150; - + /** * This constructor is for internal use only - use * {@link at.gv.egiz.pdfas.PdfAsFactory} instead. * Note: IAIK JCE and IAIK ECC security providers are automatically registered. - * + * * @param workDirectory * The work directory. * @throws PdfAsException @@ -155,16 +162,16 @@ public class PdfAsObject implements PdfAs { this(workDirectory, SettingsReader.REGISTER_IAIK_PROVIDERS_ON_DEFAULT); } - + /** * This constructor is for internal use only - use * {@link at.gv.egiz.pdfas.PdfAsFactory} instead. - * + * * @param workDirectory * The work directory. * @param registerProvider true: automatically registers IAIK JCE and ECC Provider; * false: providers will NOT be automatically registered, providers - * needed have to be registered by the API user + * needed have to be registered by the API user * @throws PdfAsException * Thrown, if the configuration cannot be processed. */ @@ -174,12 +181,12 @@ public class PdfAsObject implements PdfAs SettingsReader.initialize(path, path); reloadConfig(registerProvider); } - + /** * This constructor is for internal use only - use * {@link at.gv.egiz.pdfas.PdfAsFactory} instead. * Note: IAIK JCE and IAIK ECC security providers are automatically registered. - * + * * @throws PdfAsException * Thrown, if the configuration cannot be processed. */ @@ -187,7 +194,7 @@ public class PdfAsObject implements PdfAs { this(null); } - + /** * @see at.gv.egiz.pdfas.api.PdfAs#reloadConfig() */ @@ -197,11 +204,11 @@ public class PdfAsObject implements PdfAs SettingsReader.createInstance(); SignatureTypes.createInstance(); } - + /** * @param registerProvider true: automatically registers IAIK JCE and ECC Provider; * false: providers will NOT be automatically registered, providers - * needed have to be registered by the API user + * needed have to be registered by the API user * @see at.gv.egiz.pdfas.api.PdfAs#reloadConfig() */ private void reloadConfig(boolean registerProvider) throws PdfAsException @@ -228,7 +235,7 @@ public class PdfAsObject implements PdfAs List profileInformation = new ArrayList(profiles.size()); String default_type = settings.getValueFromKey(SignatureTypes.DEFAULT_TYPE); - + Iterator it = profiles.iterator(); while (it.hasNext()) { @@ -240,14 +247,17 @@ public class PdfAsObject implements PdfAs final String profileDescription = settings.getSetting("sig_obj." + profileId + "." + SignatureTypes.SIG_DESCR, null); boolean isDefault = (default_type != null && default_type.equals(profileId)); + + State state = State.fromString(settings.getSetting(SignatureTypes.TYPES + "." + profileId)); + // modified by tknall - SignatureProfileImpl signatureProfile = new SignatureProfileImpl(profileId, profileDescription, moaKeyIdentifier, isDefault); + SignatureProfileImpl signatureProfile = new SignatureProfileImpl(profileId, state, profileDescription, moaKeyIdentifier, isDefault); // start - added by tknall - + // signature entries relevant to the search algorithm Properties signatureEntries = new Properties(); - + // search for table entries String parentPropertyKey = "sig_obj." + profileId + ".table"; log.debug("Looking for subkeys of \"" + parentPropertyKey + "\"."); @@ -275,7 +285,7 @@ public class PdfAsObject implements PdfAs } } } - + // search for table entries parentPropertyKey = "sig_obj." + profileId + ".key"; log.debug("Looking for subkeys of \"" + parentPropertyKey + "\"."); @@ -295,46 +305,89 @@ public class PdfAsObject implements PdfAs } } } - + // set properties signatureProfile.setSignatureBlockEntries(signatureEntries); // stop - added by tknall - + profileInformation.add(signatureProfile); } return profileInformation; } - /** - * @see at.gv.egiz.pdfas.api.PdfAs#sign(at.gv.egiz.pdfas.api.sign.SignParameters) - */ - public SignResult sign(SignParameters signParameters) throws PdfAsException + public SignResult sign(SignParameters signParameters) throws PdfAsException { + // prepare log data + StatisticData sd = new StatisticData(signParameters); + StopWatch sw = new StopWatch(); + try { + sw.start(); + return performSign(signParameters); + } catch (PdfAsException e) { + sd.setException(e); + throw e; + } catch (RuntimeException e) { + sd.setException(e); + throw e; + } finally { + sw.stop(); + sd.setDuration(sw.getTime()); + statLog.log(sd); + } + } + + private SignResult performSign(SignParameters signParameters) throws PdfAsException { CheckHelper.checkSignParameters(signParameters, false); - + + // make sure that the selected profile is allowed to be used for signature + SettingsReader settings = SettingsReader.getInstance(); + if (!State.fromString(settings.getSetting(SignatureTypes.TYPES + "." + signParameters.getSignatureProfileId())) + .canSign()) { + throw new SignatureException(ErrorCode.SIGNATURE_PROFILE_IS_NOT_ALLOWED_FOR_SIGNATURE, + "The signature profile '" + signParameters.getSignatureProfileId() + + "' is not allowed to be used for signature."); + } + try { - SignatureDetailInformation signatorInfo = prepareSign(signParameters); - - return sign(signParameters, signatorInfo); - + + SignatureDetailInformation signatorInfo = performPrepareSign(signParameters); + return performSign(signParameters, signatorInfo); + } catch (java.lang.OutOfMemoryError e) { throw new OutOfMemoryException(ErrorCode.OUT_OF_MEMORY_ERROR, "Insufficient memory allocated to virtual machine. Start Java with parameters \"-Xms128m -Xmx786m -XX:MaxPermSize=256m\".", e); } } - /** - * @see at.gv.egiz.pdfas.api.PdfAs#verify(at.gv.egiz.pdfas.api.verify.VerifyParameters) - */ - public VerifyResults verify(VerifyParameters verifyParameters) throws PdfAsException + public VerifyResults verify(VerifyParameters verifyParameters) throws PdfAsException { + // prepare log data + StatisticData sd = new StatisticData(verifyParameters); + StopWatch sw = new StopWatch(); + try { + sw.start(); + return performVerify(verifyParameters); + } catch (PdfAsException e) { + sd.setException(e); + throw e; + } catch (RuntimeException e) { + sd.setException(e); + throw e; + } finally { + sw.stop(); + sd.setDuration(sw.getTime()); + statLog.log(sd); + } + } + + private VerifyResults performVerify(VerifyParameters verifyParameters) throws PdfAsException { CheckHelper.checkVerifyParameters(verifyParameters); AnalyzeParameters ap = new AnalyzeParameters(); fillAnalyzeParametersWithVerifyParameters(ap, verifyParameters); - AnalyzeResult analyzeResult = analyze(ap); + AnalyzeResult analyzeResult = performAnalyze(ap); if (verifyParameters.getSignatureToVerify() != Constants.VERIFY_ALL) { @@ -352,17 +405,17 @@ public class PdfAsObject implements PdfAs VerifyAfterAnalysisParameters vaap = new VerifyAfterAnalysisParameters(); vaap.setAnalyzeResult(analyzeResult); fillVerifyAfterAnalysisParametersWithVerifyParameters(vaap, verifyParameters); - VerifyResults res = verify(vaap); - + VerifyResults res = performVerify(vaap); + return res; - + } - + /** * Copies all adequate parameters from the {@link VerifyParameters} to the * {@link AnalyzeParameters}. - * + * * @param ap * The {@link AnalyzeParameters}. * @param vp @@ -385,7 +438,7 @@ public class PdfAsObject implements PdfAs /** * Copies all adequate parameters from the {@link VerifyParameters} to the * {@link VerifyAfterAnalysisParameters}. - * + * * @param vaap * The {@link VerifyAfterAnalysisParameters}. * @param vp @@ -406,10 +459,30 @@ public class PdfAsObject implements PdfAs reconstructParams.setSignatureDevice(verifyAfterAnalysisParameters.getSignatureDevice()); } - /** - * @see at.gv.egiz.pdfas.api.PdfAs#analyze(at.gv.egiz.pdfas.api.analyze.AnalyzeParameters) - */ - public AnalyzeResult analyze(AnalyzeParameters analyzeParameters) throws PdfAsException + public AnalyzeResult analyze(AnalyzeParameters analyzeParameters) throws PdfAsException { + // prepare log data + StatisticData sd = new StatisticData(analyzeParameters); + StopWatch sw = new StopWatch(); + try { + sw.start(); + return performAnalyze(analyzeParameters); + } catch (PdfAsException e) { + sd.setException(e); + throw e; + } catch (RuntimeException e) { + sd.setException(e); + throw e; + } finally { + sw.stop(); + sd.setDuration(sw.getTime()); + // only log in case of error + if (sd.isError()) { + statLog.log(sd); + } + } + } + + private AnalyzeResult performAnalyze(AnalyzeParameters analyzeParameters) throws PdfAsException { CheckHelper.checkAnalyzeParameters(analyzeParameters); @@ -429,10 +502,12 @@ public class PdfAsObject implements PdfAs assumeOnlySB = false; } VerificationFilterParameters parameters = new VerificationFilterParametersImpl(binaryOnly, assumeOnlySB, parametersConfig.scanForOldSignatures()); - + at.gv.egiz.pdfas.framework.input.DataSource inputDataSource = null; if (analyzeParameters.getDocument().getMimeType().equals("application/pdf")) { + // check document permissions + PDFASUtils.createPdfReaderCheckingPermissions(analyzeParameters.getDocument()); inputDataSource = new PdfDataSourceAdapter(analyzeParameters.getDocument()); } else @@ -447,13 +522,13 @@ public class PdfAsObject implements PdfAs } } assert inputDataSource != null; - + try { ExtractionStage es = new ExtractionStage(); DataSourceHolder dsh = new DataSourceHolder(inputDataSource); List signature_holders = es.extractSignatureHolders(dsh, parameters); - - + + // List sigInfs = new ArrayList(signature_holders.size()); List sigInfs = new ArrayList(); List noSigs = new ArrayList(); @@ -461,24 +536,24 @@ public class PdfAsObject implements PdfAs while (it.hasNext()) { SignatureHolder sh = (SignatureHolder)it.next(); - + if(sh instanceof NoSignatureHolder) { noSigs.add(sh); } else { - + SignatureInformation si = new SignatureInformationAdapter(sh); sigInfs.add(si); - if (analyzeParameters.isReturnNonTextualObjects()) { - si.setNonTextualObjects(doExtractNonTexualObjects(sh, (PdfDataSource) dsh.getDataSource())); - } - + if (analyzeParameters.isReturnNonTextualObjects()) { + si.setNonTextualObjects(doExtractNonTexualObjects(sh, (PdfDataSource) dsh.getDataSource())); + } + } } return new AnalyzeResultImpl(sigInfs, noSigs, parameters.hasBeenCorrected()); } catch (java.lang.OutOfMemoryError e) { throw new OutOfMemoryException(ErrorCode.OUT_OF_MEMORY_ERROR, "Insufficient memory allocated to virtual machine. Start Java with parameters \"-Xms128m -Xmx786m -XX:MaxPermSize=256m\".", e); } - + } private List doExtractNonTexualObjects(SignatureHolder sh, PdfDataSource pdfDataSource) { @@ -499,30 +574,47 @@ public class PdfAsObject implements PdfAs } } -/** - * @see at.gv.egiz.pdfas.api.PdfAs#verify(at.gv.egiz.pdfas.api.verify.VerifyAfterAnalysisParameters) - */ - public VerifyResults verify(VerifyAfterAnalysisParameters verifyAfterAnalysisParameters) throws PdfAsException + public VerifyResults verify(VerifyAfterAnalysisParameters verifyAfterAnalysisParameters) throws PdfAsException { + // prepare log data + StatisticData sd = new StatisticData(verifyAfterAnalysisParameters); + StopWatch sw = new StopWatch(); + try { + sw.start(); + return performVerify(verifyAfterAnalysisParameters); + } catch (PdfAsException e) { + sd.setException(e); + throw e; + } catch (RuntimeException e) { + sd.setException(e); + throw e; + } finally { + sw.stop(); + sd.setDuration(sw.getTime()); + statLog.log(sd); + } + } + + private VerifyResults performVerify(VerifyAfterAnalysisParameters verifyAfterAnalysisParameters) throws PdfAsException { CheckHelper.checkVerifyAfterAnalysisParameters(verifyAfterAnalysisParameters); List signatures = verifyAfterAnalysisParameters.getAnalyzeResult().getSignatures(); - + // added by tknall if (signatures == null || signatures.isEmpty()) { throw new PDFDocumentException(ErrorCode.DOCUMENT_NOT_SIGNED, "PDF document not signed."); //$NON-NLS-1$ } - + ReconstructXMLDsigAfterAnalysisParameters rxaap = new ReconstructXMLDsigAfterAnalysisParameters(); fillReconstructXMLDsigAfterAnalysisParametersWithVerifyAfterAnalysisParameters(rxaap, verifyAfterAnalysisParameters); - ReconstructXMLDsigResult reconstructResult = reconstructXMLDSIG(rxaap); - + ReconstructXMLDsigResult reconstructResult = performReconstructXMLDSIG(rxaap); + VerifyAfterReconstructXMLDsigParameters varxp = new VerifyAfterReconstructXMLDsigParameters(); fillVerifyAfterReconstructXMLDsigParametersWithVerifyAfterAnalysisParameters(varxp, verifyAfterAnalysisParameters); varxp.setReconstructXMLDsigResult(reconstructResult); - - return verify(varxp); - + + return performVerify(varxp); + } protected void fillVerifyAfterReconstructXMLDsigParametersWithVerifyAfterAnalysisParameters( @@ -534,31 +626,75 @@ public class PdfAsObject implements PdfAs varxp.setVerifySignatureIndex(verifyAfterAnalysisParameters.getVerifySignatureIndex()); } - /** - * @see PdfAs#reconstructXMLDSIG(ReconstructXMLDsigParameters) - */ public ReconstructXMLDsigResult reconstructXMLDSIG( + ReconstructXMLDsigParameters reconstructXMLDsigParameters) + throws PdfAsException { + // prepare log data + StatisticData sd = new StatisticData(reconstructXMLDsigParameters); + StopWatch sw = new StopWatch(); + try { + sw.start(); + return performReconstructXMLDSIG(reconstructXMLDsigParameters); + } catch (PdfAsException e) { + sd.setException(e); + throw e; + } catch (RuntimeException e) { + sd.setException(e); + throw e; + } finally { + sw.stop(); + sd.setDuration(sw.getTime()); + // only log in case of error + if (sd.isError()) { + statLog.log(sd); + } + } + } + + private ReconstructXMLDsigResult performReconstructXMLDSIG( ReconstructXMLDsigParameters reconstructXMLDsigParameters) throws PdfAsException { - + AnalyzeParameters analyzeParameters = new AnalyzeParameters(); fillAnalyzeParametersWithReconstructXMLDsigParameters(analyzeParameters, reconstructXMLDsigParameters); - AnalyzeResult ar = analyze(analyzeParameters); - + AnalyzeResult ar = performAnalyze(analyzeParameters); + ReconstructXMLDsigAfterAnalysisParameters rxaap = new ReconstructXMLDsigAfterAnalysisParameters(); rxaap.setSignatureDevice(reconstructXMLDsigParameters.getSignatureDevice()); rxaap.setAnalyzeResult(ar); - - return reconstructXMLDSIG(rxaap); + + return performReconstructXMLDSIG(rxaap); } - /** - * @see PdfAs#reconstructXMLDSIG(ReconstructXMLDsigAfterAnalysisParameters) - */ public ReconstructXMLDsigResult reconstructXMLDSIG( + ReconstructXMLDsigAfterAnalysisParameters reconstructXMLDsigParameters) + throws PdfAsException { + // prepare log data + StatisticData sd = new StatisticData(reconstructXMLDsigParameters); + StopWatch sw = new StopWatch(); + try { + sw.start(); + return performReconstructXMLDSIG(reconstructXMLDsigParameters); + } catch (PdfAsException e) { + sd.setException(e); + throw e; + } catch (RuntimeException e) { + sd.setException(e); + throw e; + } finally { + sw.stop(); + sd.setDuration(sw.getTime()); + // only log in case of error + if (sd.isError()) { + statLog.log(sd); + } + } + } + + private ReconstructXMLDsigResult performReconstructXMLDSIG( ReconstructXMLDsigAfterAnalysisParameters reconstructXMLDsigParameters) throws PdfAsException { - + AnalyzeResult ar = reconstructXMLDsigParameters.getAnalyzeResult(); List extendedSignatureInfos = new Vector(); for (int i = 0; i < ar.getSignatures().size(); i++) @@ -572,31 +708,52 @@ public class PdfAsObject implements PdfAs // don't care for connector exceptions because of mutli signs. they are handled during verify extendedSignatureInfos.add(new ExtendedSignatureInformation(si, null)); } - + } return new ReconstructXMLDsigResult(extendedSignatureInfos, reconstructXMLDsigParameters.getSignatureDevice()); } + public VerifyResults verify(VerifyAfterReconstructXMLDsigParameters verifyAfterReconstructXMLDsigParameters) + throws PdfAsException { + // prepare log data + StatisticData sd = new StatisticData(verifyAfterReconstructXMLDsigParameters); + StopWatch sw = new StopWatch(); + try { + sw.start(); + return performVerify(verifyAfterReconstructXMLDsigParameters); + } catch (PdfAsException e) { + sd.setException(e); + throw e; + } catch (RuntimeException e) { + sd.setException(e); + throw e; + } finally { + sw.stop(); + sd.setDuration(sw.getTime()); + statLog.log(sd); + } + } + /** * @see PdfAs#verify(VerifyAfterReconstructXMLDsigParameters) */ - public VerifyResults verify( + private VerifyResults performVerify( VerifyAfterReconstructXMLDsigParameters verifyAfterReconstructXMLDsigParameters) throws PdfAsException { - + try { List extSignatures = verifyAfterReconstructXMLDsigParameters.getReconstructXMLDsigResult().getExtendedSignatures(); String signatureDevice = verifyAfterReconstructXMLDsigParameters.getSignatureDevice(); if (signatureDevice == null){ signatureDevice = verifyAfterReconstructXMLDsigParameters.getReconstructXMLDsigResult().getDevice(); } - List results = PdfAS.verifyExtendedSignatureHolders(extSignatures, - signatureDevice, - verifyAfterReconstructXMLDsigParameters.isReturnHashInputData(), + List results = PdfAS.verifyExtendedSignatureHolders(extSignatures, + signatureDevice, + verifyAfterReconstructXMLDsigParameters.isReturnHashInputData(), verifyAfterReconstructXMLDsigParameters.getVerificationTime(), verifyAfterReconstructXMLDsigParameters.getVerifySignatureIndex()); - + List vrs = new ArrayList(results.size()); - + int verifySignatureIndex = verifyAfterReconstructXMLDsigParameters.getVerifySignatureIndex(); if (verifySignatureIndex < 0) { @@ -605,23 +762,23 @@ public class PdfAsObject implements PdfAs SignatureResponse response = (SignatureResponse) results.get(i); ExtendedSignatureInformation extSigInfo = (ExtendedSignatureInformation)extSignatures.get(i); SignatureHolder holder = (SignatureHolder) extSigInfo.getSignatureInformation().getInternalSignatureInformation(); - + VerifyResult vr = new VerifyResultAdapter(response, holder, verifyAfterReconstructXMLDsigParameters.getVerificationTime(), extSigInfo.getXmlDsigData()); vr.setNonTextualObjects( extSigInfo.getSignatureInformation().getNonTextualObjects()); - + vrs.add(vr); } }else{ SignatureResponse response = (SignatureResponse) results.get(0); ExtendedSignatureInformation extSigInfo = (ExtendedSignatureInformation)extSignatures.get(verifySignatureIndex); SignatureHolder holder = (SignatureHolder) extSigInfo.getSignatureInformation().getInternalSignatureInformation(); - + VerifyResult vr = new VerifyResultAdapter(response, holder, verifyAfterReconstructXMLDsigParameters.getVerificationTime(), extSigInfo.getXmlDsigData()); vr.setNonTextualObjects( extSigInfo.getSignatureInformation().getNonTextualObjects()); - + vrs.add(vr); } - + VerifyResultsImpl verifyResults = new VerifyResultsImpl(vrs); return verifyResults; } catch (java.lang.OutOfMemoryError e) { @@ -632,7 +789,7 @@ public class PdfAsObject implements PdfAs public DynamicSignatureProfile createDynamicSignatureProfile(String parentProfile, DynamicSignatureLifetimeEnum mode) { return DynamicSignatureProfileImpl.createFromParent(null, parentProfile, mode); } - + public DynamicSignatureProfile createEmptyDynamicSignatureProfile(DynamicSignatureLifetimeEnum mode) { return DynamicSignatureProfileImpl.createEmptyProfile(null, mode); } @@ -648,19 +805,44 @@ public class PdfAsObject implements PdfAs public DynamicSignatureProfile createEmptyDynamicSignatureProfile(String myUniqueName, DynamicSignatureLifetimeEnum mode) { - return DynamicSignatureProfileImpl.createEmptyProfile(myUniqueName, mode); + return DynamicSignatureProfileImpl.createEmptyProfile(myUniqueName, mode); + } + + public SignatureDetailInformation prepareSign(SignParameters signParameters) throws PdfAsException { + // prepare log data + StatisticData sd = new StatisticData(signParameters); + StopWatch sw = new StopWatch(); + try { + sw.start(); + return performPrepareSign(signParameters); + } catch (PdfAsException e) { + sd.setException(e); + throw e; + } catch (RuntimeException e) { + sd.setException(e); + throw e; + } finally { + sw.stop(); + sd.setDuration(sw.getTime()); + // only log in case of error + if (sd.isError()) { + statLog.log(sd); + } + } } /** * @see PdfAs#prepareSign(SignParameters) */ - public SignatureDetailInformation prepareSign(SignParameters signParameters) throws PdfAsException { + private SignatureDetailInformation performPrepareSign(SignParameters signParameters) throws PdfAsException { CheckHelper.checkSignParameters(signParameters, true); - + if (signParameters.getProfileOverrideProperties() != null) { OverridePropertyHolder.setOverrideProps(signParameters.getProfileOverrideProperties()); } + PDFASUtils.createPdfReaderCheckingPermissions(signParameters.getDocument()); + signParameters.setDocument(PdfAS.applyStrictMode(signParameters.getDocument())); SettingsReader settings = SettingsReader.getInstance(); @@ -730,29 +912,29 @@ public class PdfAsObject implements PdfAs } else if (fromConfig) { arguments[0] = "width defined by the profile " + signParameters.getSignatureProfileId(); } - log.warn(MessageFormat.format(msg, arguments)); + log.warn(MessageFormat.format(msg, (Object[]) arguments)); } } - + Signator signator = createSignator(signParameters.getSignatureType()); SignatorInformation signatorInfo = signator.prepareSign( - new PdfDataSourceAdapter(signParameters.getDocument()), - signParameters.getSignatureProfileId(), - pos, + new PdfDataSourceAdapter(signParameters.getDocument()), + signParameters.getSignatureProfileId(), + pos, signParameters.getTimeStamperImpl()); - + SignatureDetailInformationImpl ret = new SignatureDetailInformationImpl(); ret.setSignatorInformation(signatorInfo); return ret; } - + private SignaturePlaceholderData getSignaturePlaceholder(SignParameters signParameters, String defaultProfile) throws SettingsException, PDFDocumentException, PlaceholderExtractionException { SignaturePlaceholderData spd = null; SignaturePlaceholderContext.setSignaturePlaceholderData(null); - + SettingsReader settings = SettingsReader.getInstance(); // check sig_obj.PROFILEID.enable_placeholder_search @@ -766,15 +948,15 @@ public class PdfAsObject implements PdfAs // check global enable_placeholder_search configFileActivedString = settings.getValueFromKey(ENABLE_PLACEHOLDER_SEARCH_KEY); } - + Boolean configFileActived = null; if (configFileActivedString != null) configFileActived = Boolean.valueOf(configFileActivedString); Boolean signParamsActivated = signParameters.isCheckForPlaceholder(); - + boolean enableSearch; - + if (signParamsActivated != null) { enableSearch = signParamsActivated.booleanValue(); @@ -788,8 +970,8 @@ public class PdfAsObject implements PdfAs if (enableSearch) { spd = SignaturePlaceholderExtractor.extract( - signParameters.getDocument().createInputStream(), - signParameters.getPlaceholderId(), + signParameters.getDocument().createInputStream(), + signParameters.getPlaceholderId(), signParameters.getPlaceholderMatchMode()); } return spd; @@ -809,15 +991,36 @@ public class PdfAsObject implements PdfAs { signatorId = SignatorFactory.MOST_RECENT_DETACHEDTEXT_SIGNATOR_ID; } - + return at.gv.egiz.pdfas.framework.SignatorFactory.createSignator(signatorId); } - public SignResult sign(SignParameters signParameters, SignatureDetailInformation signatorInfo) + public SignResult sign(SignParameters signParameters, SignatureDetailInformation signatorInfo) + throws PdfAsException { + // prepare log data + StatisticData sd = new StatisticData(signParameters); + StopWatch sw = new StopWatch(); + try { + sw.start(); + return performSign(signParameters, signatorInfo); + } catch (PdfAsException e) { + sd.setException(e); + throw e; + } catch (RuntimeException e) { + sd.setException(e); + throw e; + } finally { + sw.stop(); + sd.setDuration(sw.getTime()); + statLog.log(sd); + } + } + + private SignResult performSign(SignParameters signParameters, SignatureDetailInformation signatorInfo) throws PdfAsException { CheckHelper.checkSignParametersForSignAfterPrepare(signParameters, false); - + if (signParameters.getProfileOverrideProperties() != null) { OverridePropertyHolder.setOverrideProps(signParameters.getProfileOverrideProperties()); } @@ -832,34 +1035,34 @@ public class PdfAsObject implements PdfAs SignatureData sd = new SignatureDataImpl(new PdfDataSourceAdapter(signatorInfo.getSignatureData()), signatorInfo.getSignatureData().getMimeType()); SignSignatureObject sso = PdfAS.sign(sd, c, signParameters.getTimeStamperImpl()); ((SignatureDetailInformationImpl)signatorInfo).setSignSignatureObject(sso); - + return finishSign(signParameters, signatorInfo); } - public SignResult finishSign(SignParameters signParameters, SignatureDetailInformation signatureDetailInformation) + public SignResult finishSign(SignParameters signParameters, SignatureDetailInformation signatureDetailInformation) throws PdfAsException { try { CheckHelper.checkSignParametersForSignAfterPrepare(signParameters, true); CheckHelper.checkSignatureDetailInformation(signatureDetailInformation); - + if (signParameters.getProfileOverrideProperties() != null) { OverridePropertyHolder.setOverrideProps(signParameters.getProfileOverrideProperties()); } - + Signator signator = createSignator(signParameters.getSignatureType()); SignatorInformation signatorInfo = ((SignatureDetailInformationImpl)signatureDetailInformation).getSignatorInfo(); signator.finishSign(signatorInfo, new DataSinkAdapter(signParameters.getOutput())); return new SignResultImpl( - signParameters.getOutput(), + signParameters.getOutput(), signatorInfo.getSignSignatureObject().getX509Certificate(), - new ActualSignaturePositionAdapter(signatorInfo.getActualTablePos()), + new ActualSignaturePositionAdapter(signatorInfo.getActualTablePos()), signatorInfo.getNonTextualObjects()); } finally { OverridePropertyHolder.removeProperties(); DynamicSignatureProfileImpl.disposeLocalProfile(); } } - + } diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/DataSinkAdapter.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/DataSinkAdapter.java index 2aee44f..b91d5a9 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/DataSinkAdapter.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/DataSinkAdapter.java @@ -30,7 +30,7 @@ import at.gv.egiz.pdfas.api.io.DataSink; /** * Adapter that converts an API DataSink to a framework DataSink. - * + * * @author wprinz */ public class DataSinkAdapter implements at.gv.egiz.pdfas.framework.output.DataSink @@ -42,7 +42,7 @@ public class DataSinkAdapter implements at.gv.egiz.pdfas.framework.output.DataSi /** * Constructor. - * + * * @param apiDataSink * The API DataSink to be adapted to a framework DataSink. */ @@ -62,7 +62,6 @@ public class DataSinkAdapter implements at.gv.egiz.pdfas.framework.output.DataSi } catch (IOException e) { - e.printStackTrace(); throw new RuntimeException(e); } } @@ -79,7 +78,6 @@ public class DataSinkAdapter implements at.gv.egiz.pdfas.framework.output.DataSi } catch (IOException e) { - e.printStackTrace(); throw new RuntimeException(e); } } diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/SignatureProfileImpl.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/SignatureProfileImpl.java index 35d8c17..1df1a65 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/SignatureProfileImpl.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/api/commons/SignatureProfileImpl.java @@ -28,6 +28,7 @@ import java.util.Properties; import org.apache.commons.lang.builder.ToStringBuilder; import at.gv.egiz.pdfas.api.commons.SignatureProfile; +import at.knowcenter.wag.egov.egiz.sig.SignatureTypes.State; /** * Holds the data of a signature profile. @@ -61,6 +62,13 @@ public class SignatureProfileImpl implements SignatureProfile { * true if this is the default profile, false otherwise. */ protected boolean defaultProfile = false; + + /** + * The state of the signature profile. Signature profiles may be disabled (OFF), allowed for signature only + * (SIGN_ONLY), allowed for verification only (VERIFY_ONLY) or just enabled (ON). + * Default value here of ON in order to assure backward compatibility. + */ + private State state = State.ON; /** * Constructor. @@ -88,13 +96,25 @@ public class SignatureProfileImpl implements SignatureProfile { * @param isDefault */ public SignatureProfileImpl(String profileId, String profileDescription, String moaKeyIdentifier, boolean isDefault) { - this.profileId = profileId; - this.moaKeyIdentifier = moaKeyIdentifier; - this.profileDescription = profileDescription; - this.signatureBlockEntries = new Properties(); - this.defaultProfile = isDefault; + this(profileId, moaKeyIdentifier); + this.profileDescription = profileDescription; + this.defaultProfile = isDefault; } + /** + * Creates a new signature profile instance. + * @param profileId The profile identifier. + * @param state The profile's state. + * @param profileDescription The profile description. + * @param moaKeyIdentifier The MOA-SS key identifier. + * @param isDefault {@code true} if this is a default profile, {@code false} if not. + */ + public SignatureProfileImpl(String profileId, State state, String profileDescription, String moaKeyIdentifier, boolean isDefault) { + this(profileId, profileDescription, moaKeyIdentifier, isDefault); + this.state = state; + } + + /** * @see at.gv.egiz.pdfas.api.commons.SignatureProfile#getProfileId() */ @@ -140,19 +160,22 @@ public class SignatureProfileImpl implements SignatureProfile { return this.profileDescription; } - public String toString() { - return new ToStringBuilder(this) - .append("profileId", this.profileId) - .append("profileDescription", this.profileDescription) - .append("moaKeyIdentifier", this.moaKeyIdentifier) - .toString(); - } + @Override + public String toString() { + return "SignatureProfileImpl [profileId=" + profileId + ", state=" + state + ", profileDescription=" + + profileDescription + ", moaKeyIdentifier=" + moaKeyIdentifier + ", defaultProfile=" + defaultProfile + + "]"; + } - /** +/** * */ public boolean isDefault() { return this.defaultProfile; } + public State getState() { + return state; + } + } diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/correction/InternalCorrector.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/correction/InternalCorrector.java index eaa6b7f..b193936 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/correction/InternalCorrector.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/input/correction/InternalCorrector.java @@ -26,6 +26,7 @@ package at.gv.egiz.pdfas.impl.input.correction; import java.io.ByteArrayOutputStream; import java.io.IOException; +import at.gv.egiz.pdfas.api.io.DataSource; import at.gv.egiz.pdfas.exceptions.ErrorCode; import at.gv.egiz.pdfas.exceptions.framework.CorrectorException; import at.gv.egiz.pdfas.framework.input.PdfDataSource; @@ -40,7 +41,7 @@ import com.lowagie.text.pdf.PdfStamper; /** * Corrects a document using iText. - * + * * @author wprinz */ public class InternalCorrector implements Corrector @@ -53,11 +54,9 @@ public class InternalCorrector implements Corrector { try { - byte[] pdf = document.getAsByteArray(); - PdfReader reader = new PdfReader(pdf); - PDFASUtils.checkReaderPermissions(reader); + PdfReader reader = PDFASUtils.createPdfReaderCheckingPermissions(document); - ByteArrayOutputStream baos = new ByteArrayOutputStream(pdf.length); + ByteArrayOutputStream baos = new ByteArrayOutputStream(document.getLength()); PdfStamper stamper = new PdfStamper(reader, baos, '\0', false); stamper.close(); diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/binary/BinarySignator_1_0_0.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/binary/BinarySignator_1_0_0.java index 0af6538..a3ff856 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/binary/BinarySignator_1_0_0.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/binary/BinarySignator_1_0_0.java @@ -83,7 +83,7 @@ import com.lowagie.text.pdf.PdfPTable; /** * Signs the document binary. - * + * *

* In prepareSign, an Incremental Update is created that contains the Signature block and the egiz dictionary. For * formatting the layout, variable values are filled with placeholders. After the layout has been fixed, all variable @@ -92,7 +92,7 @@ import com.lowagie.text.pdf.PdfPTable; *

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

- * + * * @author wprinz */ public class BinarySignator_1_0_0 implements Signator { @@ -204,13 +204,19 @@ public class BinarySignator_1_0_0 implements Signator { // on a new page, prevent pdf-as to do that, because why should make // a new page just for an invisible block // added by rpiazzi + + // disabled by dti: code fixes certain cases with invisible signatures but prevents usage of minimal + // signature profiles; the actual invisible signature issue has fixed in method + // adjustSignatureTableandCalculatePosition(...) in class at.knowcenter.wag.egov.egiz.PdfAS + /* if (signature_object.getSignatureTypeDefinition().getInvisibleFieldDefinitions().size() == SignatureTypes.REQUIRED_SIG_KEYS.length) { if (pi.isMakeNewPage()) { int pageNumber = pi.getPage(); pi = new PositioningInstruction(false, pageNumber - 1, 0, 0); } } - // end added + */ + // end added (rpiazzi) IncrementalUpdateInformation iui = IncrementalUpdateHelper.writeIncrementalUpdate(pdfDataSource, pdf_table, profile, pi, variable_field_definitions, all_field_definitions, invisible_field_definitions, @@ -318,7 +324,7 @@ public class BinarySignator_1_0_0 implements Signator { /** * Reads the signature values from the signed signature object and fills the corresponding value in the Replaces * array. - * + * * @param iui * The IncrementalUpdateInformation. */ @@ -394,7 +400,7 @@ public class BinarySignator_1_0_0 implements Signator { /** * Forms the SignatureData to be used for signing. - * + * * @param iui * The IncrementalUpdateInformation. * @return Returns the SignatureData to be used for signing. diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/detached/DetachedTextualSignator_1_0_0.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/detached/DetachedTextualSignator_1_0_0.java index 7fcdb2a..16e2718 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/detached/DetachedTextualSignator_1_0_0.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/signator/detached/DetachedTextualSignator_1_0_0.java @@ -41,7 +41,7 @@ import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUPostConnection; /** * Signs a document textually. - * + * *

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

@@ -49,7 +49,7 @@ import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUPostConnection; * In finishSign, the signed SignatureObject is transformed into a Signature * block, which is then written as an Incremental Update. *

- * + * * @author wprinz */ public class DetachedTextualSignator_1_0_0 extends TextualSignator_1_0_0 @@ -93,7 +93,7 @@ public class DetachedTextualSignator_1_0_0 extends TextualSignator_1_0_0 // String document_text = // PdfAS.extractNormalizedTextTextual(pdf.createInputStream()); // // logger_.debug("signed_text = " + document_text); - // + // // DataSource ds = new TextDataSourceImpl(document_text); // iui.signature_data = new SignatureDataImpl(ds, MIME_TYPE, "UTF-8"); // //$NON-NLS-1$ //$NON-NLS-2$ @@ -119,7 +119,6 @@ public class DetachedTextualSignator_1_0_0 extends TextualSignator_1_0_0 // } // catch (UnsupportedEncodingException e) // { - // e.printStackTrace(); // throw new PDFDocumentException(300, e); // } // } diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/VerificationFilterImpl.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/VerificationFilterImpl.java index 3f0f482..0e0da78 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/VerificationFilterImpl.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/VerificationFilterImpl.java @@ -80,7 +80,7 @@ public class VerificationFilterImpl implements VerificationFilter public static final String SUPRESS_EXCEPTION_WHEN_LAST_UIBLOCK_IS_NO_SIGNATURE = "supress_exception_when_last_iublock_is_no_signature"; public static final String BINARY_ONLY = "binary_only"; public static final String ASSUME_ONLY_SIGNATURE_BLOCKS = "assume_only_signature_blocks"; - + /** * @see at.gv.egiz.pdfas.framework.vfilter.VerificationFilter#extractSignatureHolders(at.gv.egiz.pdfas.framework.input.PdfDataSource, * java.util.List, @@ -97,7 +97,7 @@ public class VerificationFilterImpl implements VerificationFilter log.debug("Original IU blocks: " + blocks.size()); debugIUBlocks(blocks); } - + unrollLinearization(blocks); if (log.isDebugEnabled()) @@ -106,7 +106,7 @@ public class VerificationFilterImpl implements VerificationFilter debugIUBlocks(blocks); } - + SettingsReader settings; try { settings = SettingsReader.getInstance(); @@ -115,7 +115,7 @@ public class VerificationFilterImpl implements VerificationFilter } String check_doc = settings.getSetting(CHECK_DOCUMENT, "false"); - // check document for textual sigs here here if binary_only is set + // check document for textual sigs here here if binary_only is set if ("true".equalsIgnoreCase(check_doc) && parameters.extractBinarySignaturesOnly()) { @@ -125,7 +125,7 @@ public class VerificationFilterImpl implements VerificationFilter log.debug("Skipping checkDocument for textual sigs."); } // end add - + List signatureHolderChain = null; if (parameters.extractBinarySignaturesOnly()) @@ -156,11 +156,11 @@ public class VerificationFilterImpl implements VerificationFilter } } - + log.trace("extractSignaturHolders finished (" + (signatureHolderChain != null ? signatureHolderChain.size() : 0) + " elements)."); sw.stop(); log.debug("extractSignatureHolders: " + sw.getTime() + "ms."); - + return signatureHolderChain; } @@ -194,12 +194,12 @@ public class VerificationFilterImpl implements VerificationFilter foundSignatures = extractNewSignaturesFromText(normalizedText); } - + List textOnlySignatures = filterOutBinarySignatures(foundSignatures); - + return textOnlySignatures; } - + protected String normalizeText(String freetext) throws VerificationFilterException { try @@ -214,7 +214,7 @@ public class VerificationFilterImpl implements VerificationFilter /** * Removes the linearization footer from the list of update blocks. - * + * * @param blocks * The list of FooterParseResult objects in \prev order. */ @@ -263,15 +263,15 @@ public class VerificationFilterImpl implements VerificationFilter if (sao.oldSignature != null) { extractedSignatures.add(0, sao.oldSignature); - } + } } else { log.debug("extracting signatures from last partition..."); extractedSignatures = extractSignaturesFromPartition(pdf, lastTextPartition); } - - + + List signatureHolderChain = intermingleSignatures(binarySignatures, extractedSignatures); return signatureHolderChain; @@ -287,15 +287,15 @@ public class VerificationFilterImpl implements VerificationFilter Set binarySigValues = new HashSet(); Iterator iterator = binarySignatures.iterator(); while(iterator.hasNext()) { - + SignatureHolder sh = (SignatureHolder)iterator.next(); - + String sigVal = sh.getSignatureObject().getSignationValue(); binarySigValues.add(sigVal); } - + SignatureHolder oldSignature = null; - + //List originalPartitions = partitions; // This gives every IU block an own text partition // This allows text signatures to be found correctly if there are @@ -313,36 +313,36 @@ public class VerificationFilterImpl implements VerificationFilter } String check_doc = settings.getSetting(CHECK_DOCUMENT, "false"); boolean supressException = "true".equalsIgnoreCase(settings.getSetting(SUPRESS_EXCEPTION_WHEN_LAST_UIBLOCK_IS_NO_SIGNATURE, "false")); - + // flag indicating that the last IU-block of the document is a non-signature IU-block boolean lastBlockWasModified = false; - + // counter of all signatures (textual and binary) of this document int signatureCounter = 0; - + // counter of all textual signatures in this document int txtSigsSoFar = 0; - + // counter of all textual signatures in the current partition int txtSigsThisPartition = 0; - + List partitionResults = new ArrayList(partitions.size()); - List nshList = new ArrayList(); - + List nshList = new ArrayList(); + boolean sigFound = false; - + for (int i = 0; i < partitions.size(); i++) { Partition p = (Partition) partitions.get(i); - + // updating flag and counter boolean partitionContainsNewTextSignatures = true; txtSigsSoFar = txtSigsThisPartition; - + if (p instanceof TextPartition) { TextPartition tp = (TextPartition) p; - + List partitionResult = null; boolean scanThisPartitionForOldSignature = (i == 0) && scanForOldSignatures; @@ -356,34 +356,34 @@ public class VerificationFilterImpl implements VerificationFilter { partitionResult = extractSignaturesFromPartition(pdf, tp); } - - // binary signature blocks that have been detected as well are identified by comparing their signature values + + // binary signature blocks that have been detected as well are identified by comparing their signature values // with those stored in our Set above and are not considered for our IU-check List onlyTextSignatures = new ArrayList(); Iterator iter = partitionResult.iterator(); while(iter.hasNext()) { - + SignatureHolder sh = (SignatureHolder)iter.next(); if(!binarySigValues.contains(sh.getSignatureObject().getSignationValue())) { - + onlyTextSignatures.add(sh); } } - + // update signature counters txtSigsThisPartition = onlyTextSignatures.size(); int newTextSignatures = txtSigsThisPartition - txtSigsSoFar; signatureCounter = signatureCounter + newTextSignatures; - + // update sigFound flag if(txtSigsThisPartition > 0) { - + sigFound = true; } - + // TextPartition is only valid, if at least one more text signature has been found than in the previous text partition if(!(newTextSignatures > 0)) { - + partitionContainsNewTextSignatures = false; } @@ -391,39 +391,39 @@ public class VerificationFilterImpl implements VerificationFilter } else { // should be binary partition if(p instanceof BinaryPartition) { - + BinaryPartition binpart = (BinaryPartition)p; // updating counter and flag signatureCounter = signatureCounter + binpart.blocks.size(); sigFound = true; - + } } - + // if document checking is enabled, at least one signature has been found so far, we are dealing with a // non-signature IU-block if ((check_doc.equalsIgnoreCase("true"))&& (sigFound && !partitionContainsNewTextSignatures)) { - - nshList.add(new NoSignatureHolder(signatureCounter)); + + nshList.add(new NoSignatureHolder(signatureCounter)); lastBlockWasModified = true; - + } else { - + lastBlockWasModified = false; } - + } // throw an exception if the last update block does not contain a signature and signatures have been found in this document if (lastBlockWasModified) { if (!supressException) { - throw new VerificationFilterException(ErrorCode.MODIFIED_AFTER_SIGNATION, "The document has been modified after being signed."); + throw new VerificationFilterException(ErrorCode.MODIFIED_AFTER_SIGNATION, "The document has been modified after being signed."); } else { log.debug("The document has been modified after being signed. According to the configuration, no exception is thrown."); } } - + List extractedSignatures = new ArrayList(); Iterator it = partitionResults.iterator(); List prevPartitionResult = null; @@ -451,54 +451,54 @@ public class VerificationFilterImpl implements VerificationFilter } List signatureHolderChain = intermingleSignatures(binarySignatures, extractedSignatures); - + if (oldSignature != null) { signatureHolderChain.add(0, oldSignature); } - + // add the created NoSignatureHolders signatureHolderChain.addAll(nshList); - + return signatureHolderChain; } - + private void mergeSignatures(List oldList, List newList, List result) { - + for(int i=0; i < newList.size(); i++) { - + SignatureHolder currentNewSh = (SignatureHolder)newList.get(i); - + boolean shAlreadyPresentInOldList = false; int pos = -1; - + for(int j=0; j add result.add(currentNewSh); } - + } - - + + return; } - - + + protected List flattenOutTextPartitions (List partitions, List blocks) { - + List blockPartitions = new ArrayList(blocks.size()); Iterator it = partitions.iterator(); while (it.hasNext()) @@ -523,10 +523,10 @@ public class VerificationFilterImpl implements VerificationFilter blockPartitions.add(p); } } - + // note: successive binary blocks are still combined to one binary partition assert blockPartitions.size() <= blocks.size(); - + return blockPartitions; } @@ -536,15 +536,15 @@ public class VerificationFilterImpl implements VerificationFilter protected String extractText(PdfDataSource pdf, int endOfDocument, String encoding) throws PresentableException { - + log.debug("EXTRACTING TEXT (" + encoding + ")... end index = " + endOfDocument); - + DelimitedPdfDataSource dds = new DelimitedPdfDataSource(pdf, endOfDocument); //DelimitedInputStream dis = new DelimitedInputStream(pdf.createInputStream(), endOfDocument); return PdfAS.extractNormalizedTextTextual(dds, encoding); } - - + + protected List extractNewSignaturesFromText(String text) throws VerificationFilterException { try @@ -556,7 +556,7 @@ public class VerificationFilterImpl implements VerificationFilter throw new VerificationFilterException(e); } } - + protected List extractNewAndOldSignaturesFromText(String text) throws VerificationFilterException { SignaturesAndOld sao = extractSignaturesAndOld(text); @@ -651,11 +651,11 @@ public class VerificationFilterImpl implements VerificationFilter /** * Extracts the binary singatures from the given PDF. - * + * *

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

- * + * * @param pdf * @param blocks * @return Returns the List of signature holders. @@ -673,7 +673,7 @@ public class VerificationFilterImpl implements VerificationFilter String binary_only = settings.getSetting(BINARY_ONLY, "false"); String assume_sigs_only = settings.getSetting(ASSUME_ONLY_SIGNATURE_BLOCKS, "false"); boolean supressException = "true".equalsIgnoreCase(settings.getSetting(SUPRESS_EXCEPTION_WHEN_LAST_UIBLOCK_IS_NO_SIGNATURE, "false")); - + try { // PERF: extract binary signatures needs byte array @@ -689,15 +689,15 @@ public class VerificationFilterImpl implements VerificationFilter FooterParseResult fpr = (FooterParseResult) it.next(); assert fpr.next_index > prev_end; - if (VerificationFilterBinaryHelper.containsEGIZDict(data, fpr)) + PdfASID kz = null; + if (VerificationFilterBinaryHelper.containsEGIZDict(data, fpr) && + (kz = VerificationFilterBinaryHelper.extractKZFromEGIZBlock(data, fpr)) != null) { - PdfASID kz = VerificationFilterBinaryHelper.extractKZFromEGIZBlock(data, fpr); - // TODO dferbas hack baik test //kz = new PdfASID("urn:pdfsigfilter:bka.gv.at:binaer:v1.1.0"); - + Verificator verificator = VerificatorFactory.createBinaryVerificator(kz); - List binary_holders = verificator.parseBlock(pdf, data, fpr, prev_end); + List binary_holders = verificator.parseBlock(pdf, data, fpr, prev_end); binarySignatures.addAll(binary_holders); if(binary_holders.size() > 0) { @@ -707,21 +707,21 @@ public class VerificationFilterImpl implements VerificationFilter // an Exception is thrown here if: // 1) check_document is activated // 2) assume_only_signature_blocks is false - otherwise we permit updates - // 3) binary_only is true - otherwise updates are handled in method performFullConservative(). - // when binary-only is true, we can be sure that a block that contains no egiz-dict is no textual + // 3) binary_only is true - otherwise updates are handled in method performFullConservative(). + // when binary-only is true, we can be sure that a block that contains no egiz-dict is no textual // signature either but an illegal update, otherwise an Exception (doc contains textual sig) would have been thrown before // 4) a binary signature has been detected in a previous block - if(check_doc.equalsIgnoreCase("true") && + if(check_doc.equalsIgnoreCase("true") && binary_only.equalsIgnoreCase("true") && assume_sigs_only.equalsIgnoreCase("false") && - sig_detected) { - + sig_detected) { + if (!supressException) { - throw new VerificationFilterException(ErrorCode.MODIFIED_AFTER_SIGNATION, "The document has been modified after being signed."); + throw new VerificationFilterException(ErrorCode.MODIFIED_AFTER_SIGNATION, "The document has been modified after being signed."); } else { log.debug("The document has been modified after being signed. According to the configuration, no exception is thrown."); } - + } } @@ -749,7 +749,7 @@ public class VerificationFilterImpl implements VerificationFilter List extractedSignatures = extractNewSignaturesFromText(extractedText); log.debug("Extracting signatures finished."); log.debug("Number of found signatures: " + extractedSignatures.size()); - + if (extractedSignatures.size() > 0) { List cp1252SignaturesPositions = new ArrayList(); //boolean iscp1252Sig = false; @@ -760,19 +760,19 @@ public class VerificationFilterImpl implements VerificationFilter log.debug("found cp1252 signature"); cp1252SignaturesPositions.add(new Integer(i)); //iscp1252Sig = true; - //break; + //break; } - } + } if (cp1252SignaturesPositions.size() > 0) { log.debug("redo text and signature extraction with cp1252 encoding"); extractedText = extractText(pdf, endOfDocument, "cp1252"); log.debug("Extracting text finished."); - + log.debug("Extracting signatures:"); List cp1252ExtractedSignatures = extractNewSignaturesFromText(extractedText); log.debug("Extracting signatures finished."); log.debug("Number of found signatures: " + extractedSignatures.size()); - + if (cp1252ExtractedSignatures.size() != extractedSignatures.size()) { log.error("Invalid cp1252 signatures found. Skipping cp1252 compatibility."); } @@ -780,12 +780,12 @@ public class VerificationFilterImpl implements VerificationFilter for (int i = 0; i < cp1252SignaturesPositions.size(); i++) { int replaceIndex = ((Integer)cp1252SignaturesPositions.get(i)).intValue(); extractedSignatures.remove(replaceIndex); - extractedSignatures.add(replaceIndex, cp1252ExtractedSignatures.get(replaceIndex)); + extractedSignatures.add(replaceIndex, cp1252ExtractedSignatures.get(replaceIndex)); } } - + } - + if (log.isDebugEnabled()) { log.debug("extracted signatures:"); @@ -856,7 +856,7 @@ public class VerificationFilterImpl implements VerificationFilter } protected void checkBinaryOnly(PdfDataSource pdf, boolean considerOldSigs) throws VerificationFilterException { - + DelimitedPdfDataSource dds = new DelimitedPdfDataSource(pdf, pdf.getLength()); String text = null; try { @@ -864,10 +864,10 @@ public class VerificationFilterImpl implements VerificationFilter } catch (PresentableException e) { throw new VerificationFilterException(e); } - + List sigs = new ArrayList(); - - if(considerOldSigs) { + + if(considerOldSigs) { SignaturesAndOld sao = extractSignaturesAndOld(text); if(sao != null) { if(sao.newSignatures != null) { @@ -877,30 +877,30 @@ public class VerificationFilterImpl implements VerificationFilter sigs.add(sao.oldSignature); } } - } else { + } else { List signatures = extractSignatures(pdf, pdf.getLength()); if(signatures != null) { sigs.addAll(signatures); } } - + Iterator it = sigs.iterator(); while(it.hasNext()) { SignatureHolder current = (SignatureHolder)it.next(); if((current != null)&&(!current.getSignatureObject().isBinary())) { throw new VerificationFilterException(ErrorCode.NON_BINARY_SIGNATURES_PRESENT, "The document contains non-binary signatures."); } - } + } } - - + + protected static class SignaturesAndOld { public List newSignatures = null; public SignatureHolder oldSignature = null; } - + protected SignaturesAndOld extractSignaturesAndOld(String text) throws VerificationFilterException { try @@ -908,7 +908,7 @@ public class VerificationFilterImpl implements VerificationFilter log.debug("Extracting signatures:"); List extractedSignatures = extractNewSignaturesFromText(text); log.debug("Extracting signatures finished."); - + log.debug("Extracting old signatures:"); SignatureHolder oldSignature = extractOldSignature(text, extractedSignatures); log.debug("Extracting old signatures finished."); @@ -929,7 +929,7 @@ public class VerificationFilterImpl implements VerificationFilter /** * Extracts the old signature from the text, but only if it is older than the * oldest signature of the new signatueres. - * + * * @param extractedText * @param newSignatures * @return diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/helper/VerificationFilterBinaryHelper.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/helper/VerificationFilterBinaryHelper.java index 735b874..3093c36 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/helper/VerificationFilterBinaryHelper.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/impl/vfilter/helper/VerificationFilterBinaryHelper.java @@ -48,7 +48,7 @@ import at.knowcenter.wag.exactparser.parsing.results.ObjectParseResult; /** * Contains helpful methods used by the VerificationFilter to analyze the PDF for binary signatures. - * + * * @author wprinz */ public final class VerificationFilterBinaryHelper @@ -70,12 +70,12 @@ public final class VerificationFilterBinaryHelper /** * Tells, if the given incremental update block contains a binary signature. - * + * *

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

- * + * * @param block * The incremental update block. * @return Returns true, if this block is a binary signature block, false @@ -94,7 +94,7 @@ public final class VerificationFilterBinaryHelper /** * Extracts the PDF AS ID of the egiz block. - * + * * @param pdf * The pdf. * @param block @@ -120,6 +120,13 @@ public final class VerificationFilterBinaryHelper IndirectObjectReference ior = egiz_dict_iorpr.ior; final int egiz_dict_offset = PDFUtils.getObjectOffsetFromXRefByIndirectObjectReference(block.xpr, ior); + + // fix dti: + if (egiz_dict_offset < 0) { + log.debug("Current ui block contains a /EGIZSigDict trailer entry but no respective xref table entry. This indicates that this ui block does not contain binary signatures."); + return null; + } + // logger_.debug("egiz_dict_offset = " + egiz_dict_offset); ObjectParseResult obj = PDFUtils.parseObject(pdf, egiz_dict_offset); @@ -140,7 +147,7 @@ public final class VerificationFilterBinaryHelper /** * Restores the Kennzeichnung String from an Array. - * + * * @param pdf * The PDF. * @param kz_apr @@ -174,7 +181,7 @@ public final class VerificationFilterBinaryHelper si.pdf = pdf; log.trace("Adding KZ: " + si.toString()); - + partition.add(si); } -- cgit v1.2.3