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 --- .../java/at/gv/egiz/pdfas/utils/ConfigUtils.java | 318 +++++++++++++++++ .../java/at/gv/egiz/pdfas/utils/DataHashUtils.java | 156 +++++++++ .../main/java/at/gv/egiz/pdfas/utils/OgnlUtil.java | 209 ++++++++++++ .../java/at/gv/egiz/pdfas/utils/PDFASUtils.java | 92 +++++ .../main/java/at/gv/egiz/pdfas/utils/PdfAUtil.java | 66 ++++ .../java/at/gv/egiz/pdfas/utils/StreamUtils.java | 66 ++++ .../java/at/gv/egiz/pdfas/utils/TempDirHelper.java | 377 +++++++++++++++++++++ 7 files changed, 1284 insertions(+) create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/ConfigUtils.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/DataHashUtils.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/OgnlUtil.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/PDFASUtils.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/PdfAUtil.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/StreamUtils.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/TempDirHelper.java (limited to 'pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils') diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/ConfigUtils.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/ConfigUtils.java new file mode 100644 index 0000000..bbc64b1 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/ConfigUtils.java @@ -0,0 +1,318 @@ +/** + * Copyright 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.gv.egiz.pdfas.utils; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.SystemUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.log4j.PropertyConfigurator; + +import at.gv.egiz.pdfas.api.commons.Constants; +import at.gv.egiz.pdfas.api.exceptions.ConfigUtilsException; +import at.knowcenter.wag.egov.egiz.cfg.SettingsReader; +import at.knowcenter.wag.egov.egiz.pdf.Utils; + +/** + * @author Thomas Knall + */ +public final class ConfigUtils { + + private ConfigUtils() { + } + + /** + * The log. + */ + private static final Log logger_ = LogFactory.getLog(ConfigUtils.class); + + /** + * Deploys the default configuration with apache commons vfs. + * + * @param destination The destination folder. + * @param overwriteExisting If set true an already existing configuration is overwritten. If false nothing is being copied if the destination folder already exists. + * @return true if the configuration has been deployed, false if not. + * @throws ConfigUtilsException Thrown if there was an error during the deployment of the configuration. + */ + /* + private static boolean deployWithCommonsVFS(String destination, boolean overwriteExisting) throws ConfigUtilsException { + try { + FileSystemManager fsManager = VFS.getManager(); + FileObject defaultConfigurationFile = fsManager.resolveFile("res:DefaultConfiguration"); + FileObject destinationFile = fsManager.resolveFile(destination); + + if (destinationFile.exists() && !overwriteExisting) { + return false; + } + + destinationFile.copyFrom(defaultConfigurationFile, new AllFileSelector()); + return true; + } catch (FileSystemException e) { + throw new ConfigUtilsException(e); + } + } + */ + + + /** + * Deploys the default configuration from an included zip file. + * + * @param destination The destination folder. + * @param overwriteExisting If set true an already existing configuration is overwritten. If false nothing is being copied if the destination folder already exists. + * @return true if the configuration has been deployed, false if not. + * @throws ConfigUtilsException Thrown if there was an error during the deployment of the configuration. + */ + private static boolean deployFromZIP(String destination, boolean overwriteExisting) throws ConfigUtilsException { + try { + if (!overwriteExisting) { + if (configurationAlreadyExists(destination)) { + logger_.debug("There is at least one file or folder that would be overwritten at destination path \"" + destination + "\". Skipping extraction."); + return false; + } + } + InputStream in = ConfigUtils.class.getClassLoader().getResourceAsStream(Constants.DEFAULT_CONFIGURATION_ZIP_RESOURCE); + if (in == null) { + throw new ConfigUtilsException("Unable to find default configuration resource \"" + Constants.DEFAULT_CONFIGURATION_ZIP_RESOURCE + "\"."); + } + return deployFromZIP(in, destination, overwriteExisting); + } catch (IOException e) { + throw new ConfigUtilsException(e); + } + } + + /** + * Deploys the contents of a ZIP file to a certain location. + * + * @param inputStream The inputStream of a ZIP container. + * @param destination The destination folder. + * @param overwriteExisting If set true an already existing configuration is overwritten. If false nothing is being copied if the destination folder already exists. + * @return true if the configuration has been deployed, false if not. + * @throws ConfigUtilsException Thrown if there was an error during the deployment of the configuration. + */ + public static boolean deployFromZIP(InputStream inputStream, String destination, boolean overwriteExisting) throws ConfigUtilsException { + try { + if (!overwriteExisting) { + if (configurationAlreadyExists(destination)) { + logger_.debug("There is at least one file or folder that would be overwritten at destination path \"" + destination + "\". Skipping extraction."); + return false; + } + } + if (inputStream == null) { + throw new ConfigUtilsException("Unable to deploy ZIP file. InputStream is null."); + } + ZipInputStream zis = new ZipInputStream(inputStream); + ZipEntry ze; + File destinationFolder = new File(destination); + destinationFolder.mkdirs(); + logger_.debug("Extracting ZIP contents to folder \"" + destinationFolder.getCanonicalPath() + "\"."); + while ((ze = zis.getNextEntry()) != null) { + if (ze.isDirectory()) { + File newFolder = new File(destinationFolder, ze.getName()); + logger_.debug("Extracting folder \"" + newFolder.getPath() + "\"."); + newFolder.mkdirs(); + } else { + File destFile = new File(destinationFolder, ze.getName()); + logger_.trace("Extracting file \"" + destFile.getName() + "\"."); + PDFASUtils.toFile(zis, destFile); + } + zis.closeEntry(); + } + zis.close(); + return true; + } catch (IOException e) { + throw new ConfigUtilsException(e); + } + } + + private static boolean configurationAlreadyExists(String destination) throws ConfigUtilsException, IOException { + logger_.debug("Checking configuration \"" + destination + "\" already exists (resp. if there are any directories or files that would be overwritten)."); + File destinationFolder = new File(destination); + if (destinationFolder == null || !destinationFolder.exists()) { + return false; + } + InputStream in = ConfigUtils.class.getClassLoader().getResourceAsStream(Constants.DEFAULT_CONFIGURATION_ZIP_RESOURCE); + if (in == null) { + throw new ConfigUtilsException("Unable to find default configuration resource \"" + Constants.DEFAULT_CONFIGURATION_ZIP_RESOURCE + "\"."); + } + ZipInputStream zis = new ZipInputStream(in); + ZipEntry ze; + while ((ze = zis.getNextEntry()) != null) { + if (ze.isDirectory()) { + File newFolder = new File(destinationFolder, ze.getName()); + logger_.debug("Checking if folder \"" + newFolder.getPath() + "\" already exists."); + if (newFolder.exists()) { + logger_.debug("YES !"); + return true; + } else { + logger_.debug("no"); + } + } else { + File destFile = new File(destinationFolder, ze.getName()); + logger_.trace("Checking if file \"" + destFile.getName() + "\" already exists."); + if (destFile.exists()) { + logger_.trace("YES !"); + return true; + } else { + logger_.trace("no"); + } + } + zis.closeEntry(); + } + zis.close(); + return false; + } + + /** + * Deploys the default configuration to the given destination folder. + * + * @param destination The destination folder. + * @param overwriteExisting If set true an already existing configuration is overwritten. If false nothing is being copied if the destination folder already exists. + * @return The folder the configuration has been extracted to or null if the configuration has NOT been deployed. + * @throws ConfigUtilsException Thrown if there was an error during the deployment of the configuration. + */ + public static String deployDefaultConfiguration(String destination, boolean overwriteExisting) throws ConfigUtilsException { + if (destination == null) { + throw new NullPointerException("Destination must not be null."); + } + if (destination.length() == 0) { + throw new IllegalArgumentException("Destination must not be empty."); + } + return deployFromZIP(destination, overwriteExisting) ? destination : null; + } + + /** + * Deploys the default configuration to the user's home directory to the subdirectory specified by + * Constants.Constants.USERHOME_CONFIG_FOLDER. + * + * @param overwriteExisting If set true an already existing configuration is overwritten. If false nothing is being copied if the destination folder already exists. + * @return The folder the configuration has been extracted to or null if the configuration has NOT been deployed. + * @throws ConfigUtilsException Thrown if there was an error during the deployment of the configuration. + * @see Constants#USERHOME_CONFIG_FOLDER + */ + public static String deployDefaultConfiguration(boolean overwriteExisting) throws ConfigUtilsException { + String configdir = System.getProperty(Constants.CONFIG_DIR_SYSTEM_PROPERTY); + if (configdir == null) { + configdir = System.getProperty("user.home"); + if (configdir != null) { + configdir = configdir + File.separator + Constants.USERHOME_CONFIG_FOLDER; + } + } + if (configdir == null || configdir.length() == 0) { + return null; + } + return deployDefaultConfiguration(configdir, overwriteExisting); + } + + /** + * Deploys the default configuration to the user's home directory to the subdirectory specified by + * Constants.Constants.USERHOME_CONFIG_FOLDER. + * + * @return The folder the configuration has been extracted to or null if the configuration has NOT been deployed. + * @throws ConfigUtilsException Thrown if there was an error during the deployment of the configuration. + * @see Constants#USERHOME_CONFIG_FOLDER + */ + public static String deployDefaultConfiguration() throws ConfigUtilsException { + return deployDefaultConfiguration(false); + } + + public static void writeInputStreamToOutputStream(InputStream inputStream, OutputStream outputStream) throws IOException { + final int bufferSize = 1024; + byte[] buffer = new byte[bufferSize]; + int len = -1; + while ((len = inputStream.read(buffer)) != -1) { + outputStream.write(buffer, 0, len); + } + outputStream.flush(); + } + + public static String assertFileSeparator(String path) { + if (path == null) { + throw new NullPointerException("Path must not be null."); + } + if (path.endsWith(File.separator) || path.endsWith("/") || path.endsWith("\\")) { + return path; + } else { + return (path + File.separator); + } + } + + public static void initializeLogger() { + String loggerConfiguration = System.getProperty("log4j.configuration"); + if (loggerConfiguration != null) { + logger_.info("No PDF-AS logger configured because a configuration has already been set via system property \"log4j.configuration\" (=\"" + loggerConfiguration + "\")."); + return; + } + loggerConfiguration = assertFileSeparator(SettingsReader.CONFIG_PATH) + "log4j.properties"; + File loggerConfigFile = new File(loggerConfiguration); + if (!loggerConfigFile.exists()) { + logger_.info("No PDF-AS logger configured because there is no log4j.properties within the pdf-as work dir. Maybe the logger configuration is handled by an outside application (e.g. a web application)."); + return; + } + logger_.info("Initializing PDF-AS logger (configuration = \"" + loggerConfiguration + "\")."); + PropertyConfigurator.configure(loggerConfiguration); + } + + public static void printConfigInfo(Log logger) { + int length = Utils.max(new int[] { SettingsReader.RESOURCES_PATH.length(), SettingsReader.TMP_PATH.length(), SettingsReader.CONFIG_PATH.length(), SettingsReader.CERT_PATH.length() }); + + String separator = StringUtils.repeat("*", length + 25); + String infoResources = " resources path = \"" + SettingsReader.RESOURCES_PATH + "\""; + String infoConfiguration = " configuration path = \"" + SettingsReader.CONFIG_PATH + "\""; + String infoCertStore = " certstore path = \"" + SettingsReader.CERT_PATH + "\""; + String infoTempPath = " temporary path = \"" + SettingsReader.TMP_PATH + "\""; + String encoding = " file.encoding = \"" + System.getProperty("file.encoding") + "\""; + + if (logger != null) { + logger.info(separator); + logger.info(infoResources); + logger.info(infoConfiguration); + logger.info(infoCertStore); + logger.info(infoTempPath); + logger.info(encoding); + logger.info(separator); + } else { + StringBuffer buffer = new StringBuffer(); + buffer.append(separator).append(SystemUtils.LINE_SEPARATOR); + buffer.append(infoResources).append(SystemUtils.LINE_SEPARATOR); + buffer.append(infoConfiguration).append(SystemUtils.LINE_SEPARATOR); + buffer.append(infoCertStore).append(SystemUtils.LINE_SEPARATOR); + buffer.append(infoTempPath).append(SystemUtils.LINE_SEPARATOR); + buffer.append(encoding).append(SystemUtils.LINE_SEPARATOR); + buffer.append(separator); + System.out.println(buffer.toString()); + } + } + + public static void printConfigInfo() { + printConfigInfo(null); + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/DataHashUtils.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/DataHashUtils.java new file mode 100644 index 0000000..4b26ada --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/DataHashUtils.java @@ -0,0 +1,156 @@ +/** + * Copyright 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.gv.egiz.pdfas.utils; + +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.security.DigestInputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +import org.apache.commons.codec.binary.Base64; + +import at.knowcenter.wag.egov.egiz.pdf.BinarySignatureHolder; +import at.knowcenter.wag.egov.egiz.pdf.SignatureHolder; +import at.knowcenter.wag.egov.egiz.pdf.TextualSignatureHolder; + +/** + * Contains helpful methods for building data hashed. + * + *

+ * Data hashes are useful for summarizing the signed data of signatures for + * debugging and testing purposes. Do not use these hashes for signatures. + *

+ *

+ * A data hash is always a Base64 encoded String. + *

+ * + * @author wprinz + * + */ +public final class DataHashUtils +{ + + /** + * + * @param text + * @return + */ + public static String buildDataHash(String text) + { + try + { + MessageDigest md = getMessageDigest(); + // probable performance leak for very large texts + md.update(text.getBytes("UTF-8")); + byte[] rawDigest = md.digest(); + + return encodeDigest(rawDigest); + } + catch (UnsupportedEncodingException e) + { + throw new RuntimeException(e); + } + } + + public static String buildDataHash(byte[] data) + { + MessageDigest md = getMessageDigest(); + md.update(data); + byte[] rawDigest = md.digest(); + + return encodeDigest(rawDigest); + } + + public static String buildDataHash(InputStream is) + { + try + { + MessageDigest md = getMessageDigest(); + + DigestInputStream dis = new DigestInputStream(is, md); + + byte[] temp = new byte[1024]; + int i = 0; + while (dis.read(temp) >= 0) + { + // this just keeps the compiler from optimizing this loop away + i++; + } + dis.close(); + + byte[] rawDigest = md.digest(); + + return encodeDigest(rawDigest); + } + catch (IOException e) + { + throw new RuntimeException(e); + } + } + + public static String buildDataHash(SignatureHolder sh) + { + if (sh instanceof TextualSignatureHolder) + { + TextualSignatureHolder tsh = (TextualSignatureHolder) sh; + String signedText = tsh.getSignedText(); + return buildDataHash(signedText); + } + + { + BinarySignatureHolder bsh = (BinarySignatureHolder) sh; + InputStream is = bsh.getSignedPdf().createInputStream(); + return buildDataHash(is); + } + } + + protected static MessageDigest getMessageDigest() + { + try + { + MessageDigest sha1 = MessageDigest.getInstance("SHA-1"); + return sha1; + } + catch (NoSuchAlgorithmException e) + { + throw new RuntimeException(e); + } + } + + protected static String encodeDigest(byte[] rawDigest) + { + try + { + byte[] encoded = Base64.encodeBase64(rawDigest); + String str = new String(encoded, "US-ASCII"); + return str; + } + catch (UnsupportedEncodingException e) + { + throw new RuntimeException(e); + } + } +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/OgnlUtil.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/OgnlUtil.java new file mode 100644 index 0000000..69b30f8 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/OgnlUtil.java @@ -0,0 +1,209 @@ +/** + * Copyright 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.gv.egiz.pdfas.utils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import ognl.Ognl; +import ognl.OgnlException; + +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; + +/** + * Utility class for ognl evaluation. + * ognl website + * @author dferbas + * @author mhiess + * + */ +public class OgnlUtil { + + private static final String EXP_END = "}"; + + private static final String EXP_START = "${"; + + private static final Logger log = Logger.getLogger(OgnlUtil.class); + + private Map context = new HashMap(); + private Object root = null; + + public OgnlUtil() { + this.init(null); + } + + public OgnlUtil(Map context) { + this.init(context); + } + + public OgnlUtil(Object root) { + this.root = root; + this.init(null); + } + + /** + * Adds the default utils to the context + * + * @param context1 + */ + private void init(Map context1) { + if (context1 != null) { + this.context = context1; + } + } + + private List extractExpressions(String text) { + + List expressions = new ArrayList(); + + int indexStart = 0; + int indexEnd = 0; + String exp; + + while (indexStart != -1) { + indexStart = text.indexOf(EXP_START, indexStart); + indexEnd = text.indexOf(EXP_END, indexStart); + + if (indexStart != -1 && indexEnd != -1) { + + exp = text.substring(indexStart + 2, indexEnd); + log.debug("Found expression in template: " + exp); + if (!exp.equals("") && exp != null) { + if (!expressions.contains(exp)) { + expressions.add(exp); + } else { + log.debug("Duplicated expression '" + exp + "' found"); + } + } + + indexStart = indexEnd; + } + } + + return expressions; + } + + public boolean containsExpression(String template) { + return template != null && StringUtils.contains(template,"${") && StringUtils.contains(template, "}"); + } + + /** + * Compile/evaluate a message with ognl expressions marked with ${expression} + * + * @param template + * @return + */ + public String compileMessage(String template) { + + if (this.context != null) { + String compiledMsg = template; + List expressions = this.extractExpressions(template); + + String value; + for (Iterator it = expressions.iterator(); it.hasNext();) { + String expr = (String) it.next(); + + try { + if (this.root != null) { + value = String.valueOf(Ognl.getValue(expr, this.root)); + } else { + value = String.valueOf(Ognl.getValue(expr, this.context)); + } + log.debug("Found value: '" + value + "' for expression: '" + expr + "'"); + + if (value == null) { + value = ""; + log.debug("Set value for expression to: empty string"); + } + + compiledMsg = StringUtils.replace(compiledMsg, EXP_START + expr + EXP_END, value); + } catch (OgnlException e) { + log.error(e.getMessage(), e); + } + } + log.debug("Returning compiled message: " + compiledMsg); + return compiledMsg; + } + return null; + } + + /** + * Evaluate an expression as ognl, returning result as object. No placeholders ${ } allowed. + * @param ognlExp + * @return + */ + public Object evaluate(String ognlExp) { + + if (this.context != null) { + + Object value = null; + try { + value = Ognl.getValue(ognlExp, this.context); + log.debug("Found value: '" + value + "' for expression: '" + ognlExp + "'"); + + } catch (OgnlException e) { + log.error(e.getMessage(), e); + } + return value; + } else return null; + } + + /** + * This method compiles a map of ognl expression to a map with entries + * + * @param toCompile + * @return + */ + public Map compileExpressions(Map toCompile) { + if (this.context != null) { + Map result = new HashMap(); + + for (Iterator it = result.entrySet().iterator(); it.hasNext();) { + Entry entry = (Entry) it.next(); + try { + result.put(entry.getKey(), Ognl.getValue(entry.getValue(), this.context)); + } catch (OgnlException e) { + result.put(entry.getKey(), null); + log.warn(e.getMessage(), e); + } + } + return result; + + } + return null; + } + + public Map getContext() { + return this.context; + } + + public void mergeOgnlContext(OgnlUtil ognlUtil) { + this.context.putAll(ognlUtil.getContext()); + } +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/PDFASUtils.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/PDFASUtils.java new file mode 100644 index 0000000..4cd3bd5 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/PDFASUtils.java @@ -0,0 +1,92 @@ +/** + * Copyright 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.gv.egiz.pdfas.utils; + +import java.io.BufferedOutputStream; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.pdfbox.pdmodel.PDDocument; + +import at.gv.egiz.pdfas.exceptions.ErrorCode; +import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException; + +import com.lowagie.text.pdf.PdfReader; + +/** + * @author tknall + */ +public class PDFASUtils { +//23.11.2010 changed by exthex - added checkDocumentPermissions(PDDocument doc) + + private PDFASUtils() { + } + + /** + * Verifies that a document could be opened with full permissions. + * @param pdfReader The PdfReader + * @throws PDFDocumentException Thrown if document has not been opened with full permissions. + */ + public static void checkReaderPermissions(PdfReader pdfReader) throws PDFDocumentException { + if (pdfReader.isEncrypted()) { + throw new PDFDocumentException(ErrorCode.DOCUMENT_IS_PROTECTED, "Document is encrypted."); + } + if (!pdfReader.isOpenedWithFullPermissions()) { + throw new PDFDocumentException(ErrorCode.DOCUMENT_IS_PROTECTED, "Document is protected."); + } + } + + public static boolean toFile(byte[] data, File file) throws IOException { + return PDFASUtils.toFile(new ByteArrayInputStream(data), file); + } + + public static boolean toFile(InputStream inputStream, File file) throws IOException { + boolean result = false; + BufferedOutputStream bufferedOutputStream = null; + try { + bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(file)); + ConfigUtils.writeInputStreamToOutputStream(inputStream, bufferedOutputStream); + } finally { + if (bufferedOutputStream != null) { + try { + bufferedOutputStream.close(); + result = true; + } catch (IOException e) { + result = false; + } + } + } + return result; + } + + public static void checkDocumentPermissions(PDDocument doc) throws PDFDocumentException { + if (doc.isEncrypted()) { + throw new PDFDocumentException(ErrorCode.DOCUMENT_IS_PROTECTED, "Document is encrypted."); + } + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/PdfAUtil.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/PdfAUtil.java new file mode 100644 index 0000000..e741bca --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/PdfAUtil.java @@ -0,0 +1,66 @@ +/** + * Copyright 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.gv.egiz.pdfas.utils; + +/** + * PDF/A utility class + * @author dferbas + * + */ +public class PdfAUtil { + /** + * dferbas: Text representation of pdfa version string + */ + private static final String PDFA_PREFIX = "ISO 19005-1:2005 PDF/A-"; + /** + * Extract pdfa version from pdf metadata + * @param pdfMetadata + * @return + */ + public static String findPdfAVersion(String pdfMetadata) { + + String inf = pdfMetadata; + String pdfaNsMark = "http://www.aiim.org/pdfa/ns/id/"; + String partMark = ""; + String confMark = ""; + int pdfaI = inf.indexOf(pdfaNsMark); + + if (pdfaI > -1) { + int part = inf.indexOf(partMark); + StringBuffer version = new StringBuffer(PDFA_PREFIX); + part = part + partMark.length(); + version.append(inf.substring(part, part + 1)); + int conf = inf.indexOf(confMark); + + conf = conf + confMark.length(); + version.append(inf.substring(conf, conf + 1).toLowerCase()); + + return version.toString(); + } else { + return null; + + } + } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/StreamUtils.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/StreamUtils.java new file mode 100644 index 0000000..3dce5b1 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/StreamUtils.java @@ -0,0 +1,66 @@ +/** + * Copyright 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.gv.egiz.pdfas.utils; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +public class StreamUtils +{ + + public static void writeInputStreamToOutputStream (InputStream is, OutputStream os) throws IOException + { + byte [] buffer = new byte [2048]; + + int read = -1; + while ((read = is.read(buffer)) > 0) + { + os.write(buffer, 0, read); + } + os.flush(); + is.close(); + os.close(); + } + + // The InputStream should be self- delimited. +// public static void writeInputStreamToOutputStream(InputStream is, OutputStream os, int length) throws IOException +// { +// byte [] buffer = new byte [2048]; +// +// int bytes_to_write = length; +// +// int read = -1; +// while ((read = is.read(buffer, 0, (bytes_to_write >= buffer.length) ? buffer.length : bytes_to_write)) > 0) +// { +// os.write(buffer, 0, read); +// bytes_to_write -= read; +// } +// is.close(); +// os.close(); +// +// assert bytes_to_write == 0; +// } + +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/TempDirHelper.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/TempDirHelper.java new file mode 100644 index 0000000..bccc67b --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/TempDirHelper.java @@ -0,0 +1,377 @@ +/** + * Copyright 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.gv.egiz.pdfas.utils; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStreamWriter; +import java.text.DecimalFormat; +import java.text.NumberFormat; +import java.util.Iterator; +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.pdfas.framework.input.DataSource; +import at.gv.egiz.pdfas.framework.input.PdfDataSource; +import at.gv.egiz.pdfas.framework.input.TextDataSource; +import at.gv.egiz.pdfas.framework.output.DataSink; +import at.gv.egiz.pdfas.impl.input.ByteArrayPdfDataSourceImpl; +import at.gv.egiz.pdfas.impl.input.FileBased; +import at.gv.egiz.pdfas.impl.input.FileBasedTextDataSourceImpl; +import at.gv.egiz.pdfas.impl.input.TextDataSourceImpl; +import at.gv.egiz.pdfas.impl.input.helper.DataSourceHelper; +import at.gv.egiz.pdfas.impl.output.ByteArrayDataSink; +import at.knowcenter.wag.egov.egiz.cfg.SettingsReader; +import at.knowcenter.wag.egov.egiz.pdf.SignatureHolder; +import at.knowcenter.wag.egov.egiz.pdf.TextualSignatureHolder; + +/** + * @author wprinz + * + */ +public class TempDirHelper +{ + /** + * The log. + */ + private static Log log = LogFactory.getLog(TempDirHelper.class); + + protected static long runningIndex = 0; + + /** + * Assembles the File of the temporary directory without checking if it really + * exists. + */ + public static File assembleTemporaryDirectoryFile() + { + File temp_dir = new File(SettingsReader.TMP_PATH); + return temp_dir; + } + + /** + * Returns the directory where temporary files should be stored. + * + *

+ * If the directory doesn't exist, it is created. + *

+ * + * @return Returns the directory where temporary files should be stored. + */ + public static File getTemporaryDirectory() + { + File temp_dir = assembleTemporaryDirectoryFile(); + if (!temp_dir.exists()) + { + temp_dir.mkdirs(); + } + return temp_dir; + } + + /** + * Deletes all files in the temporary directory, if it exists. + * + *

+ * This should be used to clear temporary files when the application shuts + * down. + *

+ */ + public static void clearTemporaryDirectory() + { + File temp_dir = assembleTemporaryDirectoryFile(); + log.debug("Clearing temporary directory: " + temp_dir); + + if (!temp_dir.exists()) + { + return; + } + + File[] files = temp_dir.listFiles(); + for (int i = 0; i < files.length; i++) + { + // added by tknall: do not try to remove svn-metadata + if (files[i].getName().endsWith(".svn")) { + continue; + } + log.debug(" Clearing temporary file: " + files[i]); + boolean delete_success = files[i].delete(); + if (!delete_success) + { + log.error("Couldn't delete the temporary file: " + files[i]); + } + } + } + + public static void storeTextSignatureHoldersIfApplicable(List shs, String fileNameSuffix) throws IOException + { + Iterator it = shs.iterator(); + while (it.hasNext()) + { + SignatureHolder sh = (SignatureHolder) it.next(); + if (sh instanceof TextualSignatureHolder) + { + TextualSignatureHolder tsh = (TextualSignatureHolder) sh; + if (!(tsh.getDataSource() instanceof FileBased)) + { + TextDataSource tds = (TextDataSource) tsh.getDataSource(); + if (isReasonableToStore(tds.getText().length())) + { + TextDataSource fbtds = placeTextIntoTempDir(tds.getText(), fileNameSuffix); + tsh.exchangeDataSource(fbtds); + } + } + } + } + } + + /** + * Places the text into the temp dir if reasonable. + * + *

+ * Reasonable means that the text is longer than a certain threshold. + * Otherwise a short text is simply held in memory. + *

+ * + * @param text + * The text to be stored. + * @param fileNameSuffix + * A file name suffix so that the temp file gets a more "readable" + * name. + * @return Returns the TextDataSource. + * @throws IOException + * F.e. + */ + public static TextDataSource placeTextIntoTempDir(String text, String fileNameSuffix) throws IOException + { + if (isReasonableToStore(text.length())) + { + String fileName = formatFileName(fileNameSuffix); + + File tmpFile = createTempFileInDir(fileName); + + FileOutputStream fos = new FileOutputStream(tmpFile); + OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8"); + osw.write(text); + osw.close(); + + FileBasedTextDataSourceImpl textDataSource = new FileBasedTextDataSourceImpl(tmpFile, "UTF-8"); + return textDataSource; + } + else + { + return new TextDataSourceImpl(text); + } + } + + /** + * Tells, if it is reasonable to store the text of the given length onto the + * disk. + * + * @param textLength + * The length of the text under question. + * @return Returns true if the text should be stored on the disk. + */ + public static boolean isReasonableToStore(int textLength) + { + return false; +// return textLength >= 10000; + } + + public static PdfDataSource placePdfIntoTempDir(InputStream pdfInput, String fileNameSuffix) throws IOException + { + log.debug("PERF: placing pdf into memory cache"); + + byte [] pdfData = DataSourceHelper.convertInputStreamToByteArray(pdfInput); + PdfDataSource pdfDataSource = new ByteArrayPdfDataSourceImpl(pdfData); + +// File pdfFile = placeInputIntoTempDirFile(pdfInput, fileNameSuffix); +// +// FileBasedPdfDataSourceImpl pdfDataSource = new FileBasedPdfDataSourceImpl(pdfFile, (int) pdfFile.length()); + return pdfDataSource; + } + + public static File placeInputIntoTempDirFile(InputStream input, String fileNameSuffix) throws IOException + { + String fileName = formatFileName(fileNameSuffix); + + File tmpFile = createTempFileInDir(fileName); + + FileOutputStream fos = new FileOutputStream(tmpFile); + + byte[] buffer = new byte[2048]; + int read = -1; + while ((read = input.read(buffer)) > 0) + { + fos.write(buffer, 0, read); + } + fos.close(); + input.close(); + + return tmpFile; + } + + public static File formTempFile(String fileNameSuffix) + { + String fileName = formatFileName(fileNameSuffix); + File tmpFile = getFileInTempDir(fileName); + + return tmpFile; + } + + protected static File getFileInTempDir (String fileName) + { +// File tempDir = new File(new File(SettingsReader.RESOURCES_PATH), "pdfastmp"); + File tempDir = assembleTemporaryDirectoryFile(); + + File tmpFile = new File(tempDir, fileName); + + return tmpFile; + } + + protected static String formatFileName(String fileNameSuffix) + { + // double check so that file name is always correct. + fileNameSuffix = extractFileNameSuffix(fileNameSuffix); + String fileName = "tmp" + formatIndex(runningIndex) + "_" + fileNameSuffix; + runningIndex++; + + return fileName; + } + + protected static String formatIndex(long index) + { + NumberFormat nf = new DecimalFormat("00000000"); + + return nf.format(index); + } + + protected static File createTempFileInDir(String fileName) throws IOException + { + File tmpFile = getFileInTempDir(fileName); + + tmpFile.createNewFile(); + + tmpFile.deleteOnExit(); + + return tmpFile; + } + + public static DataSink createTempDataSink(String fileNameSuffix) throws IOException + { + log.debug("PERF: placing pdf into memory cache"); + + DataSink ds = new ByteArrayDataSink(); + +// String fileName = formatFileName(fileNameSuffix); +// +// File tmpFile = createTempFileInDir(fileName); +// +// FileBasedDataSink ds = new FileBasedDataSink(tmpFile); + + return ds; + } + +// public static void writeDataSinkToHttpResponse(DataSink ds, HttpServletResponse response) throws IOException +// { +// +// response.setContentType(ds.getMimeType()); +// response.setCharacterEncoding(ds.getCharacterEncoding()); +// +// OutputStream os = response.getOutputStream(); +// +// if (ds instanceof FileBasedDataSink) +// { +// FileBasedDataSink fbds = (FileBasedDataSink)ds; +// byte[] buffer = new byte[2048]; +// FileInputStream fis = new FileInputStream(fbds.getFile()); +// int n = -1; +// while ((n = fis.read(buffer)) > 0) +// { +// os.write(buffer, 0, n); +// } +// fis.close(); +// } +// else +// { +// ByteArrayDataSink bads = (ByteArrayDataSink)ds; +// os.write(bads.getByteArray()); +// os.flush(); +// +// } +// +// os.close(); +//} + + /** + * Deletes the underlying file of the FileBased DataSource. + * + *

+ * If the DataSource is not FileBased, nothing is done. + *

+ *

+ * This is usually used by the application to delete temporary files. + *

+ * + * @param dataSource + */ + public static void deleteDataSourceIfFileBased(DataSource dataSource) + { + if (dataSource instanceof FileBased) + { + FileBased fb = (FileBased) dataSource; + log.debug("Deleting temp file " + fb.getFile()); + boolean deleted = fb.getFile().delete(); + log.debug("deleted = " + deleted); + } + } + + public static void deleteDataSinkIfFileBased(DataSink dataSink) + { + if (dataSink instanceof FileBased) + { + FileBased fb = (FileBased) dataSink; + log.debug("Deleting temp file " + fb.getFile()); + boolean deleted = fb.getFile().delete(); + log.debug("deleted = " + deleted); + } + } + + /** + * Given a file (maybe with path), extracts the file name suffix. + * @param file The file and maybe path. + * @return Returns the file name. + */ + public static String extractFileNameSuffix (String file) + { + if (file == null || file.trim().length() == 0) + { + return "nofilename"; + } + File f = new File(file); + return f.getName(); + } +} -- cgit v1.2.3