aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/at/knowcenter/wag/egov/egiz/pdf/BinarySignature.java
diff options
context:
space:
mode:
authortknall <tknall@7b5415b0-85f9-ee4d-85bd-d5d0c3b42d1c>2013-01-09 15:41:29 +0000
committertknall <tknall@7b5415b0-85f9-ee4d-85bd-d5d0c3b42d1c>2013-01-09 15:41:29 +0000
commit535a04fa05f739ec16dd81666e3b0f82dfbd442d (patch)
tree0804f301c1a9ceb303a8441b7b29244fc8eb7ff0 /src/main/java/at/knowcenter/wag/egov/egiz/pdf/BinarySignature.java
parent1efaf6fd5619dfa95c9d7e8c71eda4c2ffba4998 (diff)
downloadpdf-as-3-535a04fa05f739ec16dd81666e3b0f82dfbd442d.tar.gz
pdf-as-3-535a04fa05f739ec16dd81666e3b0f82dfbd442d.tar.bz2
pdf-as-3-535a04fa05f739ec16dd81666e3b0f82dfbd442d.zip
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
Diffstat (limited to 'src/main/java/at/knowcenter/wag/egov/egiz/pdf/BinarySignature.java')
-rw-r--r--src/main/java/at/knowcenter/wag/egov/egiz/pdf/BinarySignature.java2145
1 files changed, 0 insertions, 2145 deletions
diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/pdf/BinarySignature.java b/src/main/java/at/knowcenter/wag/egov/egiz/pdf/BinarySignature.java
deleted file mode 100644
index ece9525..0000000
--- a/src/main/java/at/knowcenter/wag/egov/egiz/pdf/BinarySignature.java
+++ /dev/null
@@ -1,2145 +0,0 @@
-/**
- * <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.
- *
- * $Id: BinarySignature.java,v 1.4 2006/10/11 07:57:58 wprinz Exp $
- */
-package at.knowcenter.wag.egov.egiz.pdf;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.UnsupportedEncodingException;
-import java.net.MalformedURLException;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.List;
-
-import org.apache.commons.lang.ArrayUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import at.gv.egiz.pdfas.api.timestamp.TimeStamper;
-import at.gv.egiz.pdfas.exceptions.ErrorCode;
-import at.gv.egiz.pdfas.exceptions.pdf.CaptionNotFoundException;
-import at.gv.egiz.pdfas.exceptions.pdf.KZSettingNotFoundException;
-import at.gv.egiz.pdfas.framework.input.PdfDataSource;
-import at.gv.egiz.pdfas.framework.output.DataSink;
-import at.gv.egiz.pdfas.framework.signator.SignatorInformation;
-import at.gv.egiz.pdfas.placeholder.SignaturePlaceholderContext;
-import at.gv.egiz.pdfas.placeholder.SignaturePlaceholderData;
-import at.gv.egiz.pdfas.utils.PDFASUtils;
-import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
-import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException;
-import at.knowcenter.wag.egov.egiz.exceptions.PlaceholderException;
-import at.knowcenter.wag.egov.egiz.exceptions.PresentableException;
-import at.knowcenter.wag.egov.egiz.exceptions.SettingNotFoundException;
-import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
-import at.knowcenter.wag.egov.egiz.sig.SignatureFieldDefinition;
-import at.knowcenter.wag.egov.egiz.sig.SignatureObject;
-import at.knowcenter.wag.egov.egiz.sig.SignatureTypeDefinition;
-import at.knowcenter.wag.egov.egiz.sig.SignatureTypes;
-import at.knowcenter.wag.egov.egiz.tools.CodingHelper;
-import at.knowcenter.wag.exactparser.ByteArrayUtils;
-
-import com.lowagie.text.BadElementException;
-import com.lowagie.text.Document;
-import com.lowagie.text.DocumentException;
-import com.lowagie.text.Image;
-import com.lowagie.text.Rectangle;
-import com.lowagie.text.pdf.BadPdfFormatException;
-import com.lowagie.text.pdf.PRStream;
-import com.lowagie.text.pdf.PdfArray;
-import com.lowagie.text.pdf.PdfContentByte;
-import com.lowagie.text.pdf.PdfDictionary;
-import com.lowagie.text.pdf.PdfImage;
-import com.lowagie.text.pdf.PdfIndirectObject;
-import com.lowagie.text.pdf.PdfIndirectReference;
-import com.lowagie.text.pdf.PdfName;
-import com.lowagie.text.pdf.PdfNumber;
-import com.lowagie.text.pdf.PdfObject;
-import com.lowagie.text.pdf.PdfPTable;
-import com.lowagie.text.pdf.PdfReader;
-import com.lowagie.text.pdf.PdfStamper;
-import com.lowagie.text.pdf.PdfStamperImp;
-import com.lowagie.text.pdf.PdfString;
-import com.lowagie.text.pdf.PdfTemplate;
-
-/**
- * Contains various extension functions to digitally sign documents.
- *
- * <p>
- * These functions are used to replace parts of the original Egiz plain text
- * signature mechanism.
- * </p>
- *
- * @author wprinz
- */
-public abstract class BinarySignature
-{
-//23.11.2010 changed by exthex - added replacePlaceholder(PdfStamper stamper, int pageNr, String placeholderName) method
-
- protected static Log logger = LogFactory.getLog(BinarySignature.class);
- /**
- * The tolerance area of the line break algorithm.
- *
- * @see Placeholder#replacePlaceholderWithTolerance(byte[], List, byte[], int)
- */
- public static final int LINE_BREAK_TOLERANCE = 10;
-
- /**
- * The number of bytes left out for the certificate placeholder.
- */
- public static final int CERTIFICATE_PLACEHOLDER_LENGTH = 10000;
-
- /**
- * The number of bytes left out for the timestamp placeholder.
- */
- public static final int TIMESTAMP_PLACEHOLDER_LENGTH = 5000;
-
- /**
- * The placeholder character used to fill out Strings in the layout process.
- */
- public static final byte LAYOUT_PLACEHOLDER = 'w';
-
- /**
- * This placeholder is used to fill out holes between the byte ranges before
- * the document is signed.
- */
- public static final byte SIGN_PLACEHOLDER = 0;
-
- /**
- * The nil brev used to define an unrecognized value.
- */
- public static final byte[] BREV_NIL = { 'n', 'i', 'l' };
-
- /**
- * The date brev.
- */
- public static final byte[] BREV_DAT = { 'd', 'a', 't' };
-
- /**
- * The issure brev.
- */
- public static final byte[] BREV_ISS = { 'i', 's', 's' };
-
- /**
- * The serial number brev.
- */
- public static final byte[] BREV_SNR = { 's', 'n', 'r' };
-
- /**
- * The value brev.
- */
- public static final byte[] BREV_VAL = { 'v', 'a', 'l' };
-
- /**
- * The SIG_ID brev.
- */
- public static final byte[] BREV_SID = { 's', 'i', 'd' };
-
- /**
- * The SIG_ALG brev.
- */
- public static final byte[] BREV_ALG = { 'a', 'l', 'g' };
-
- /**
- * No explicit encoding.
- */
- public static final byte[] ENCODING_NIL = { 'n', 'i', 'l' };
-
- /**
- * PDF WinAnsiEncoding.
- */
- public static final byte[] ENCODING_WIN = { 'w', 'i', 'n' };
-
- /**
- * URL encoding.
- */
- public static final byte[] ENCODING_URL = { 'u', 'r', 'l' };
-
- /**
- * The PDFName of the Egiz Dictionary.
- *
- * <p>
- * Used to locate and identify the Egiz Dictionary in the document.
- * </p>
- */
- public static final PdfName EGIZ_DICT_NAME = new PdfName("EGIZSigDict");
-
- /**
- * The PDFName of the Original Document Size (ODS) field in an Egiz
- * Dictionary.
- *
- * <p>
- * The ODS must be a positive integral number.
- * </p>
- */
- public static final PdfName EGIZ_ODS_NAME = new PdfName("ODS");
-
- /**
- * The PDFName of the Kennzeichnung attribute.
- */
- public static final PdfName EGIZ_KZ_NAME = new PdfName("ID");
-
- /**
- * The PDFName of the /replaces field in an Egiz Dictionary.
- */
- public static final PdfName EGIZ_REPLACES_NAME = new PdfName("replaces");
-
- /**
- * The PDFName of the /encodings field in an Egiz Dictionary.
- */
- public static final PdfName EGIZ_ENCODINGS_NAME = new PdfName("encodings");
-
- /**
- * The PDFName of the byte ranges array.
- */
- public static final PdfName EGIZ_BYTERANGES_NAME = new PdfName("ByteRange");
-
- /**
- * The PdfName of the certificate array.
- */
- public static final PdfName EGIZ_CERTIFICATE_NAME = new PdfName("Cert");
-
- /**
- * The PdfName of the Timestamp
- */
- public static final PdfName EGIZ_TIMESTAMP_NAME = new PdfName("TimeStamp");
-
- /**
- * The PdfName of the data array that contains various egiz-dict data.
- */
- public static final PdfName EGIZ_DATA_NAME = new PdfName("Data");
-
- /**
- * The PDFName of the Signature XObject field in an Egiz Dictionary.
- *
- * <p>
- * This must be an indirect reference to the XObject containing the Signature
- * table.
- * </p>
- */
- public static final PdfName EGIZ_XOBJ_NAME = new PdfName("SigXObject");
-
- /**
- * The number placeholder that is used to give numbers a fixed length.
- */
- protected static final PdfNumber NUMBER_PLACEHOLDER = new PdfNumber(999999999);
-
- /**
- * Extracts the signature text only.
- *
- * <p>
- * The signature text is the text of the Signature XObject.
- * </p>
- *
- * @param egiz_dict
- * The Egiz Dictionary.
- *
- * @return Returns the signature text.
- */
- public static String extractSignatureTextOnly(PdfDictionary egiz_dict) throws IOException
- {
- PdfIndirectReference xobj_ir = (PdfIndirectReference) egiz_dict.get(EGIZ_XOBJ_NAME);
- PRStream temp_stream = (PRStream) PdfReader.getPdfObject(xobj_ir);
-
- byte[] stream_bytes = PdfReader.getStreamBytes(temp_stream);
-
- return Utils.extractPureTextFromContentStream(stream_bytes);
- }
-
- /**
- * Retrieves the size of the original document from the Egiz Dictionary.
- *
- * @param egiz_dict
- * The Egiz Dictionary.
- * @return Returns the size (in bytes) of the original document.
- */
- public static int getOriginalDocumentSizeFromEgizDict(PdfDictionary egiz_dict)
- {
- PdfObject ods_obj = egiz_dict.get(EGIZ_ODS_NAME);
- PdfNumber ods_number = (PdfNumber) PdfReader.getPdfObject(ods_obj);
-
- return ods_number.intValue();
- }
-
- /**
- * Retrieves the previous Egiz dictionary from the given one, if a previous
- * dictionary exists.
- *
- * @param egiz_dict
- * The Egiz Dictionary.
- * @return Returns the previous Egiz Dictionary, or null if there is none.
- */
- public static PdfDictionary getPreviousFromEgizDict(PdfDictionary egiz_dict)
- {
- PdfObject prev_obj = egiz_dict.get(PdfName.PREV);
- PdfDictionary previous_dict = (PdfDictionary) PdfReader.getPdfObject(prev_obj);
- return previous_dict;
- }
-
- /**
- * Retrieves the Egiz Dictionary from the document if present.
- *
- * @param reader
- * The reader to retrieve the dictionary from.
- * @return Returns the Egiz Dictionary, if present, or returns null, if no
- * egiz dictionary was found.
- */
- public static PdfDictionary getEgizDictFromReader(PdfReader reader)
- {
- PdfIndirectReference dict_ir = getEgizDictIndRefFromReader(reader);
- if (dict_ir == null)
- {
- return null;
- }
-
- PdfDictionary egiz_dict = (PdfDictionary) PdfReader.getPdfObject(dict_ir);
-
- return egiz_dict;
- }
-
- /**
- * Retrieves the Egiz Dictionary's indirect reference from the reader.
- *
- * @param reader
- * The reader.
- * @return Returns the indirect reference of the Egiz Dictionary, or null, if
- * none exists.
- */
- public static PdfIndirectReference getEgizDictIndRefFromReader(PdfReader reader)
- {
- PdfDictionary catalog = reader.getCatalog();
- PdfIndirectReference dict_ir = (PdfIndirectReference) catalog.get(EGIZ_DICT_NAME);
- return dict_ir;
- }
-
- /**
- * Retrieves the chain of Egiz Dictionaries from the reader.
- *
- * <p>
- * The first element in the List will be the top most (oldest) Egiz
- * Dictionary. The last element in the List will be the bottom most (latest)
- * Egiz Dictionary. If the list is empty, no dictionary could be found at all,
- * which means that the document is not digitally signed.
- * </p>
- *
- * @param reader
- * The reader.
- * @return Returns the List of PdfDictionaries from the document.
- */
- public static List getEgizDictChainFromReader(PdfReader reader)
- {
- List dicts = new ArrayList();
-
- PdfDictionary current_dict = getEgizDictFromReader(reader);
- if (current_dict != null)
- {
- dicts.add(0, current_dict);
-
- while ((current_dict = getPreviousFromEgizDict(current_dict)) != null)
- {
- dicts.add(0, current_dict);
- }
- }
-
- return dicts;
- }
-
- /**
- * Builds a digest of the given data.
- *
- * @param data
- * The data to be digested.
- * @param length
- * The length of the data portion that should be used for digesting.
- * This allows to build the digest only over parts of the data.
- * @return Returns the created digest.
- * @throws PDFDocumentException
- * Forwarded exception.
- */
- public static byte[] buildDigest(final byte[] data, final int length) throws PDFDocumentException
- {
- MessageDigest sha_512 = null;
- try
- {
- sha_512 = MessageDigest.getInstance("SHA-512");
- }
- catch (NoSuchAlgorithmException e)
- {
- e.printStackTrace();
- throw new PDFDocumentException(202, "Digest algorithm not supported - NoSuchAlgorithmException", e);
- }
-
- sha_512.reset();
- sha_512.update(data, 0, length);
- byte[] digest = sha_512.digest();
-
- return digest;
- }
-
- /**
- * Retrieves the signable text from the given document.
- *
- * @param data
- * The data.
- * @param ods
- * The original document size.
- * @return Returns the signable text.
- */
- public static String retrieveSignableTextFromData(final byte[] data, final int ods)
- {
- // byte[] digest = buildDigest(data, ods);
- String raw_text = CodingHelper.encodeBase64(data);// digest); // data);
-
- return raw_text;
- }
-
- /**
- * Fills the holes in the byte ranges with the SIGN_PLACEHOLDER.
- *
- * @param data
- * The given byte ranged data.
- * @param byte_ranges
- * The byte ranges.
- * @return Returns the filled text.
- */
- public static byte[] prepareDataToSign(final byte[] data, final List byte_ranges)
- {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- Iterator it = byte_ranges.iterator();
- int last_end = 0;
- while (it.hasNext())
- {
- StringInfo si = (StringInfo) it.next();
-
- for (int i = last_end; i < si.string_start; i++)
- {
- baos.write(SIGN_PLACEHOLDER);
- }
-
- baos.write(data, si.string_start, si.string_length);
-
- last_end = si.string_start + si.string_length;
- }
- byte[] data_to_sign = baos.toByteArray();
-
- return data_to_sign;
- }
-
- // TODO old code - remove
- // /**
- // * Extracts the binary 'text' of a document.
- // *
- // * <p>
- // * If the document contains an Egiz Dictionary, which means that it is
- // already
- // * signed, the binary text is the Base64 coded string of the original
- // document
- // * followed by the Ascii representation of the signature block.
- // * </p>
- // * <p>
- // * If the document does not contain an Egiz Dictionary, which means that it
- // is
- // * unsigned, only the binary Base64 coded original document is returned as
- // * binary text.
- // * </p>
- // * <p>
- // * This function is intented for being used instead of the "text extraction"
- // * mechanism used in the plain text Egiz project.
- // * </p>
- // *
- // * @param doc
- // * The file.
- // * @return Returns the binary text of the document.
- // * @throws PDFDocumentException
- // * Forwarded exception.
- // */
- // public static String extractTextBinary(File doc) throws
- // PDFDocumentException
- // {
- // try
- // {
- // FileInputStream fis = new FileInputStream(doc);
- // return extractTextBinary(fis);
- // }
- // catch (FileNotFoundException e)
- // {
- // throw new PDFDocumentException(202, e);
- // }
- // }
- //
- // /**
- // * Extracts the text binary.
- // *
- // * @param is
- // * @return Returns the binary text.
- // * @throws PDFDocumentException
- // */
- // public static String extractTextBinary(InputStream is) throws
- // PDFDocumentException
- // {
- // try
- // {
- // // for some stupid reason this produces a read error if the is comes from
- // // a
- // // multipart servlet form..???
- // ByteArrayOutputStream baos = new ByteArrayOutputStream();
- // int i = -1;
- // int acc = 0;
- // byte[] b = new byte[1000];
- // while ((i = is.read(b)) > 0)
- // {
- // acc += i;
- // System.out.print(" " + i);
- // baos.write(b, 0, i);
- // }
- // System.out.println("acc = " + acc);
- // byte[] pdf = baos.toByteArray();
- //
- // return extractTextBinary(pdf);
- // }
- // catch (IOException e)
- // {
- // throw new PDFDocumentException(202, e);
- // }
- // }
- //
- // /**
- // * Extracts the signable text from a binary pdf document.
- // *
- // * <p>
- // * The signable text is the text that will be signed or verified afterwards.
- // * </p>
- // *
- // * @param pdf
- // * The pdf document.
- // * @return Returns the extracted text String.
- // * @throws PDFDocumentException
- // * Forwarded exception.
- // */
- // public static String extractTextBinary(final byte[] pdf) throws
- // PDFDocumentException
- // {
- // try
- // {
- // PdfReader reader = new PdfReader(new ByteArrayInputStream(pdf));
- // PdfDictionary egiz_dict = getEgizDictFromReader(reader);
- // if (egiz_dict == null)
- // {
- // System.out.println("NO Egiz Dict found - whole doc = original doc");
- //
- // int ods = pdf.length;
- // return retrieveSignableTextFromData(pdf, ods);
- // }
- //
- // String sig_text = extractSignatureTextOnly(egiz_dict);
- //
- // int ods = getOriginalDocumentSizeFromEgizDict(egiz_dict);
- //
- // String raw_text = retrieveSignableTextFromData(pdf, ods);
- // raw_text += "\n";
- // raw_text += sig_text;
- //
- // return raw_text;
- // }
- // catch (IOException e)
- // {
- // throw new PDFDocumentException(202, e);
- // }
- // }
-
- // TODO obsolete code - remove
- // /**
- // * Retrieves the List of SignatureHolders containing the information of all
- // * digital signatures of the given document.
- // *
- // * <p>
- // * If the List of SignatureHolders is empty, the document is not signed
- // * anyways.
- // * </p>
- // *
- // * @param pdf
- // * The complete pdf document.
- // * @return Returns the List of SignatureHolders.
- // * @throws PDFDocumentException
- // * @throws SignatureTypesException
- // * @throws SignatureException
- // */
- // public static List extractSignatureHoldersBinary(final byte[] pdf) throws
- // PDFDocumentException, SignatureTypesException, SignatureException
- // {
- // try
- // {
- // PdfReader reader = new PdfReader(new ByteArrayInputStream(pdf));
- // List chain = getEgizDictChainFromReader(reader);
- //
- // List signatures = new ArrayList();
- // Iterator it = chain.iterator();
- // while (it.hasNext())
- // {
- // PdfDictionary dict = (PdfDictionary) it.next();
- //
- // int ods = getOriginalDocumentSizeFromEgizDict(dict);
- // String signature_text = extractSignatureTextOnly(dict);
- //
- // SignatureTypes sig_types = SignatureTypes.getInstance();
- // List types = sig_types.getSignatureTypeDefinitions();
- // SignatureBlock sig_block = new SignatureBlock(types);
- // boolean could_separate = sig_block.separateBlockFromRawText(signature_text,
- // false);
- //
- // if (could_separate)
- // {
- // SignatureObject sig_object = sig_block.getSignatureObject();
- //
- // SignatureHolder holder = new BinarySignatureHolder(pdf, ods, sig_object);
- // signatures.add(holder);
- // }
- // }
- //
- // return signatures;
- // }
- // catch (IOException e)
- // {
- // throw new PDFDocumentException(201, e);
- // }
- // }
-
- // /**
- // * Signs a document with the given signature table using the Incremental
- // * Update method.
- // *
- // * <p>
- // * The table containing the signature text will be appended. As specified by
- // * the parameters, the signature will be appended to the last page, or a
- // plain
- // * new page will be created for the signature to hold.
- // * </p>
- // * <p>
- // * The table will be completely wrapped by an XObject, which will also be
- // * indirectly referenced by the Egiz Dictionary. This will ease the
- // * verification process.
- // * </p>
- // * <p>
- // * An Egiz Dictionary will be added to the new document that contains
- // * information about the signature. Basically the size of the original
- // * document and the reference of the signature table.
- // * </p>
- // *
- // * @param original_document
- // * The file name of the original document.
- // * @param new_document
- // * The file name of the new document to be created.
- // * @param pdf_table
- // * The PdfPTable that contains the signature block.
- // * @param pos_x
- // * The x position where the table should be inserted.
- // * @param pos_y
- // * The y position where the table should be inserted (on the last
- // * page). If this is negative, a new page will be appended to the
- // * document. Then the table will be inserted on that new page using
- // * the absolute value of pos_y. Note that pos_y specifies the top
- // * line of the table.
- // * @throws PresentableException
- // * Forwarded exception.
- // *
- // * @see #writeIncrementalUpdate(byte[], PdfPTable, float, float, boolean)
- // */
- // public static void writeIncrementalUpdate(String original_document,
- // String new_document, PdfPTable pdf_table, float pos_x, float pos_y,
- // int egiz_dict_num_replaces) throws PresentableException
- // {
- // try
- // {
- // File original_document_file = new File(original_document);
- // FileInputStream fis = new FileInputStream(original_document_file);
- // byte[] pdf = new byte[(int) original_document_file.length()];
- // fis.read(pdf);
- // fis.close();
- //
- // byte[] signed_pdf = writeIncrementalUpdate(pdf, pdf_table, pos_x, pos_y,
- // egiz_dict_num_replaces);
- //
- // File new_document_file = new File(new_document);
- // FileOutputStream fos = new FileOutputStream(new_document_file);
- // fos.write(signed_pdf);
- // fos.close();
- // }
- // catch (IOException e)
- // {
- // throw new PresentableException(e);
- // }
- // }
-
- protected static int getLineBreakTolerance(IncrementalUpdateInformation iui) throws PDFDocumentException
- {
- SettingsReader settings;
- try
- {
- settings = SettingsReader.getInstance();
- }
- catch (SettingsException e)
- {
- throw new PDFDocumentException(e.getErrorCode(), e);
- }
- String phLineBreakTolerance = SignatureTypeDefinition.readPhLenStringFromSettings(settings, iui.signProfile, "line_break_tolerance");
- int lineBreakTolerance = LINE_BREAK_TOLERANCE;
- if (phLineBreakTolerance != null)
- {
- lineBreakTolerance = Integer.parseInt(phLineBreakTolerance);
- }
- return lineBreakTolerance;
- }
-
- protected static int getCertificatePlaceholderLength(IncrementalUpdateInformation iui) throws SettingNotFoundException
- {
- SettingsReader settings;
- try
- {
- settings = SettingsReader.getInstance();
- }
- catch (SettingsException e)
- {
- throw new SettingNotFoundException(e);
- }
- String certPhLen = SignatureTypeDefinition.readPhLenStringFromSettings(settings, iui.signProfile, "certificate");
- int certLen = CERTIFICATE_PLACEHOLDER_LENGTH;
- if (certPhLen != null)
- {
- certLen = Integer.parseInt(certPhLen);
- }
- return certLen;
- }
-
- protected static int getTimestampPlaceholderLength(IncrementalUpdateInformation iui) throws SettingNotFoundException
- {
- SettingsReader settings;
- try
- {
- settings = SettingsReader.getInstance();
- }
- catch (SettingsException e)
- {
- throw new SettingNotFoundException(e);
- }
- String phLen = SignatureTypeDefinition.readPhLenStringFromSettings(settings, iui.signProfile, "timestamp");
- int tsLen = TIMESTAMP_PLACEHOLDER_LENGTH;
- if (phLen != null)
- {
- tsLen = Integer.parseInt(phLen);
- }
- return tsLen;
- }
-
- /**
- * Signs a document with the given signature table using the Incremental
- * Update method.
- *
- * <p>
- * The table containing the signature text will be appended. As specified by
- * the parameters, the signature will be appended to the last page, or a plain
- * new page will be created for the signature to hold.
- * </p>
- * <p>
- * The table will be completely wrapped by an XObject, which will also be
- * indirectly referenced by the Egiz Dictionary. This will ease the
- * verification process.
- * </p>
- * <p>
- * An Egiz Dictionary will be added to the new document that contains
- * information about the signature. Basically the size of the original
- * document and the reference of the signature table.
- * </p>
- *
- * @param original_document
- * The original document.
- * @param pdf_table
- * The PdfPTable that contains the signature block.
- * @param pi
- * The PositioningInstruction telling the algorithm where to place
- * the signature block.
- * @param invisible_field_definitions
- * List of invisible field definitions to be added to the egiz dict.
- * May be null or empty, if there are no invisible fields.
- * @param invisibleKZString
- * If not null, thins String is the KZ String to be written into the
- * /Data array.
- * @return Returns the new document.
- * @throws PresentableException
- * Forwarded exception.
- */
- public static IncrementalUpdateInformation writeIncrementalUpdate(PdfDataSource original_document, DataSink written_pdf, PdfPTable pdf_table, String profile, PositioningInstruction pi,
- List variable_field_definitions, List all_field_definitions, List invisible_field_definitions, String invisibleKZString, TimeStamper timeStamper, SignatorInformation si, SignatureObject so) throws PresentableException
- {
- try
- {
- IncrementalUpdateInformation iui = new IncrementalUpdateInformation();
- iui.original_document = original_document;
- iui.start_index = original_document.getLength();
- iui.signProfile = profile;
- iui.timeStamper = timeStamper;
-
- Document.compress = true; // exthex : compress now, excluding the xobject later
-
- // System.out.println("wprinz: STAMPING PDF");
-
- // InputStream is = original_document.createInputStream();
- byte[] pdf_data = original_document.getAsByteArray();
- PdfReader reader = new PdfReader(pdf_data);
- PDFASUtils.checkReaderPermissions(reader);
- // is.close();
-
- OutputStream baos = written_pdf.createOutputStream("application/pdf");
- // ByteArrayOutputStream baos = new ByteArrayOutputStream();
-
- // IMPORTANT: append the new content to the original document using
- // incremental updated
- // The stamper allows this by setting append = true
- boolean adobeSigField = AdobeSignatureHelper.isAdobeSignatureFieldEnabled(so.getSignatureTypeDefinition().getType());
- PdfStamper stamper = null;
- if (adobeSigField) {
- stamper = PdfStamper.createSignature(reader, baos, '\0', null, true);
- } else {
- stamper = new PdfStamper(reader, baos, '\0', true);
- }
-
- if (pi.isMakeNewPage())
- {
- int pdf_page_num = reader.getNumberOfPages();
-
- Rectangle psize = reader.getPageSizeWithRotation(pdf_page_num);
- Rectangle rect = new Rectangle(psize);
- stamper.insertPage(pdf_page_num + 1, rect);
- }
-
- if (pi.getPage() < 1 || pi.getPage() > stamper.getReader().getNumberOfPages())
- {
- throw new PDFDocumentException(224, "The provided page (=" + pi.getPage() + ") is out of range.");
- }
-
- if (SignaturePlaceholderContext.isSignaturePlaceholderDataSet() &&
- SignaturePlaceholderContext.getSignaturePlaceholderData().getPlaceholderName() != null)
- {
- replacePlaceholder(stamper, pi.getPage(), SignaturePlaceholderContext.getSignaturePlaceholderData().getPlaceholderName());
- }
-
- PdfContentByte content = stamper.getOverContent(pi.getPage());
- // content = StampContent einer PageStamp.
-
- // System.out.println("table_width = " + pdf_table.getTotalWidth() + ",
- // table_height = " + pdf_table.getTotalHeight());
-
- PdfTemplate table_template = content.createTemplate(pdf_table.getTotalWidth(), pdf_table.getTotalHeight());
- table_template.setCompress(Boolean.FALSE); // do not compress sigblock because we rewrite it afterwards for bin sig
-
- // exthex
- StructContentHelper structHelper = new StructContentHelper(stamper, content, pi.getPage());
- structHelper.prepareStructData(table_template);
-
- pdf_table.writeSelectedRows(0, -1, 0, pdf_table.getTotalHeight(), table_template);
-
- // table_template.moveTo(0, 0);
- // table_template.lineTo(pdf_table.getTotalWidth(),
- // pdf_table.getTotalHeight());
- // table_template.stroke();
- // table_template.moveTo(0, 0);
- // table_template.lineTo(100, 100);
- // table_template.stroke();
-
- // pdf_table.writeSelectedRows(0, -1, SIGNATURE_BORDER / 2,
- // table_position, content);
-
-
- structHelper.beginSigBlockContent();
-
- content.addTemplate(table_template, pi.getX(), pi.getY() - pdf_table.getTotalHeight());
-
- structHelper.endSigBlockContent();
-
-
- ActualTablePos atp = new ActualTablePos();
- atp.page = pi.getPage();
- atp.x = pi.getX();
- atp.y = pi.getY(); // TODO is this correct or flipped?
- atp.width = pdf_table.getTotalWidth();
- atp.height = pdf_table.getTotalHeight();
- iui.actualTablePos = atp;
-
- structHelper.buildFigureStructData(so, table_template);
- structHelper.buildSigBlockStructData();
- structHelper.finishMainStructData();
-
- structHelper.buildVerifyLinkStructData(table_template, atp);
-
- // For debugging print a 100x100 grid
- // {
- // Rectangle psize = reader.getPageSizeWithRotation(pos.page);
- // float page_width = psize.width();
- // float page_height = psize.height();
- // for (float x = 0; x < page_width; x += 100)
- // {
- // content.moveTo(x, 0);
- // content.lineTo(x, page_height);
- // content.stroke();
- // }
- // for (float y = 0; y < page_height; y += 100)
- // {
- // content.moveTo(0, y);
- // content.lineTo(page_width, y);
- // content.stroke();
- // }
- // }
-
- // content.setLineWidth(10.0f);
- // content.moveTo(0, 0);
- // content.lineTo(100, 100);
- // content.stroke();
-
- // PdfIndirectReference page_ref =
- // stamper.getWriter().getPageReference(signature_page);
- // System.out.println("page_ref = " + page_ref.toString());
-
- // PdfObject page_obj = PdfReader.getPdfObject(page_ref);
- // System.out.println("page_obj = " + page_obj);
-
- // PdfDictionary page_dict = (PdfDictionary) page_obj;
- // PdfObject resources_obj = page_dict.get(PdfName.RESOURCES);
- // System.out.println("resources_obj = " + resources_obj);
- // PdfDictionary resources = (PdfDictionary)
- // PdfReader.getPdfObject(resources_obj);
- // for (Iterator it = resources.getKeys().iterator(); it.hasNext();)
- // {
- // PdfName key = (PdfName) it.next();
- // PdfObject value = resources.get(key);
- // System.out.println(" " + key + " = " + value);
- // }
-
- // add the EGIZ dict:
- if (variable_field_definitions != null)
- {
- createEgizDict(stamper, table_template, iui, variable_field_definitions, all_field_definitions, invisible_field_definitions, invisibleKZString);
- }
-
- if (adobeSigField) {
- AdobeSignatureHelper.createAdobeSignatureField(stamper, si, so, atp, structHelper); // here..., stamper is closed
- } else {
- stamper.close();
- }
- // System.out.println("wprinz: STAMPING FINISHED");
-
- // just to make sure the stream is really closed
- baos.close();//
- //org.apache.commons.io.FileUtils.writeByteArrayToFile(new java.io.File("C:/out.pdf"), ((at.gv.egiz.pdfas.impl.output.ByteArrayDataSink) written_pdf).getByteArray());
- // iui.signed_pdf = baos.toByteArray();
-
- structHelper.removeCurrent();
- return iui;
- }
- catch (IOException e)
- {
- e.printStackTrace();
- throw new PresentableException(ErrorCode.CANNOT_WRITE_PDF, e);
- }
- catch (DocumentException e)
- {
- e.printStackTrace();
- throw new PresentableException(ErrorCode.CANNOT_WRITE_PDF, e);
- }
- }
-
- private static void replacePlaceholder(PdfStamper stamper, int pageNr, String placeholderName) throws BadElementException, MalformedURLException, IOException, BadPdfFormatException, PresentableException {
- Image img = Image.getInstance(SignaturePlaceholderData.class.getResource("empty.jpg"));
- PdfImage pImg = new PdfImage(img, "Imwurscht", null);
- PdfStamperImp stamperImp = (PdfStamperImp)stamper.getWriter();
- PdfIndirectObject ind = stamperImp.addToBody(pImg);
-
- PdfDictionary resources = stamper.getReader().getPageN(pageNr).getAsDict(PdfName.RESOURCES);
- if (ind != null && resources != null)
- {
- PdfDictionary xobjDict = resources.getAsDict(PdfName.XOBJECT);
- if (xobjDict != null)
- {
- xobjDict.put(new PdfName(placeholderName), ind.getIndirectReference());
- stamperImp.markUsed(resources);
- }
- else
- {
- throw new PresentableException(ErrorCode.CANNOT_WRITE_PDF, new NullPointerException("Image dictionary not found in document structure!"));
- }
- }
- else
- {
- throw new PresentableException(ErrorCode.CANNOT_WRITE_PDF, new NullPointerException("Resource dictionary not found in document structure!"));
- }
- }
-
-
- /**
- * Creates the EGIZ Dictionary and adds it to the document.
- *
- * @param stamper
- * The PdfStamper.
- * @param table_template
- * The Template of the Signature block.
- * @param iui
- * The IncrementalUpdateInformation.
- * @param variable_field_definitions
- * The field definitions.
- * @throws IOException
- * @throws SettingNotFoundException
- * @throws CaptionNotFoundException
- */
- protected static void createEgizDict(PdfStamper stamper, PdfTemplate table_template, IncrementalUpdateInformation iui, List variable_field_definitions, List all_field_definitions,
- List invisible_field_definitions, String invisibleKZString) throws IOException, SettingNotFoundException, CaptionNotFoundException
- {
- // iui.temp_ir = table_template.getIndirectReference();
- iui.temp_ir_number = table_template.getIndirectReference().getNumber();
- iui.temp_ir_generation = table_template.getIndirectReference().getGeneration();
-
- byte[] content_stream = table_template.toPdf(null);
- iui.content_stream_length = content_stream.length;
-
- iui.replaces = determineReplacesInContentStream(content_stream, 0, content_stream.length, variable_field_definitions);
- if (invisibleKZString == null)
- {
- iui.kz_list = determineKZ(content_stream, 0, content_stream.length, all_field_definitions);
- }
- else
- {
- StringInfo si = new StringInfo();
- si.string_start = -1;
- si.string_length = invisibleKZString.length();
-
- iui.kz_list = new ArrayList();
- iui.kz_list.add(si);
- }
-
- // PdfIndirectReference previous_egiz_dict_ind_ref =
- // getEgizDictIndRefFromReader(reader);
-
- PdfDictionary egiz_dict = new PdfDictionary(EGIZ_DICT_NAME);
- egiz_dict.put(EGIZ_XOBJ_NAME, table_template.getIndirectReference());
- egiz_dict.put(EGIZ_ODS_NAME, NUMBER_PLACEHOLDER);
-
- // /ID
- PdfArray kz_array = new PdfArray();
- for (int i = 0; i < iui.kz_list.size(); i++)
- {
- kz_array.add(NUMBER_PLACEHOLDER); // start
- kz_array.add(NUMBER_PLACEHOLDER); // length
- }
- egiz_dict.put(EGIZ_KZ_NAME, kz_array);
-
- // ByteRanges
- int num_replaces = calcNumReps(iui.replaces);
- int num_holes = num_replaces + 1 + 1;
- // +1 = the /encodings hole
- // +1 = the /Cert
- // +1 = the /Timestamp
- if (iui.timeStamper != null) {
- num_holes += 1;
- }
- boolean has_hidden_variable_fields = invisible_field_definitions != null && !invisible_field_definitions.isEmpty();
- if (has_hidden_variable_fields)
- {
- num_holes += invisible_field_definitions.size();
- }
- int num_byte_ranges = num_holes + 1;
-
- PdfArray byte_ranges_array = new PdfArray();
- for (int i = 0; i < num_byte_ranges; i++)
- {
- byte_ranges_array.add(NUMBER_PLACEHOLDER); // start
- byte_ranges_array.add(NUMBER_PLACEHOLDER); // length
- }
- egiz_dict.put(EGIZ_BYTERANGES_NAME, byte_ranges_array);
-
- PdfArray encodings_array = new PdfArray();
- encodings_array.add(new PdfName(new String(ENCODING_NIL))); // the
- // /encodings
- encodings_array.add(new PdfName(new String(ENCODING_NIL))); // the /Cert
-
- // array itself
- PdfArray replaces_array = new PdfArray();
- replaces_array.add(new PdfName(new String(BREV_NIL, "US-ASCII"))); // the
- // /encodings
- replaces_array.add(new PdfName(new String(BREV_NIL, "US-ASCII"))); // the
- // /Cert
-
- if (iui.timeStamper != null) {
- encodings_array.add(new PdfName(new String(ENCODING_NIL))); // the /Timestamp
- replaces_array.add(new PdfName(new String(BREV_NIL, "US-ASCII"))); // the /timestamp
-
- }
-
- // hidden replaces
- List hidden_replaces = null;
- if (has_hidden_variable_fields)
- {
- hidden_replaces = new ArrayList();
-
- Iterator it = invisible_field_definitions.iterator();
- while (it.hasNext())
- {
- SignatureFieldDefinition sfd = (SignatureFieldDefinition) it.next();
- byte[] brev = typeToBrev(sfd.field_name);
- encodings_array.add(new PdfName(new String(ENCODING_WIN, "US-ASCII")));
- replaces_array.add(new PdfName(new String(brev, "US-ASCII")));
-
- ReplaceInfo ri = new ReplaceInfo();
- ri.brev = brev;
- ri.enc = ENCODING_WIN;
- ri.sfd = sfd;
- ri.replaces = new ArrayList();
-
- StringInfo si = new StringInfo();
- si.string_start = -1; // to be determined later on
- si.string_length = sfd.placeholder_length;
- ri.replaces.add(si);
-
- hidden_replaces.add(ri);
- }
- }
-
- // content stream replaces
- Iterator it = iui.replaces.iterator();
- while (it.hasNext())
- {
- ReplaceInfo ri = (ReplaceInfo) it.next();
- for (int i = 0; i < ri.replaces.size(); i++)
- {
- byte[] brev = typeToBrev(ri.sfd.field_name);
- encodings_array.add(new PdfName(new String(ENCODING_WIN, "US-ASCII")));
- replaces_array.add(new PdfName(new String(brev, "US-ASCII")));
- }
- }
- egiz_dict.put(EGIZ_REPLACES_NAME, replaces_array);
-
- egiz_dict.put(EGIZ_ENCODINGS_NAME, encodings_array);
-
- PdfArray cert_array = new PdfArray();
- iui.cert_length = getCertificatePlaceholderLength(iui);
- byte[] cert_bytes = new byte[iui.cert_length];
- for (int i = 0; i < cert_bytes.length; i++)
- {
- cert_bytes[i] = 0;
- }
- PdfString cert_placeholder = new PdfString(cert_bytes);
- cert_array.add(cert_placeholder);
- egiz_dict.put(EGIZ_CERTIFICATE_NAME, cert_array);
-
- // Timestamp
- if (iui.timeStamper != null) {
- // only if handler is available
- PdfArray timestamp_array = new PdfArray();
- iui.timestamp_length = getTimestampPlaceholderLength(iui);
- byte[] timestamp_bytes = new byte[iui.timestamp_length];
- for (int i = 0; i < timestamp_bytes.length; i++)
- {
- timestamp_bytes[i] = 0;
- }
- PdfString timestamp_placeholder = new PdfString(timestamp_bytes);
- timestamp_array.add(timestamp_placeholder);
- egiz_dict.put(EGIZ_TIMESTAMP_NAME, timestamp_array);
- }
-
-
- // /Data array with hidden information
- if (has_hidden_variable_fields || invisibleKZString != null)
- {
- PdfArray hidden_fields_array = new PdfArray();
-
- if (invisibleKZString != null)
- {
- PdfString str = new PdfString(invisibleKZString);
- hidden_fields_array.add(str);
- }
-
- if (has_hidden_variable_fields)
- {
- iui.replaces.addAll(0, hidden_replaces);
-
- for (int i = 0; i < invisible_field_definitions.size(); i++)
- {
- SignatureFieldDefinition sfd = (SignatureFieldDefinition) invisible_field_definitions.get(i);
- byte[] placeholder = new byte[sfd.placeholder_length];
- for (int phIdx = 0; phIdx < placeholder.length; phIdx++)
- {
- placeholder[phIdx] = SIGN_PLACEHOLDER;
- }
- PdfString str = new PdfString(placeholder);
- hidden_fields_array.add(str);
- }
- }
-
- egiz_dict.put(EGIZ_DATA_NAME, hidden_fields_array);
- }
-
-
- PdfIndirectObject dict_ref = stamper.getWriter().addToBody(egiz_dict);
- // iui.egiz_dict_ir = dict_ref.getIndirectReference();
- iui.egiz_dict_ir_number = dict_ref.getIndirectReference().getNumber();
- iui.egiz_dict_ir_generation = dict_ref.getIndirectReference().getGeneration();
-
- PdfIndirectReference root_ref = (PdfIndirectReference) stamper.getReader().getTrailer().get(PdfName.ROOT);
- PdfDictionary root = (PdfDictionary) PdfReader.getPdfObject(root_ref);
- // root.put(EGIZ_DICT_NAME, dict_ref.getIndirectReference());
- ((PdfStamperImp) stamper.getWriter()).markUsed(root);
-
- // PdfDictionary extra_cata = stamper.getWriter().getExtraCatalog();
- // extra_cata.put(dict_type, dict_ref.getIndirectReference());
-
- ((PdfStamperImp) stamper.getWriter()).setEgizDictTrailerInfo(EGIZ_DICT_NAME, dict_ref.getIndirectReference());
- }
-
- /**
- * Converts a field name (type) to the corresponding BREV.
- *
- * @param type
- * The field name (type).
- * @return Returns the corresponding BREV, or BREV_NIL if the type is not
- * recognized.
- */
- protected static byte[] typeToBrev(String type)
- {
- if (type.equals(SignatureTypes.SIG_DATE))
- {
- return BREV_DAT;
- }
- if (type.equals(SignatureTypes.SIG_ISSUER))
- {
- return BREV_ISS;
- }
- if (type.equals(SignatureTypes.SIG_VALUE))
- {
- return BREV_VAL;
- }
- if (type.equals(SignatureTypes.SIG_NUMBER))
- {
- return BREV_SNR;
- }
- if (type.equals(SignatureTypes.SIG_ID))
- {
- return BREV_SID;
- }
- if (type.equals(SignatureTypes.SIG_ALG))
- {
- return BREV_ALG;
- }
-
-
- return BREV_NIL;
- }
-
- /**
- * Updates the information in the egiz dictionary to reflect the real offsets
- * of the byte ranges.
- *
- * <p>
- * This replaces the "dummy numbers" in the egiz dictionary with the correct
- * values.
- * </p>
- *
- * @param iui
- * The IncrementalUpdateInformation.
- * @throws PDFDocumentException
- */
- public static void markByteRanges(IncrementalUpdateInformation iui) throws PDFDocumentException
- {
- try
- {
- iui.byte_ranges = new ArrayList();
-
- int num_digits = Integer.toString(NUMBER_PLACEHOLDER.intValue()).length();
- byte[] signed_pdf = iui.signed_pdf;
-
- String str = iui.egiz_dict_ir_number + " " + iui.egiz_dict_ir_generation + " obj";
- byte[] obj_bytes = ArrayUtils.add(str.getBytes("US-ASCII"), 0, (byte) 0x0A);
- int obj_index = ByteArrayUtils.lastIndexOf(signed_pdf, obj_bytes);
- int obj_start = obj_index + obj_bytes.length;
-
- String ods_str = "/ODS ";
- byte[] ods_bytes = ods_str.getBytes("US-ASCII");
- int ods_index = ByteArrayUtils.indexOf(signed_pdf, obj_start, ods_bytes);
- int ods_start = ods_index + ods_bytes.length;
-
- String kz_str = "/ID[";
- byte[] kz_bytes = kz_str.getBytes("US-ASCII");
- int kz_index = ByteArrayUtils.indexOf(signed_pdf, obj_start, kz_bytes);
- int kz_start = kz_index + kz_bytes.length;
-
- String br_str = "/ByteRange[";
- byte[] br_bytes = br_str.getBytes("US-ASCII");
- int br_index = ByteArrayUtils.indexOf(signed_pdf, obj_start, br_bytes);
- int array_start = br_index + br_bytes.length;
-
- String enc_str = "/encodings[";
- byte[] enc_bytes = enc_str.getBytes("US-ASCII");
- int enc_index = ByteArrayUtils.indexOf(signed_pdf, obj_start, enc_bytes);
- int enc_start = enc_index + enc_bytes.length;
-
- String cert_str = "/Cert[(";
- byte[] cert_bytes = cert_str.getBytes("US-ASCII");
- int cert_index = ByteArrayUtils.indexOf(signed_pdf, obj_start, cert_bytes);
- int cert_start = cert_index + cert_bytes.length;
-
- //Timestamp
- int timestamp_index = 0;
- int timestamp_start = 0;
- if (iui.timeStamper != null) {
- String timestamp_str = "/TimeStamp[(";
- byte[] timestamp_bytes = timestamp_str.getBytes("US-ASCII");
- timestamp_index = ByteArrayUtils.indexOf(signed_pdf, obj_start, timestamp_bytes);
- timestamp_start = timestamp_index + timestamp_bytes.length;
- }
-
- replaceNumber(signed_pdf, ods_start, signed_pdf.length, num_digits);
-
-
- int cur_pos = array_start;
- int cur_br_start = 0;
-
-
- // write the /encodings byte range
- {
- int num_replaces = calcNumReps(iui.replaces);
- int num_holes = num_replaces + 1 + 1;
- // +1 = the /encodings hole
- // +1 = the /Cert
- // +1 = the /Timestamp
- if (iui.timeStamper != null) {
- num_holes += 1;
- }
-
- int enc_length = (1 + 3) * num_holes;
-
- StringInfo byte_range = new StringInfo();
- byte_range.string_start = cur_br_start;
- byte_range.string_length = enc_start;
- iui.byte_ranges.add(byte_range);
-
- replaceNumber(signed_pdf, cur_pos, byte_range.string_start, num_digits);
- cur_pos += num_digits;
- cur_pos += 1;
- replaceNumber(signed_pdf, cur_pos, byte_range.string_length, num_digits);
- cur_pos += num_digits;
- cur_pos += 1;
-
- cur_br_start = enc_start + enc_length;
-
- iui.enc_start = enc_start;
- iui.enc_length = enc_length;
- }
-
- // write the /Cert byte range
- {
- StringInfo byte_range = new StringInfo();
- byte_range.string_start = cur_br_start;
- byte_range.string_length = cert_start - cur_br_start;
- iui.byte_ranges.add(byte_range);
-
- replaceNumber(signed_pdf, cur_pos, byte_range.string_start, num_digits);
- cur_pos += num_digits;
- cur_pos += 1;
- replaceNumber(signed_pdf, cur_pos, byte_range.string_length, num_digits);
- cur_pos += num_digits;
- cur_pos += 1;
-
- cur_br_start = cert_start + iui.cert_length;
-
- iui.cert_start = cert_start;
- }
-
- // write the /Timestamp byte range
- if (iui.timeStamper != null) {
- StringInfo byte_range = new StringInfo();
- byte_range.string_start = cur_br_start;
- byte_range.string_length = timestamp_start - cur_br_start;
- iui.byte_ranges.add(byte_range);
-
- replaceNumber(signed_pdf, cur_pos, byte_range.string_start, num_digits);
- cur_pos += num_digits;
- cur_pos += 1;
- replaceNumber(signed_pdf, cur_pos, byte_range.string_length, num_digits);
- cur_pos += num_digits;
- cur_pos += 1;
-
- cur_br_start = timestamp_start + iui.timestamp_length;
-
- iui.timestamp_start = timestamp_start;
- }
-
- // determine the /Data byte ranges if any
- List ifd = iui.invisible_field_definitions;
- if (!ifd.isEmpty() || iui.invisibleKZString != null)
- {
- String data_str = "/Data[(";
- byte[] data_bytes = data_str.getBytes("US-ASCII");
- int data_index = ByteArrayUtils.indexOf(signed_pdf, obj_start, data_bytes);
- int data_start = data_index + data_bytes.length;
-
- int hole_start = data_start;
-
- if (iui.invisibleKZString != null)
- {
- StringInfo si = (StringInfo) iui.kz_list.get(0);
- si.string_start = hole_start;
-
- hole_start += si.string_length + 2;
- }
-
- for (int i = 0; i < ifd.size(); i++)
- {
- ReplaceInfo ri = (ReplaceInfo) iui.replaces.get(i);
- StringInfo si = (StringInfo) ri.replaces.get(0);
- si.string_start = hole_start;
-
- hole_start += si.string_length + 2;
- }
-
- }
-
- Iterator rit = iui.replaces.iterator();
- while (rit.hasNext())
- {
- ReplaceInfo ri = (ReplaceInfo) rit.next();
-
- // byte [] value_bytes = ri.value.getBytes("ISO-8859-1");
- // int write_pos = 0;
-
- Iterator sit = ri.replaces.iterator();
- while (sit.hasNext())
- {
- StringInfo si = (StringInfo) sit.next();
-
- StringInfo byte_range = new StringInfo();
- byte_range.string_start = cur_br_start;
- byte_range.string_length = si.string_start - cur_br_start;
- iui.byte_ranges.add(byte_range);
-
- replaceNumber(signed_pdf, cur_pos, byte_range.string_start, num_digits);
- cur_pos += num_digits;
- cur_pos += 1;
- replaceNumber(signed_pdf, cur_pos, byte_range.string_length, num_digits);
- cur_pos += num_digits;
- cur_pos += 1;
-
- cur_br_start = si.string_start + si.string_length;
- }
-
- }
-
- StringInfo byte_range = new StringInfo();
- byte_range.string_start = cur_br_start;
- byte_range.string_length = signed_pdf.length - cur_br_start;
- iui.byte_ranges.add(byte_range);
-
- replaceNumber(signed_pdf, cur_pos, byte_range.string_start, num_digits);
- cur_pos += num_digits;
- cur_pos += 1;
- replaceNumber(signed_pdf, cur_pos, byte_range.string_length, num_digits);
- cur_pos += num_digits;
- cur_pos += 1;
-
-
- // update the Kennzeichnung byte ranges
- cur_pos = kz_start;
- for (int i = 0; i < iui.kz_list.size(); i++)
- {
- StringInfo si = (StringInfo) iui.kz_list.get(i);
-
- replaceNumber(signed_pdf, cur_pos, si.string_start, num_digits);
- cur_pos += num_digits;
- cur_pos += 1;
- replaceNumber(signed_pdf, cur_pos, si.string_length, num_digits);
- cur_pos += num_digits;
- cur_pos += 1;
- }
-
- }
- catch (IOException e)
- {
- throw new PDFDocumentException(201, e);
- }
-
- }
-
- /**
- * Replaces the certificate placeholder with the certificate from the signed
- * Signature Object.
- *
- * @param iui
- * The IncrementalUpdateInformation.
- * @throws PDFDocumentException
- */
- public static void replaceCertificate(IncrementalUpdateInformation iui) throws PDFDocumentException
- {
- X509Certificate certificate = iui.signed_signature_object.getX509Certificate();
- try
- {
- byte[] der = certificate.getEncoded();
- byte[] encoded = CodingHelper.encodeBase64(der).getBytes("US-ASCII");
- byte[] escaped = Placeholder.escapePDFString(encoded);
- if (escaped.length > iui.cert_length)
- {
- throw new PlaceholderException("certificate", escaped.length - iui.cert_length);
- }
- System.arraycopy(escaped, 0, iui.signed_pdf, iui.cert_start, escaped.length);
- }
- catch (CertificateEncodingException e)
- {
- throw new PDFDocumentException(300, e);
- }
- catch (UnsupportedEncodingException e)
- {
- throw new PDFDocumentException(300, e);
- }
-
- // X509Cert cert = iui.signed_signature_object.getX509Cert();
- // // X509Certificate certificate = cert.getX509Certificate();
- // try
- // {
- // byte[] encoded = cert.getCertString().getBytes("US-ASCII"); //
- // certificate.getEncoded();
- // byte[] escaped = Placeholder.escapePDFString(encoded);
- // if (escaped.length > iui.cert_length)
- // {
- // throw new PlaceholderException("certificate", escaped.length -
- // iui.cert_length);
- // }
- // System.arraycopy(escaped, 0, iui.signed_pdf, iui.cert_start,
- // escaped.length);
- // }
- // // catch (CertificateEncodingException e)
- // // {
- // // throw new PDFDocumentException(300, e);
- // // }
- // catch (UnsupportedEncodingException e)
- // {
- // throw new PDFDocumentException(300, e);
- // }
- }
-
- /**
- * Replaces the timestam placeholder with the timestamp from the signed
- * Signature Object.
- *
- * @param iui
- * The IncrementalUpdateInformation.
- * @throws PDFDocumentException
- */
- public static void replaceTimestamp(IncrementalUpdateInformation iui) throws PDFDocumentException
- {
- String timestamp = iui.signed_signature_object.getSigTimeStamp();
- if (timestamp != null) {
- byte[] escaped = Placeholder.escapePDFString(timestamp.getBytes());
- if (escaped.length > iui.timestamp_length)
- {
- throw new PlaceholderException("timestamp", escaped.length - iui.timestamp_length);
- }
- System.arraycopy(escaped, 0, iui.signed_pdf, iui.timestamp_start, escaped.length);
- }
- }
-
- /**
- * Replaces the placeholders with values from the signed SignatureObject.
- *
- * @param iui
- * The IncrementalUpdateInformation.
- * @throws PDFDocumentException
- */
- public static void replacePlaceholders(IncrementalUpdateInformation iui) throws PDFDocumentException
- {
- final int lineBreakTolerance = getLineBreakTolerance(iui);
-
- final byte[] signed_pdf = iui.signed_pdf;
-
- // int num_replaces = calcNumReps(iui.replaces);
- // int num_holes = num_replaces + 1 + 1; // +1 = the /encodings hole; +1 =
- // the
- // /Cert
-
- int encoding_entry_index = 0;
- {// /encodings itself
- int enc_offset = iui.enc_start + encoding_entry_index * 4;
- signed_pdf[enc_offset] = '/';
- System.arraycopy(ENCODING_NIL, 0, signed_pdf, enc_offset + 1, ENCODING_NIL.length);
- encoding_entry_index++;
- }
- {// /Cert itself
- int enc_offset = iui.enc_start + encoding_entry_index * 4;
- signed_pdf[enc_offset] = '/';
- System.arraycopy(ENCODING_NIL, 0, signed_pdf, enc_offset + 1, ENCODING_NIL.length);
- encoding_entry_index++;
- }
- if (iui.signed_signature_object.getSigTimeStamp() != null)
- {// /Timestamp itself
- int enc_offset = iui.enc_start + encoding_entry_index * 4;
- signed_pdf[enc_offset] = '/';
- System.arraycopy(ENCODING_NIL, 0, signed_pdf, enc_offset + 1, ENCODING_NIL.length);
- encoding_entry_index++;
- }
-
- for (int i = 0; i < iui.replaces.size(); i++)
- {
- ReplaceInfo ri = (ReplaceInfo) iui.replaces.get(i);
-
- try
- {
- String value = ri.value;
-
- if (value == null)
- {
- value = "";
- }
-
- byte[] encoding = ENCODING_WIN;
- byte[] replace_bytes = Placeholder.applyWinAnsiEncoding(value);
-
- String restored_value = Placeholder.unapplyWinAnsiEncoding(replace_bytes);
- if (!value.equals(restored_value))
- {
- // debug:
- logger.warn("WinAnsiEncoding doesn't fit - using URL instead!");
- // /debug!
-
- replace_bytes = Placeholder.applyURLEncoding(value);
-
- encoding = ENCODING_URL;
- }
-
- for (int string_index = 0; string_index < ri.replaces.size(); string_index++)
- {
- int enc_offset = iui.enc_start + encoding_entry_index * 4;
- signed_pdf[enc_offset] = '/';
- System.arraycopy(encoding, 0, signed_pdf, enc_offset + 1, encoding.length);
- encoding_entry_index++;
- }
-
- Placeholder.replacePlaceholderWithTolerance(signed_pdf, ri.replaces, replace_bytes, lineBreakTolerance);
- }
- catch (PlaceholderException e)
- {
- throw new PlaceholderException(ri.sfd.field_name, e.getMissing());
- }
-
- }
- }
-
- /**
- * Calculates the number of actual String replaces from a given ReplaceInfo
- * list.
- * <p>
- * This is used to determine the number of actual replaces that has to be
- * carried out. Accordingly to this number, entries in the dictionary are
- * created.
- * </p>
- *
- * @param replaces
- * The ReplaceInfo list.
- * @return Returns the number of string replaces.
- */
- protected static int calcNumReps(List replaces)
- {
- int number = 0;
- Iterator it = replaces.iterator();
- while (it.hasNext())
- {
- ReplaceInfo ri = (ReplaceInfo) it.next();
- number += ri.replaces.size();
- }
- return number;
- }
-
- /**
- * Determines the List of ReplaceInfo objects of replaces in the content
- * stream regarding the given field definitions.
- *
- * <p>
- * This method collects all variable String fields in a content stream and
- * orders them according to their start offset.
- * </p>
- *
- * @param pdf
- * The PDF.
- * @param begin
- * The start of the content stream.
- * @param end
- * The end of the content stream.
- * @param field_definitions
- * The field definitions that are counceled to find out which and
- * where varaible strings are.
- * @return Returns the list of ReplaceInfo objects specifying the variable
- * areas.
- * @throws CaptionNotFoundException
- */
- protected static List determineReplacesInContentStream(final byte[] pdf, int begin, int end, List field_definitions) throws CaptionNotFoundException
- {
- List replaces = new ArrayList();
- try
- {
-
- List strings = Placeholder.parseStrings(pdf, begin, end);
-
- for (int index = 0; index < field_definitions.size(); index++)
- {
- SignatureFieldDefinition sfd = (SignatureFieldDefinition) field_definitions.get(index);
-
- if (sfd.placeholder_length > 0)
- {
- ReplaceInfo ri = new ReplaceInfo();
- ri.sfd = sfd;
- ri.replaces = new ArrayList();
-
- byte[] caption = sfd.caption.getBytes("ISO-8859-1");
-
- int caption_index = findIndex(strings, caption);
- if (caption_index < 0)
- {
- throw new CaptionNotFoundException(sfd.caption);
- }
- int start_index = skipStrings(strings, caption_index, caption);
- int next_index = findFirstNotPlaceholder(strings, start_index);
-
- for (int i = start_index; i < next_index; i++)
- {
- StringInfo si = (StringInfo) strings.get(i);
- ri.replaces.add(si);
- }
-
- replaces.add(ri);
- }
- }
- }
- catch (UnsupportedEncodingException e)
- {
- logger.error(e.getMessage(), e);
- }
-
- // sort replaces
- Collections.sort(replaces, new Comparator() {
- public int compare(Object arg0, Object arg1)
- {
- ReplaceInfo ri0 = (ReplaceInfo) arg0;
- ReplaceInfo ri1 = (ReplaceInfo) arg1;
- int start0 = ((StringInfo) ri0.replaces.get(0)).string_start;
- int start1 = ((StringInfo) ri1.replaces.get(0)).string_start;
- return start0 - start1;
- }
- });
-
- return replaces;
- }
-
- /**
- * Determines the Kennzeichnug in the content stream.
- *
- * @param pdf
- * The PDF.
- * @param begin
- * The start of the content stream.
- * @param end
- * The end of the content stream.
- * @param field_definitions
- * The field definitions.
- * @return Returns the List of StringInfo objects representing the KZ field.
- * @throws SettingNotFoundException
- * F.e.
- */
- protected static List determineKZ(final byte[] pdf, int begin, int end, List field_definitions) throws SettingNotFoundException
- {
- try
- {
- List strings = Placeholder.parseStrings(pdf, begin, end);
-
- for (int index = 0; index < field_definitions.size(); index++)
- {
- SignatureFieldDefinition sfd = (SignatureFieldDefinition) field_definitions.get(index);
-
- if (sfd.field_name.equals(SignatureTypes.SIG_KZ))
- {
- List kz_list = new ArrayList();
-
- byte[] caption = sfd.caption.getBytes("ISO-8859-1");
-
- int caption_index = findIndex(strings, caption);
- int start_index = skipStrings(strings, caption_index, caption);
-
- int end_index = -1;
- for (end_index = start_index; end_index < strings.size(); end_index++)
- {
- StringInfo si = (StringInfo) strings.get(end_index);
-
- if (startsWithCaption(si, field_definitions))
- {
- break;
- }
-
- kz_list.add(si);
- }
-
- return kz_list;
- }
- }
- }
- catch (UnsupportedEncodingException e)
- {
- logger.error(e.getMessage(), e);
- }
- throw new KZSettingNotFoundException("Field " + SignatureTypes.SIG_KZ + " not found.");
- }
-
- /**
- * Finds the index of the StringInfo within the StringInfo list that has the
- * given content (caption).
- *
- * @param strings
- * The list of StringInfos.
- * @param caption
- * The text to be matched to the strings.
- * @return Returns the index of the found string, or -1 if no string matched.
- */
- protected static int findIndex(List strings, byte[] caption)
- {
- for (int i = 0; i < strings.size(); i++)
- {
- if (isCaption(strings, i, caption))
- {
- return i;
- }
- }
- return -1;
- }
-
- protected static boolean isCaption(List strings, int index, byte[] caption)
- {
- try
- {
-
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- for (int i = index; i < strings.size(); i++)
- {
- StringInfo si = (StringInfo) strings.get(i);
- baos.write(si.copyStringBytes());
- }
- byte[] str_data = baos.toByteArray();
- byte[] unescaped = Placeholder.unescapePDFString(str_data);
- if (ByteArrayUtils.compareByteArrays(unescaped, 0, caption))
- {
- return true;
- }
- else
- {
- return false;
- }
- }
- catch (IOException e)
- {
- logger.error(e.getMessage(), e);
- return false;
- }
-
- }
-
- protected static int skipStrings(List strings, int index, byte[] caption)
- {
- int length = 0;
- for (int i = index; i < strings.size(); i++)
- {
- StringInfo si = (StringInfo) strings.get(i);
- length += si.string_length;
-
- if (length >= caption.length)
- {
- return i + 1;
- }
- }
- return -1;
- }
-
- /**
- * Tells, if the given StringInfo contains only placeholder characters.
- *
- * @param si
- * The StringInfo.
- * @param placeholder
- * The placeholder character.
- * @return Returns true, if the string contains only the given placeholder
- * characters, false otherwise.
- */
- protected static boolean isPlaceholder(StringInfo si, byte placeholder)
- {
- byte[] string_bytes = si.copyStringBytes();
- for (int i = 0; i < string_bytes.length; i++)
- {
- if (string_bytes[i] != placeholder)
- {
- return false;
- }
- }
- return true;
- }
-
- protected static boolean startsWithCaption(StringInfo si, List field_definitions)
- {
- try
- {
- for (int i = 0; i < field_definitions.size(); i++)
- {
- SignatureFieldDefinition sfd = (SignatureFieldDefinition) field_definitions.get(i);
-
- String caption = sfd.caption;
- String str = si.getString("ISO-8859-1");
-
- if (caption.startsWith(str))
- {
- return true;
- }
- }
- return false;
- }
- catch (UnsupportedEncodingException e)
- {
- logger.error(e.getMessage(), e);
- return false;
- }
- }
-
- /**
- * Finds the first string after and at the given index not being a placeholder
- * string.
- *
- * @param strings
- * The list of StringInfos.
- * @param start
- * The index where to start the search.
- * @return Returns the index of the first not placeholder string, or
- * strings.size() if no more non placeholder strings could be found.
- */
- protected static int findFirstNotPlaceholder(List strings, int start)
- {
- for (int i = start; i < strings.size(); i++)
- {
- StringInfo si = (StringInfo) strings.get(i);
- if (!isPlaceholder(si, LAYOUT_PLACEHOLDER))
- {
- return i;
- }
- }
- return strings.size();
- }
-
- /**
- * Restores the given String to its placeholder.
- *
- * @param pdf
- * The PDF.
- * @param si
- * The string.
- * @param placeholder
- * The placeholder the string should be filled with.
- */
- public static void restorePlaceholder(final byte[] pdf, StringInfo si, final byte placeholder)
- {
- byte[] ph = new byte[si.string_length];
- for (int i = 0; i < ph.length; i++)
- {
- ph[i] = placeholder;
- }
- System.arraycopy(ph, 0, pdf, si.string_start, ph.length);
- }
-
- /**
- * Reconstructs the replaces from the PDF and forms suitable value strings.
- *
- * @param pdf
- * The PDF.
- * @param brevs
- * The brevs.
- * @param sis
- * The StringInfo objects of the strings.
- * @return Returns the List of ReplaceInfo objects containing the restored
- * values.
- * @throws PDFDocumentException
- */
- public static List reconstructReplaces(final byte[] pdf, byte[][] brevs, StringInfo[] sis, byte[][] encodings) throws PDFDocumentException
- {
- try
- {
- List replaces = new ArrayList();
-
- ReplaceInfo cur_ri = null;
-
- for (int cur = 0; cur < brevs.length; cur++)
- {
- if (ByteArrayUtils.compareByteArrays(brevs[cur], 0, BREV_NIL))
- {
- continue;
- }
-
- if (cur_ri == null || !ByteArrayUtils.compareByteArrays(cur_ri.brev, 0, brevs[cur]))
- {
- if (cur >= encodings.length) {
- throw new PDFDocumentException(ErrorCode.INVALID_SIGNATURE_DICTIONARY, "Invalid EGIZ signature dictionary.");
- }
- cur_ri = new ReplaceInfo();
-
- cur_ri.replaces = new ArrayList();
-
- cur_ri.brev = brevs[cur];
- cur_ri.enc = encodings[cur];
-
- replaces.add(cur_ri);
- }
-
- cur_ri.replaces.add(sis[cur]);
- }
-
- // restore value Strings
- Iterator rit = replaces.iterator();
- while (rit.hasNext())
- {
- ReplaceInfo ri = (ReplaceInfo) rit.next();
- ri.value = Placeholder.reconstructStringFromPartition(pdf, ri.replaces, ri.enc);
-
- // System.out.println(new String(ri.brev, "US-ASCII") + ": " +
- // ri.value);
- }
-
- return replaces;
- }
- catch (IOException e)
- {
- throw new PDFDocumentException(310, e);
- }
-
- }
-
- /**
- * Reads an unsigned integer number.
- *
- * @param pdf
- * The PDF.
- * @param start_index
- * The start index of the number.
- * @param num_digits
- * The number of digits.
- * @return Returns the read number.
- */
- public static int readNumber(final byte[] pdf, final int start_index, final int num_digits)
- {
- try
- {
- byte[] n_bytes = new byte[num_digits];
- System.arraycopy(pdf, start_index, n_bytes, 0, num_digits);
- String n_string = new String(n_bytes, "US-ASCII");
-
- int n = Integer.parseInt(n_string);
- return n;
- }
- catch (UnsupportedEncodingException e)
- {
- logger.error(e.getMessage(), e);
- return -1;
- }
- }
-
- /**
- * Replaces a number by the new value.
- *
- * @param pdf
- * The PDF.
- * @param start_index
- * The start index of the number.
- * @param number
- * The new number.
- * @param num_digits
- * The number of digits.
- */
- public static void replaceNumber(final byte[] pdf, final int start_index, final int number, final int num_digits)
- {
- try
- {
- if (number < 0)
- {
- throw new IllegalArgumentException("The given number " + number + " must not be negative.");
- }
- String number_string = Integer.toString(number);
- if (number_string.length() > num_digits)
- {
- throw new IllegalArgumentException("The given number " + number + " has more than " + num_digits + " digits.");
- }
-
- int leading_zeros = num_digits - number_string.length();
- String zeros_string = "";
- for (int i = 0; i < leading_zeros; i++)
- {
- zeros_string += "0";
- }
-
- String total_string = zeros_string + number_string;
- byte[] total_bytes = total_string.getBytes("US-ASCII");
- System.arraycopy(total_bytes, 0, pdf, start_index, num_digits);
- }
- catch (UnsupportedEncodingException e)
- {
- logger.error(e.getMessage(), e);
- }
- }
-
-
- // TODO old code - remove
- // /**
- // * For debugging purposes.
- // *
- // * @param args
- // * @throws IOException
- // */
- // public static void main(String[] args) throws IOException
- // {
- // File signed_doc = new File("C:/wprinz/temp.pdf");
- //
- // PdfReader reader = new PdfReader(new FileInputStream(signed_doc));
- // PdfDictionary egiz_dict = getEgizDictFromReader(reader);
- // if (egiz_dict == null)
- // {
- // System.out.println("NO Egiz Dict");
- // return;
- // }
- //
- // String sig_text = extractSignatureTextOnly(egiz_dict);
- // System.out.println("Sig Text:");
- // System.out.println(sig_text);
- //
- // int ods = getOriginalDocumentSizeFromEgizDict(egiz_dict);
- // System.out.println("Original Document Size = " + ods);
- // }
-
-}