From 535a04fa05f739ec16dd81666e3b0f82dfbd442d Mon Sep 17 00:00:00 2001 From: tknall Date: Wed, 9 Jan 2013 15:41:29 +0000 Subject: pdf-as-lib maven project files moved to pdf-as-lib git-svn-id: https://joinup.ec.europa.eu/svn/pdf-as/pdf-as/trunk@926 7b5415b0-85f9-ee4d-85bd-d5d0c3b42d1c --- .../wag/egov/egiz/pdf/AdobeSignatureHelper.java | 272 +++++++++++++++++++++ 1 file changed, 272 insertions(+) create mode 100644 pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/AdobeSignatureHelper.java (limited to 'pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/AdobeSignatureHelper.java') 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 2006 by Know-Center, Graz, Austria + * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a + * joint initiative of the Federal Chancellery Austria and Graz University of + * Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ +package at.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; + } + } + +} -- cgit v1.2.3