/**
*
*/
package at.gv.egiz.pdfas.impl.api;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Vector;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import at.gv.egiz.pdfas.api.PdfAs;
import at.gv.egiz.pdfas.api.analyze.AnalyzeParameters;
import at.gv.egiz.pdfas.api.analyze.AnalyzeResult;
import at.gv.egiz.pdfas.api.commons.Constants;
import at.gv.egiz.pdfas.api.commons.DynamicSignatureLifetimeEnum;
import at.gv.egiz.pdfas.api.commons.DynamicSignatureProfile;
import at.gv.egiz.pdfas.api.commons.DynamicSignatureProfileImpl;
import at.gv.egiz.pdfas.api.commons.SignatureInformation;
import at.gv.egiz.pdfas.api.exceptions.PdfAsException;
import at.gv.egiz.pdfas.api.sign.SignParameters;
import at.gv.egiz.pdfas.api.sign.SignResult;
import at.gv.egiz.pdfas.api.sign.SignatureDetailInformation;
import at.gv.egiz.pdfas.api.verify.VerifyAfterAnalysisParameters;
import at.gv.egiz.pdfas.api.verify.VerifyAfterReconstructXMLDsigParameters;
import at.gv.egiz.pdfas.api.verify.VerifyParameters;
import at.gv.egiz.pdfas.api.verify.VerifyResult;
import at.gv.egiz.pdfas.api.verify.VerifyResults;
import at.gv.egiz.pdfas.api.xmldsig.ExtendedSignatureInformation;
import at.gv.egiz.pdfas.api.xmldsig.ReconstructXMLDsigAfterAnalysisParameters;
import at.gv.egiz.pdfas.api.xmldsig.ReconstructXMLDsigParameters;
import at.gv.egiz.pdfas.api.xmldsig.ReconstructXMLDsigResult;
import at.gv.egiz.pdfas.api.xmldsig.XMLDsigData;
import at.gv.egiz.pdfas.commandline.CommandlineConnectorChooser;
import at.gv.egiz.pdfas.exceptions.ErrorCode;
import at.gv.egiz.pdfas.exceptions.framework.PlaceholderExtractionException;
import at.gv.egiz.pdfas.framework.ConnectorParameters;
import at.gv.egiz.pdfas.framework.DataSourceHolder;
import at.gv.egiz.pdfas.framework.config.SettingsHelper;
import at.gv.egiz.pdfas.framework.input.ExtractionStage;
import at.gv.egiz.pdfas.framework.input.PdfDataSource;
import at.gv.egiz.pdfas.framework.signator.Signator;
import at.gv.egiz.pdfas.framework.signator.SignatorInformation;
import at.gv.egiz.pdfas.framework.vfilter.VerificationFilterParameters;
import at.gv.egiz.pdfas.impl.api.analyze.AnalyzeResultImpl;
import at.gv.egiz.pdfas.impl.api.commons.DataSinkAdapter;
import at.gv.egiz.pdfas.impl.api.commons.PdfDataSourceAdapter;
import at.gv.egiz.pdfas.impl.api.commons.SignatureInformationAdapter;
import at.gv.egiz.pdfas.impl.api.commons.SignatureProfileImpl;
import at.gv.egiz.pdfas.impl.api.commons.TextDataSourceAdapter;
import at.gv.egiz.pdfas.impl.api.sign.ActualSignaturePositionAdapter;
import at.gv.egiz.pdfas.impl.api.sign.SignResultImpl;
import at.gv.egiz.pdfas.impl.api.sign.SignatureDetailInformationImpl;
import at.gv.egiz.pdfas.impl.api.verify.VerifyResultAdapter;
import at.gv.egiz.pdfas.impl.api.verify.VerifyResultsImpl;
import at.gv.egiz.pdfas.impl.input.DelimitedPdfDataSource;
import at.gv.egiz.pdfas.impl.vfilter.VerificationFilterParametersImpl;
import at.gv.egiz.pdfas.impl.xmldsig.XMLDsigReconstructor;
import at.gv.egiz.pdfas.placeholder.SignaturePlaceholderContext;
import at.gv.egiz.pdfas.placeholder.SignaturePlaceholderData;
import at.gv.egiz.pdfas.placeholder.SignaturePlaceholderExtractor;
import at.gv.egiz.pdfas.utils.ConfigUtils;
import at.knowcenter.wag.egov.egiz.PdfAS;
import at.knowcenter.wag.egov.egiz.PdfASID;
import at.knowcenter.wag.egov.egiz.cfg.OverridePropertyHolder;
import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
import at.knowcenter.wag.egov.egiz.exceptions.OutOfMemoryException;
import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException;
import at.knowcenter.wag.egov.egiz.exceptions.PresentableException;
import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
import at.knowcenter.wag.egov.egiz.exceptions.SignatorFactoryException;
import at.knowcenter.wag.egov.egiz.exceptions.SignatureException;
import at.knowcenter.wag.egov.egiz.framework.SignatorFactory;
import at.knowcenter.wag.egov.egiz.pdf.AdobeSignatureHelper;
import at.knowcenter.wag.egov.egiz.pdf.BinarySignatureHolder;
import at.knowcenter.wag.egov.egiz.pdf.NoSignatureHolder;
import at.knowcenter.wag.egov.egiz.pdf.ObjectExtractor;
import at.knowcenter.wag.egov.egiz.pdf.SignatureHolder;
import at.knowcenter.wag.egov.egiz.pdf.TablePos;
import at.knowcenter.wag.egov.egiz.pdf.TextualSignatureHolder;
import at.knowcenter.wag.egov.egiz.sig.SignatureData;
import at.knowcenter.wag.egov.egiz.sig.SignatureDataImpl;
import at.knowcenter.wag.egov.egiz.sig.SignatureResponse;
import at.knowcenter.wag.egov.egiz.sig.SignatureTypeDefinition;
import at.knowcenter.wag.egov.egiz.sig.SignatureTypes;
import at.knowcenter.wag.egov.egiz.sig.connectors.Connector;
import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject;
/**
* Implementation of the {@link PdfAs} interface.
*
* @author wprinz
*/
public class PdfAsObject implements PdfAs
{
//23.11.2010 changed by exthex - added methods for reconstructXMLDsig
/**
* The log.
*/
private static Log log = LogFactory.getLog(PdfAsObject.class);
private static final String ENABLE_PLACEHOLDER_SEARCH_KEY = "enable_placeholder_search";
/**
* Configuration key for minimal signature block width threshold. Any width below this certain value will lead to a warning log entry."
*/
private static final String SIGNATURE_BLOCK_WIDTH_THRESHOLD_FOR_WARNING_KEY = "signature_block_width_warning_threshold";
/**
* Minimal signature block width. If a width below that value is defined (by parameter, by placeholder or by configuration) a warning log entry is created.
*/
public static final float DEFAULT_SIGNATURE_BLOCK_WIDTH_THRESHOLD = 150;
/**
* This constructor is for internal use only - use
* {@link at.gv.egiz.pdfas.PdfAsFactory} instead.
* Note: IAIK JCE and IAIK ECC security providers are automatically registered.
*
* @param workDirectory
* The work directory.
* @throws PdfAsException
* Thrown, if the configuration cannot be processed.
*/
public PdfAsObject(File workDirectory) throws PdfAsException
{
this(workDirectory, SettingsReader.REGISTER_IAIK_PROVIDERS_ON_DEFAULT);
}
/**
* This constructor is for internal use only - use
* {@link at.gv.egiz.pdfas.PdfAsFactory} instead.
*
* @param workDirectory
* The work directory.
* @param registerProvider true
: automatically registers IAIK JCE and ECC Provider;
* false
: providers will NOT be automatically registered, providers
* needed have to be registered by the API user
* @throws PdfAsException
* Thrown, if the configuration cannot be processed.
*/
public PdfAsObject(File workDirectory, boolean registerProvider) throws PdfAsException
{
String path = workDirectory != null ? workDirectory.getPath() : null;
SettingsReader.initialize(path, path);
reloadConfig(registerProvider);
}
/**
* This constructor is for internal use only - use
* {@link at.gv.egiz.pdfas.PdfAsFactory} instead.
* Note: IAIK JCE and IAIK ECC security providers are automatically registered.
*
* @throws PdfAsException
* Thrown, if the configuration cannot be processed.
*/
public PdfAsObject() throws PdfAsException
{
this(null);
}
/**
* @see at.gv.egiz.pdfas.api.PdfAs#reloadConfig()
*/
public void reloadConfig() throws PdfAsException
{
ConfigUtils.initializeLogger();
SettingsReader.createInstance();
SignatureTypes.createInstance();
}
/**
* @param registerProvider true
: automatically registers IAIK JCE and ECC Provider;
* false
: providers will NOT be automatically registered, providers
* needed have to be registered by the API user
* @see at.gv.egiz.pdfas.api.PdfAs#reloadConfig()
*/
private void reloadConfig(boolean registerProvider) throws PdfAsException
{
ConfigUtils.initializeLogger();
SettingsReader.createInstance(registerProvider);
SignatureTypes.createInstance();
}
/**
* @see at.gv.egiz.pdfas.api.PdfAs#getProfileInformation()
*/
public List getProfileInformation() throws PdfAsException
{
log.debug("Collecting profile information.");
final String MOA_SIGN_KEY_IDENTIFIER_KEY = "moa.sign.KeyIdentifier";
SettingsReader settings = SettingsReader.getInstance();
final String defaultMoaKeyIdentifiert = settings.getSetting(MOA_SIGN_KEY_IDENTIFIER_KEY, null);
SignatureTypes types = SignatureTypes.getInstance();
List profiles = types.getSignatureTypeDefinitions();
List profileInformation = new ArrayList(profiles.size());
String default_type = settings.getValueFromKey(SignatureTypes.DEFAULT_TYPE);
Iterator it = profiles.iterator();
while (it.hasNext())
{
SignatureTypeDefinition profile = (SignatureTypeDefinition) it.next();
final String profileId = profile.getType();
log.debug("Processing profile \"" + profileId + "\".");
final String moaKeyIdentifier = settings.getSetting("sig_obj." + profileId + "." + MOA_SIGN_KEY_IDENTIFIER_KEY, defaultMoaKeyIdentifiert);
final String profileDescription = settings.getSetting("sig_obj." + profileId + "." + SignatureTypes.SIG_DESCR, null);
boolean isDefault = (default_type != null && default_type.equals(profileId));
// modified by tknall
SignatureProfileImpl signatureProfile = new SignatureProfileImpl(profileId, profileDescription, moaKeyIdentifier, isDefault);
// start - added by tknall
// signature entries relevant to the search algorithm
Properties signatureEntries = new Properties();
// search for table entries
String parentPropertyKey = "sig_obj." + profileId + ".table";
log.debug("Looking for subkeys of \"" + parentPropertyKey + "\".");
Vector keysVector = settings.getSettingKeys(parentPropertyKey);
if (keysVector != null) {
Iterator keyIt = keysVector.iterator();
while (keyIt.hasNext()) {
String subKey = (String) keyIt.next();
if (subKey != null && subKey.length() > 0) {
String fullKey = parentPropertyKey + "." + subKey;
String value = settings.getValueFromKey(fullKey);
int lastIndex = fullKey.lastIndexOf(".");
if (lastIndex != -1) {
String endsWith = fullKey.substring(lastIndex + 1);
if (value != null && value.length() > 0) {
if (NumberUtils.isDigits(endsWith)) {
signatureEntries.setProperty(fullKey, value);
} else {
log.debug("Ignoring table entry \"" + fullKey + "\" because it does not end with a digit. Therefore it is not relevant for the seach algorithm.");
}
} else {
log.warn("Problem detected with key \"" + fullKey + "\". The value is empty.");
}
}
}
}
}
// search for table entries
parentPropertyKey = "sig_obj." + profileId + ".key";
log.debug("Looking for subkeys of \"" + parentPropertyKey + "\".");
keysVector = settings.getSettingKeys(parentPropertyKey);
if (keysVector != null) {
Iterator keyIt = keysVector.iterator();
while (keyIt.hasNext()) {
String subKey = (String) keyIt.next();
if (subKey != null && subKey.length() > 0) {
String fullKey = parentPropertyKey + "." + subKey;
String value = settings.getValueFromKey(fullKey);
if (value != null && value.length() > 0) {
signatureEntries.setProperty(fullKey, value);
} else {
log.warn("Problem detected with key \"" + fullKey + "\". The value is empty.");
}
}
}
}
// set properties
signatureProfile.setSignatureBlockEntries(signatureEntries);
// stop - added by tknall
profileInformation.add(signatureProfile);
}
return profileInformation;
}
/**
* @see at.gv.egiz.pdfas.api.PdfAs#sign(at.gv.egiz.pdfas.api.sign.SignParameters)
*/
public SignResult sign(SignParameters signParameters) throws PdfAsException
{
CheckHelper.checkSignParameters(signParameters, false);
try {
SignatureDetailInformation signatorInfo = prepareSign(signParameters);
return sign(signParameters, signatorInfo);
} catch (java.lang.OutOfMemoryError e) {
throw new OutOfMemoryException(ErrorCode.OUT_OF_MEMORY_ERROR, "Insufficient memory allocated to virtual machine. Start Java with parameters \"-Xms128m -Xmx786m -XX:MaxPermSize=256m\".", e);
}
}
/**
* @see at.gv.egiz.pdfas.api.PdfAs#verify(at.gv.egiz.pdfas.api.verify.VerifyParameters)
*/
public VerifyResults verify(VerifyParameters verifyParameters) throws PdfAsException
{
CheckHelper.checkVerifyParameters(verifyParameters);
AnalyzeParameters ap = new AnalyzeParameters();
fillAnalyzeParametersWithVerifyParameters(ap, verifyParameters);
AnalyzeResult analyzeResult = analyze(ap);
if (verifyParameters.getSignatureToVerify() != Constants.VERIFY_ALL)
{
if (verifyParameters.getSignatureToVerify() >= analyzeResult.getSignatures().size())
{
throw new SignatureException(312, "The selected signature to be verified doesn't exist. " + verifyParameters.getSignatureToVerify());
}
Object stv = analyzeResult.getSignatures().get(verifyParameters.getSignatureToVerify());
List selectedSignature = new ArrayList(1);
selectedSignature.add(stv);
analyzeResult = new AnalyzeResultImpl(selectedSignature);
}
VerifyAfterAnalysisParameters vaap = new VerifyAfterAnalysisParameters();
vaap.setAnalyzeResult(analyzeResult);
fillVerifyAfterAnalysisParametersWithVerifyParameters(vaap, verifyParameters);
VerifyResults res = verify(vaap);
return res;
}
/**
* Copies all adequate parameters from the {@link VerifyParameters} to the
* {@link AnalyzeParameters}.
*
* @param ap
* The {@link AnalyzeParameters}.
* @param vp
* The {@link VerifyParameters}.
*/
protected void fillAnalyzeParametersWithVerifyParameters(AnalyzeParameters ap, VerifyParameters vp)
{
ap.setDocument(vp.getDocument());
ap.setVerifyMode(vp.getVerifyMode());
ap.setReturnNonTextualObjects(vp.isReturnNonTextualObjects());
}
protected void fillAnalyzeParametersWithReconstructXMLDsigParameters(AnalyzeParameters ap, ReconstructXMLDsigParameters rxp)
{
ap.setDocument(rxp.getDocument());
ap.setVerifyMode(rxp.getVerifyMode());
ap.setReturnNonTextualObjects(rxp.isReturnNonTextualObjects());
}
/**
* Copies all adequate parameters from the {@link VerifyParameters} to the
* {@link VerifyAfterAnalysisParameters}.
*
* @param vaap
* The {@link VerifyAfterAnalysisParameters}.
* @param vp
* The {@link VerifyParameters}.
*/
protected void fillVerifyAfterAnalysisParametersWithVerifyParameters(VerifyAfterAnalysisParameters vaap, VerifyParameters vp)
{
vaap.setSignatureDevice(vp.getSignatureDevice());
vaap.setVerificationTime(vp.getVerificationTime());
vaap.setReturnHashInputData(vp.isReturnHashInputData());
}
protected void fillReconstructXMLDsigAfterAnalysisParametersWithVerifyAfterAnalysisParameters(
ReconstructXMLDsigAfterAnalysisParameters reconstructParams,
VerifyAfterAnalysisParameters verifyAfterAnalysisParameters) {
reconstructParams.setAnalyzeResult(verifyAfterAnalysisParameters.getAnalyzeResult());
reconstructParams.setSignatureDevice(verifyAfterAnalysisParameters.getSignatureDevice());
}
/**
* @see at.gv.egiz.pdfas.api.PdfAs#analyze(at.gv.egiz.pdfas.api.analyze.AnalyzeParameters)
*/
public AnalyzeResult analyze(AnalyzeParameters analyzeParameters) throws PdfAsException
{
CheckHelper.checkAnalyzeParameters(analyzeParameters);
VerificationFilterParameters parametersConfig = SettingsHelper.readVerificationFilterParametersFromSettings();
boolean binaryOnly = parametersConfig.extractBinarySignaturesOnly();
if (analyzeParameters.getVerifyMode().equals(Constants.VERIFY_MODE_BINARY_ONLY))
{
binaryOnly = true;
}
boolean assumeOnlySB = parametersConfig.assumeOnlySignatureUpdateBlocks();
if (analyzeParameters.getVerifyMode().equals(Constants.VERIFY_MODE_SEMI_CONSERVATIVE))
{
assumeOnlySB = true;
}
if (analyzeParameters.getVerifyMode().equals(Constants.VERIFY_MODE_FULL_CONSERVATIVE))
{
assumeOnlySB = false;
}
VerificationFilterParameters parameters = new VerificationFilterParametersImpl(binaryOnly, assumeOnlySB, parametersConfig.scanForOldSignatures());
at.gv.egiz.pdfas.framework.input.DataSource inputDataSource = null;
if (analyzeParameters.getDocument().getMimeType().equals("application/pdf"))
{
inputDataSource = new PdfDataSourceAdapter(analyzeParameters.getDocument());
}
else
{
try
{
inputDataSource = new TextDataSourceAdapter(analyzeParameters.getDocument());
}
catch (UnsupportedEncodingException e)
{
throw new PresentableException(ErrorCode.DOCUMENT_CANNOT_BE_READ, "The characterEncoding is not supported." + analyzeParameters.getDocument().getCharacterEncoding(), e);
}
}
assert inputDataSource != null;
try {
ExtractionStage es = new ExtractionStage();
DataSourceHolder dsh = new DataSourceHolder(inputDataSource);
List signature_holders = es.extractSignatureHolders(dsh, parameters);
// List sigInfs = new ArrayList(signature_holders.size());
List sigInfs = new ArrayList();
List noSigs = new ArrayList();
Iterator it = signature_holders.iterator();
while (it.hasNext())
{
SignatureHolder sh = (SignatureHolder)it.next();
if(sh instanceof NoSignatureHolder) {
noSigs.add(sh);
} else {
SignatureInformation si = new SignatureInformationAdapter(sh);
sigInfs.add(si);
if (analyzeParameters.isReturnNonTextualObjects()) {
si.setNonTextualObjects(doExtractNonTexualObjects(sh, (PdfDataSource) dsh.getDataSource()));
}
}
}
return new AnalyzeResultImpl(sigInfs, noSigs, parameters.hasBeenCorrected());
} catch (java.lang.OutOfMemoryError e) {
throw new OutOfMemoryException(ErrorCode.OUT_OF_MEMORY_ERROR, "Insufficient memory allocated to virtual machine. Start Java with parameters \"-Xms128m -Xmx786m -XX:MaxPermSize=256m\".", e);
}
}
private List doExtractNonTexualObjects(SignatureHolder sh, PdfDataSource pdfDataSource) {
if (sh == null) return null;
if (sh instanceof BinarySignatureHolder) {
BinarySignatureHolder bsh = (BinarySignatureHolder)sh;
return ObjectExtractor.extractNonTextInfo(bsh.getSignedPdf());
} else if (sh instanceof TextualSignatureHolder) {
TextualSignatureHolder tsh = (TextualSignatureHolder)sh;
if (tsh.getUiBlockEndPos() == 0) {
log.warn("uiblockendpos not available. Extract objects from final pdf document");
return ObjectExtractor.extractNonTextInfo(pdfDataSource);
}
DelimitedPdfDataSource dpds = new DelimitedPdfDataSource(pdfDataSource, tsh.getUiBlockEndPos());
return ObjectExtractor.extractNonTextInfo(dpds);
} else {
return null;
}
}
/**
* @see at.gv.egiz.pdfas.api.PdfAs#verify(at.gv.egiz.pdfas.api.verify.VerifyAfterAnalysisParameters)
*/
public VerifyResults verify(VerifyAfterAnalysisParameters verifyAfterAnalysisParameters) throws PdfAsException
{
CheckHelper.checkVerifyAfterAnalysisParameters(verifyAfterAnalysisParameters);
List signatures = verifyAfterAnalysisParameters.getAnalyzeResult().getSignatures();
// added by tknall
if (signatures == null || signatures.isEmpty()) {
throw new PDFDocumentException(ErrorCode.DOCUMENT_NOT_SIGNED, "PDF document not signed."); //$NON-NLS-1$
}
ReconstructXMLDsigAfterAnalysisParameters rxaap = new ReconstructXMLDsigAfterAnalysisParameters();
fillReconstructXMLDsigAfterAnalysisParametersWithVerifyAfterAnalysisParameters(rxaap, verifyAfterAnalysisParameters);
ReconstructXMLDsigResult reconstructResult = reconstructXMLDSIG(rxaap);
VerifyAfterReconstructXMLDsigParameters varxp = new VerifyAfterReconstructXMLDsigParameters();
fillVerifyAfterReconstructXMLDsigParametersWithVerifyAfterAnalysisParameters(varxp, verifyAfterAnalysisParameters);
varxp.setReconstructXMLDsigResult(reconstructResult);
return verify(varxp);
}
protected void fillVerifyAfterReconstructXMLDsigParametersWithVerifyAfterAnalysisParameters(
VerifyAfterReconstructXMLDsigParameters varxp,
VerifyAfterAnalysisParameters verifyAfterAnalysisParameters) {
varxp.setReturnHashInputData(verifyAfterAnalysisParameters.isReturnHashInputData());
varxp.setSignatureDevice(verifyAfterAnalysisParameters.getSignatureDevice());
varxp.setVerificationTime(verifyAfterAnalysisParameters.getVerificationTime());
varxp.setVerifySignatureIndex(verifyAfterAnalysisParameters.getVerifySignatureIndex());
}
/**
* @see PdfAs#reconstructXMLDSIG(ReconstructXMLDsigParameters)
*/
public ReconstructXMLDsigResult reconstructXMLDSIG(
ReconstructXMLDsigParameters reconstructXMLDsigParameters)
throws PdfAsException {
AnalyzeParameters analyzeParameters = new AnalyzeParameters();
fillAnalyzeParametersWithReconstructXMLDsigParameters(analyzeParameters, reconstructXMLDsigParameters);
AnalyzeResult ar = analyze(analyzeParameters);
ReconstructXMLDsigAfterAnalysisParameters rxaap = new ReconstructXMLDsigAfterAnalysisParameters();
rxaap.setSignatureDevice(reconstructXMLDsigParameters.getSignatureDevice());
rxaap.setAnalyzeResult(ar);
return reconstructXMLDSIG(rxaap);
}
/**
* @see PdfAs#reconstructXMLDSIG(ReconstructXMLDsigAfterAnalysisParameters)
*/
public ReconstructXMLDsigResult reconstructXMLDSIG(
ReconstructXMLDsigAfterAnalysisParameters reconstructXMLDsigParameters)
throws PdfAsException {
AnalyzeResult ar = reconstructXMLDsigParameters.getAnalyzeResult();
List extendedSignatureInfos = new Vector();
for (int i = 0; i < ar.getSignatures().size(); i++)
{
SignatureInformation si = (SignatureInformation)ar.getSignatures().get(i);
XMLDsigData dsigData;
try {
dsigData = XMLDsigReconstructor.reconstruct(si, reconstructXMLDsigParameters.getSignatureDevice());
extendedSignatureInfos.add(new ExtendedSignatureInformation(si, dsigData));
} catch (ConnectorException e) {
// don't care for connector exceptions because of mutli signs. they are handled during verify
extendedSignatureInfos.add(new ExtendedSignatureInformation(si, null));
}
}
return new ReconstructXMLDsigResult(extendedSignatureInfos, reconstructXMLDsigParameters.getSignatureDevice());
}
/**
* @see PdfAs#verify(VerifyAfterReconstructXMLDsigParameters)
*/
public VerifyResults verify(
VerifyAfterReconstructXMLDsigParameters verifyAfterReconstructXMLDsigParameters)
throws PdfAsException {
try {
List extSignatures = verifyAfterReconstructXMLDsigParameters.getReconstructXMLDsigResult().getExtendedSignatures();
String signatureDevice = verifyAfterReconstructXMLDsigParameters.getSignatureDevice();
if (signatureDevice == null){
signatureDevice = verifyAfterReconstructXMLDsigParameters.getReconstructXMLDsigResult().getDevice();
}
List results = PdfAS.verifyExtendedSignatureHolders(extSignatures,
signatureDevice,
verifyAfterReconstructXMLDsigParameters.isReturnHashInputData(),
verifyAfterReconstructXMLDsigParameters.getVerificationTime(), verifyAfterReconstructXMLDsigParameters.getVerifySignatureIndex());
List vrs = new ArrayList(results.size());
int verifySignatureIndex = verifyAfterReconstructXMLDsigParameters.getVerifySignatureIndex();
if (verifySignatureIndex < 0)
{
for (int i = 0; i < extSignatures.size(); i++)
{
SignatureResponse response = (SignatureResponse) results.get(i);
ExtendedSignatureInformation extSigInfo = (ExtendedSignatureInformation)extSignatures.get(i);
SignatureHolder holder = (SignatureHolder) extSigInfo.getSignatureInformation().getInternalSignatureInformation();
VerifyResult vr = new VerifyResultAdapter(response, holder, verifyAfterReconstructXMLDsigParameters.getVerificationTime(), extSigInfo.getXmlDsigData());
vr.setNonTextualObjects( extSigInfo.getSignatureInformation().getNonTextualObjects());
vrs.add(vr);
}
}else{
SignatureResponse response = (SignatureResponse) results.get(0);
ExtendedSignatureInformation extSigInfo = (ExtendedSignatureInformation)extSignatures.get(verifySignatureIndex);
SignatureHolder holder = (SignatureHolder) extSigInfo.getSignatureInformation().getInternalSignatureInformation();
VerifyResult vr = new VerifyResultAdapter(response, holder, verifyAfterReconstructXMLDsigParameters.getVerificationTime(), extSigInfo.getXmlDsigData());
vr.setNonTextualObjects( extSigInfo.getSignatureInformation().getNonTextualObjects());
vrs.add(vr);
}
VerifyResultsImpl verifyResults = new VerifyResultsImpl(vrs);
return verifyResults;
} catch (java.lang.OutOfMemoryError e) {
throw new OutOfMemoryException(ErrorCode.OUT_OF_MEMORY_ERROR, "Insufficient memory allocated to virtual machine. Start Java with parameters \"-Xms128m -Xmx786m -XX:MaxPermSize=256m\".", e);
}
}
public DynamicSignatureProfile createDynamicSignatureProfile(String parentProfile, DynamicSignatureLifetimeEnum mode) {
return DynamicSignatureProfileImpl.createFromParent(null, parentProfile, mode);
}
public DynamicSignatureProfile createEmptyDynamicSignatureProfile(DynamicSignatureLifetimeEnum mode) {
return DynamicSignatureProfileImpl.createEmptyProfile(null, mode);
}
public DynamicSignatureProfile loadDynamicSignatureProfile(String name) {
return DynamicSignatureProfileImpl.loadProfile(name);
}
public DynamicSignatureProfile createDynamicSignatureProfile(String myUniqueName,
String parentProfile, DynamicSignatureLifetimeEnum mode) {
return DynamicSignatureProfileImpl.createFromParent(myUniqueName, parentProfile, mode);
}
public DynamicSignatureProfile createEmptyDynamicSignatureProfile(String myUniqueName,
DynamicSignatureLifetimeEnum mode) {
return DynamicSignatureProfileImpl.createEmptyProfile(myUniqueName, mode);
}
/**
* @see PdfAs#prepareSign(SignParameters)
*/
public SignatureDetailInformation prepareSign(SignParameters signParameters) throws PdfAsException {
CheckHelper.checkSignParameters(signParameters, true);
if (signParameters.getProfileOverrideProperties() != null) {
OverridePropertyHolder.setOverrideProps(signParameters.getProfileOverrideProperties());
}
signParameters.setDocument(PdfAS.applyStrictMode(signParameters.getDocument()));
SettingsReader settings = SettingsReader.getInstance();
String defaultProfile = settings.getValueFromKey(SignatureTypes.DEFAULT_TYPE);
SignaturePlaceholderData spd = getSignaturePlaceholder(signParameters, defaultProfile);
if (spd != null){
if (spd.getProfile() != null)
signParameters.setSignatureProfileId(spd.getProfile());
if (spd.getType() != null)
signParameters.setSignatureType(spd.getType());
if (spd.getKey() != null)
signParameters.setSignatureKeyIdentifier(spd.getKey());
// check again, we might have destroyed something
CheckHelper.checkSignParameters(signParameters, true);
}
if (signParameters.getSignatureProfileId() == null)
{
signParameters.setSignatureProfileId(defaultProfile);
}
boolean fromPlaceholder = false;
boolean fromSignParameters = false;
boolean fromConfig = false;
TablePos pos = null;
if (spd != null && spd.getTablePos() != null){
// position and width is determined by placeholder image
fromPlaceholder = true;
pos = spd.getTablePos();
} else {
// position and width is determined by api sign parameters
pos = PosHelper.formTablePos(signParameters.getSignaturePositioning());
if (pos != null) {
fromSignParameters = true;
}
}
TablePos effectivePos = pos;
if (effectivePos == null) {
String pos_string = settings.getSetting(SignatureTypes.SIG_OBJ + signParameters.getSignatureProfileId() + ".pos", null);
if (pos_string != null) {
// position and width is determined by profile configuration
effectivePos = PdfAS.parsePositionFromPosString(pos_string);
fromConfig = true;
}
}
if (effectivePos != null) {
// check if width is lower than the smallest meaningful width
String thresholdString = AdobeSignatureHelper.getDefaultableConfigProperty(signParameters.getSignatureProfileId(), SIGNATURE_BLOCK_WIDTH_THRESHOLD_FOR_WARNING_KEY, String.valueOf(DEFAULT_SIGNATURE_BLOCK_WIDTH_THRESHOLD));
float threshold = DEFAULT_SIGNATURE_BLOCK_WIDTH_THRESHOLD;
try {
threshold = Float.parseFloat(thresholdString);
} catch (NumberFormatException e) {
if (log.isDebugEnabled()) {
log.debug("Unable to parse threshold value (\"" + thresholdString + "\") of configuration value \"" + SIGNATURE_BLOCK_WIDTH_THRESHOLD_FOR_WARNING_KEY + "\". Using default value: " + DEFAULT_SIGNATURE_BLOCK_WIDTH_THRESHOLD);
}
}
if (!effectivePos.isWauto() && effectivePos.getWidth() < threshold) {
String msg = "The {0} for the signature block is very small ({1}). The signature block might not get placed correcty.";
String[] arguments = new String[]{ "given width", "" + effectivePos.getWidth()};
// very small, warn user
if (fromPlaceholder) {
arguments[0] = "width given by the placeholder image";
} else if (fromSignParameters) {
arguments[0] = "width defined by the sign parameters";
} else if (fromConfig) {
arguments[0] = "width defined by the profile " + signParameters.getSignatureProfileId();
}
log.warn(MessageFormat.format(msg, arguments));
}
}
Signator signator = createSignator(signParameters.getSignatureType());
SignatorInformation signatorInfo = signator.prepareSign(
new PdfDataSourceAdapter(signParameters.getDocument()),
signParameters.getSignatureProfileId(),
pos,
signParameters.getTimeStamperImpl());
SignatureDetailInformationImpl ret = new SignatureDetailInformationImpl();
ret.setSignatorInformation(signatorInfo);
return ret;
}
private SignaturePlaceholderData getSignaturePlaceholder(SignParameters signParameters,
String defaultProfile) throws SettingsException, PDFDocumentException, PlaceholderExtractionException {
SignaturePlaceholderData spd = null;
SignaturePlaceholderContext.setSignaturePlaceholderData(null);
SettingsReader settings = SettingsReader.getInstance();
// check sig_obj.PROFILEID.enable_placeholder_search
String profile = signParameters.getSignatureProfileId();
if (profile == null)
profile = defaultProfile;
String key = SignatureTypes.SIG_OBJ + profile + "." + ENABLE_PLACEHOLDER_SEARCH_KEY;
String configFileActivedString = settings.getValueFromKey(key);
if (configFileActivedString == null){
// check global enable_placeholder_search
configFileActivedString = settings.getValueFromKey(ENABLE_PLACEHOLDER_SEARCH_KEY);
}
Boolean configFileActived = null;
if (configFileActivedString != null)
configFileActived = Boolean.valueOf(configFileActivedString);
Boolean signParamsActivated = signParameters.isCheckForPlaceholder();
boolean enableSearch;
if (signParamsActivated != null)
{
enableSearch = signParamsActivated.booleanValue();
} else {
if (configFileActived != null)
enableSearch = configFileActived.booleanValue();
else
enableSearch = false;
}
if (enableSearch)
{
spd = SignaturePlaceholderExtractor.extract(
signParameters.getDocument().createInputStream(),
signParameters.getPlaceholderId(),
signParameters.getPlaceholderMatchMode());
}
return spd;
}
private Signator createSignator(String signatureType) throws SignatorFactoryException {
PdfASID signatorId = null;
if (signatureType.equals(Constants.SIGNATURE_TYPE_BINARY))
{
signatorId = SignatorFactory.MOST_RECENT_BINARY_SIGNATOR_ID;
}
if (signatureType.equals(Constants.SIGNATURE_TYPE_TEXTUAL))
{
signatorId = SignatorFactory.MOST_RECENT_TEXTUAL_SIGNATOR_ID;
}
if (signatureType.equals(Constants.SIGNATURE_TYPE_DETACHEDTEXTUAL))
{
signatorId = SignatorFactory.MOST_RECENT_DETACHEDTEXT_SIGNATOR_ID;
}
return at.gv.egiz.pdfas.framework.SignatorFactory.createSignator(signatorId);
}
public SignResult sign(SignParameters signParameters, SignatureDetailInformation signatorInfo)
throws PdfAsException {
CheckHelper.checkSignParametersForSignAfterPrepare(signParameters, false);
if (signParameters.getProfileOverrideProperties() != null) {
OverridePropertyHolder.setOverrideProps(signParameters.getProfileOverrideProperties());
}
String connectorId = CommandlineConnectorChooser.chooseCommandlineConnectorForSign(signParameters.getSignatureDevice());
ConnectorParameters cp = new ConnectorParameters();
cp.setProfileId(signParameters.getSignatureProfileId());
cp.setSignatureKeyIdentifier(signParameters.getSignatureKeyIdentifier());
Connector c = at.gv.egiz.pdfas.framework.ConnectorFactory.createConnector(connectorId, cp);
SignatureData sd = new SignatureDataImpl(new PdfDataSourceAdapter(signatorInfo.getSignatureData()), signatorInfo.getSignatureData().getMimeType());
SignSignatureObject sso = PdfAS.sign(sd, c, signParameters.getTimeStamperImpl());
((SignatureDetailInformationImpl)signatorInfo).setSignSignatureObject(sso);
return finishSign(signParameters, signatorInfo);
}
public SignResult finishSign(SignParameters signParameters, SignatureDetailInformation signatureDetailInformation)
throws PdfAsException {
try {
CheckHelper.checkSignParametersForSignAfterPrepare(signParameters, true);
CheckHelper.checkSignatureDetailInformation(signatureDetailInformation);
if (signParameters.getProfileOverrideProperties() != null) {
OverridePropertyHolder.setOverrideProps(signParameters.getProfileOverrideProperties());
}
Signator signator = createSignator(signParameters.getSignatureType());
SignatorInformation signatorInfo = ((SignatureDetailInformationImpl)signatureDetailInformation).getSignatorInfo();
signator.finishSign(signatorInfo, new DataSinkAdapter(signParameters.getOutput()));
return new SignResultImpl(
signParameters.getOutput(),
signatorInfo.getSignSignatureObject().getX509Certificate(),
new ActualSignaturePositionAdapter(signatorInfo.getActualTablePos()),
signatorInfo.getNonTextualObjects());
} finally {
OverridePropertyHolder.removeProperties();
DynamicSignatureProfileImpl.disposeLocalProfile();
}
}
}