aboutsummaryrefslogtreecommitdiff
path: root/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils
diff options
context:
space:
mode:
Diffstat (limited to 'pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils')
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/CsvUtils.java82
-rw-r--r--pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/PDFASUtils.java268
2 files changed, 301 insertions, 49 deletions
diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/CsvUtils.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/CsvUtils.java
new file mode 100644
index 0000000..a78da93
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/utils/CsvUtils.java
@@ -0,0 +1,82 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+package at.gv.egiz.pdfas.utils;
+
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * Methods in order to create valid delimiter separated data, where the semicolon as used as delimiter, also known as
+ * the German version of CSV.
+ *
+ * @author Datentechnik Innovation GmbH
+ * @see <a href="http://tools.ietf.org/html/rfc4180">RFC 4180</a>
+ */
+public class CsvUtils {
+
+ /**
+ * The delimiter char used instead of COMMA.
+ */
+ public static final char DEFAULT_DELIMITER = ';';
+
+ private static final char QUOTE_CHAR = '"';
+ private static final char LF_CHAR = '\n';
+ private static final char CR_CHAR = '\r';
+
+ private static final char[] SHOULD_BE_QUOTED = { LF_CHAR, CR_CHAR, DEFAULT_DELIMITER, QUOTE_CHAR };
+ private static final String CSV_QUOTE = String.valueOf(QUOTE_CHAR);
+
+ /**
+ * Returns an DSV escapted representation of the given object using the default delimiter character (
+ * {@link #DEFAULT_DELIMITER}).
+ *
+ * @param obj
+ * The object.
+ * @return An escapted representation of the given object.
+ */
+ public static String escapeCsvValue(Object obj) {
+ // null value should be printed as empty column
+ if (obj == null) {
+ return "";
+ }
+ // get String representation of object
+ String asString = String.valueOf(obj);
+ // do we need to escape anything?
+ if (StringUtils.containsNone(asString, SHOULD_BE_QUOTED)) {
+ return asString;
+ }
+
+ // RFC 4180 (7): If double-quotes are used to enclose fields, then a double-quote
+ // appearing inside a field must be escaped by preceding it with
+ // another double quote.
+ asString = StringUtils.replace(asString, CSV_QUOTE, CSV_QUOTE + CSV_QUOTE);
+
+ // RFC 4180 (6): Fields containing line breaks (CRLF), double quotes, and commas
+ // should be enclosed in double-quotes.
+ if (StringUtils.containsAny(asString, SHOULD_BE_QUOTED)) {
+ return QUOTE_CHAR + asString + QUOTE_CHAR;
+ }
+ return asString;
+ }
+
+}
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
index 7f09dfc..a2332dd 100644
--- 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
@@ -30,63 +30,233 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.BooleanUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.apache.pdfbox.pdmodel.PDDocument;
+import at.gv.egiz.pdfas.api.io.DataSource;
import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException;
+import com.lowagie.text.Document;
+import com.lowagie.text.pdf.BadPasswordException;
import com.lowagie.text.pdf.PdfReader;
/**
- * @author tknall
+ * Collection of useful utilities.
*/
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.");
- }
- }
-
+
+ private static Log log = LogFactory.getLog(PDFASUtils.class);
+
+ /**
+ * The configuration key for PDF/A support.
+ */
+ public static final String CFG_KEY_PDFA = "SIG_PDFA1B_VALID";
+
+ 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.
+ */
+ private 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.");
+ }
+ }
+
+ /**
+ * Verifies that the document is not encrypted and/or protected. In case no restrictions have been applied to the
+ * document a pdf reader is returned.
+ *
+ * @param dataSource
+ * The document data source.
+ * @throws PDFDocumentException
+ * Thrown if the document could not be opened with full permissions.
+ */
+ public static PdfReader createPdfReaderCheckingPermissions(DataSource dataSource) throws PDFDocumentException {
+ return createPdfReaderCheckingPermissions(dataSource.createInputStream());
+ }
+
+ /**
+ * Verifies that the document is not encrypted and/or protected. In case no restrictions have been applied to the
+ * document a pdf reader is returned.
+ *
+ * @param dataSource
+ * The document data source.
+ * @throws PDFDocumentException
+ * Thrown if the document could not be opened with full permissions.
+ */
+ public static PdfReader createPdfReaderCheckingPermissions(at.gv.egiz.pdfas.framework.input.DataSource dataSource)
+ throws PDFDocumentException {
+ return createPdfReaderCheckingPermissions(dataSource.createInputStream());
+ }
+
+ /**
+ * Verifies that the document is not encrypted and/or protected. In case no restrictions have been applied to the
+ * document a pdf reader is returned.
+ *
+ * @param inputStream
+ * The document data input stream.
+ * @throws PDFDocumentException
+ * Thrown if the document could not be opened with full permissions.
+ */
+ public static PdfReader createPdfReaderCheckingPermissions(InputStream inputStream) throws PDFDocumentException {
+ PdfReader reader = null;
+ try {
+ // try to parse document
+ // If fully encrypted, PdfReader will fail;
+ // It should throw a BadPasswordException, but unfortunately does not (throws an IOException instead,
+ // internally catching BadPAsswordException; see comments below).
+ reader = new PdfReader(inputStream);
+ checkReaderPermissions(reader);
+ return reader;
+ } catch (BadPasswordException e) {
+ // will never be reached with itext-2.1.5-rev3628-pdfas:v1.1
+ // just added for later versions... (see comments below)
+ // itext-2.1.5-rev3628-pdfas:v1.2 correctly throws BadPasswordException
+ throw new PDFDocumentException(ErrorCode.DOCUMENT_IS_PROTECTED, "Document is protected.");
+ } catch (PDFDocumentException e) {
+ throw e;
+ } catch (Exception e) {
+ final String EX_MSG_FOR_ENCRYPTED_DOCUMENT = "Bad user Password";
+ // Inspecting the exception message seems to be the only way when using itext-2.1.5-rev3628-pdfas:v1.1:
+ // itext neither externally throws a BadPasswordException nor passed the cause...,
+ // later versions do!
+ // String "Bad user Password" is set in com.lowagie.text.pdf.BadPasswordException so this approach will
+ // work as long as the underlying itext library is not beeing updated.
+ if (StringUtils.containsIgnoreCase(e.getMessage(), EX_MSG_FOR_ENCRYPTED_DOCUMENT)) {
+ throw new PDFDocumentException(ErrorCode.DOCUMENT_IS_PROTECTED, "Document is protected.");
+ }
+ throw new PDFDocumentException(ErrorCode.DOCUMENT_CANNOT_BE_READ, "Unable to parse document.");
+ } finally {
+ IOUtils.closeQuietly(inputStream);
+ closeQuietly(reader);
+ }
+ }
+
+ /**
+ * Quietly closes a pdf reader.
+ *
+ * @param reader
+ * The reader.
+ */
+ public static void closeQuietly(PdfReader reader) {
+ if (reader != null) {
+ try {
+ reader.close();
+ } catch (Throwable e) {
+ // ignore
+ }
+ }
+ }
+
+ /**
+ * Quietly closes a pdf document.
+ *
+ * @param pdDocument
+ * The pdf document.
+ */
+ public static void closeQuietly(PDDocument pdDocument) {
+ if (pdDocument != null) {
+ try {
+ pdDocument.close();
+ } catch (Throwable e) {
+ // ignore
+ }
+ }
+ }
+
+ /**
+ * Quietly closes a pdf document.
+ *
+ * @param pdDocument
+ * The pdf document.
+ */
+ public static void closeQuietly(org.pdfbox.pdmodel.PDDocument pdDocument) {
+ if (pdDocument != null) {
+ try {
+ pdDocument.close();
+ } catch (Throwable e) {
+ // ignore
+ }
+ }
+ }
+
+ /**
+ * Quietly closes a pdf document.
+ *
+ * @param pdDocument
+ * The pdf document.
+ */
+ public static void closeQuietly(Document doc) {
+ if (doc != null) {
+ try {
+ doc.close();
+ } catch (Throwable e) {
+ // ignore
+ }
+ }
+ }
+
+ 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;
+ }
+
+ /**
+ * Returns {@code true} if the given {@code profileId} is PDF/A-1b enabled, {@code false} if not.
+ *
+ * @param profileId
+ * The signature profile.
+ * @return {@code true} if the given {@code profileId} is PDF/A-1b enabled, {@code false} if not.
+ */
+ public static boolean isPdfAEnabled(String profileId) {
+ if (profileId == null) {
+ throw new NullPointerException("Profile identifier must not be null.");
+ }
+ if (StringUtils.isEmpty(profileId)) {
+ throw new IllegalArgumentException("Profile identifier must not be empty.");
+ }
+ try {
+ String pdfa = SettingsReader.getInstance().getSetting("sig_obj." + profileId + ".key." + CFG_KEY_PDFA,
+ "default." + CFG_KEY_PDFA, "false");
+ return BooleanUtils.toBoolean(pdfa);
+ } catch (Exception e) {
+ log.error("Unable to read settings for PDF/A functionality.", e);
+ return false;
+ }
+ }
+
}