You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by le...@apache.org on 2011/06/25 18:51:58 UTC
svn commit: r1139570 - in
/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox: cos/COSName.java
pdmodel/PDDocument.java
pdmodel/interactive/digitalsignature/SignatureOptions.java
Author: lehmi
Date: Sat Jun 25 16:51:57 2011
New Revision: 1139570
URL: http://svn.apache.org/viewvc?rev=1139570&view=rev
Log:
PDFBOX-1031: added a preferred signature size to the SignatureOptions as proposed by Thomas Chojecki
Modified:
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/PDDocument.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/digitalsignature/SignatureOptions.java
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java?rev=1139570&r1=1139569&r2=1139570&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java Sat Jun 25 16:51:57 2011
@@ -391,12 +391,16 @@ public final class COSName extends COSBa
public static final COSName DP = new COSName( "DP" );
/**
- * A common COSName value.
- */
+ * A common COSName value.
+ */
+ public static final COSName DR = new COSName( "DR" );
+ /**
+ * A common COSName value.
+ */
public static final COSName DV = new COSName( "DV" );
/**
- * A common COSName value.
- */
+ * A common COSName value.
+ */
public static final COSName DW = new COSName( "DW" );
/**
@@ -537,6 +541,10 @@ public final class COSName extends COSBa
/**
* A common COSName value.
*/
+ public static final COSName FORM = new COSName( "Form" );
+ /**
+ * A common COSName value.
+ */
public static final COSName FORMTYPE = new COSName( "FormType" );
/**
* A common COSName value.
@@ -1193,6 +1201,10 @@ public final class COSName extends COSBa
* A common COSName value.
*/
public static final COSName SIG = new COSName("Sig");
+ /**
+ * A common COSName value.
+ */
+ public static final COSName SIG_FLAGS = new COSName("SigFlags");
private String name;
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/PDDocument.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/PDDocument.java?rev=1139570&r1=1139569&r2=1139570&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/PDDocument.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/PDDocument.java Sat Jun 25 16:51:57 2011
@@ -82,19 +82,9 @@ import org.apache.pdfbox.pdmodel.interac
*/
public class PDDocument implements Pageable
{
- private static final String COSDictionary = null;
private COSDocument document;
- // NOTE BGUILLON: this property must be removed because it is
- // not the responsability of this class to know
- //private boolean encryptOnSave = false;
-
-
- // NOTE BGUILLON: these properties are not used anymore. See getCurrentAccessPermission() instead
- //private String encryptUserPassword = null;
- //private String encryptOwnerPassword = null;
-
//cached values
private PDDocumentInformation documentInformation;
private PDDocumentCatalog documentCatalog;
@@ -105,13 +95,6 @@ public class PDDocument implements Pagea
private PDEncryptionDictionary encParameters = null;
/**
- * This will tell if the document was decrypted with the master password.
- * NOTE BGUILLON: this property is not used anymore. See getCurrentAccessPermission() instead
- */
- //private boolean decryptedWithOwnerPassword = false;
-
-
- /**
* The security handler used to decrypt / encrypt the document.
*/
private SecurityHandler securityHandler = null;
@@ -166,8 +149,7 @@ public class PDDocument implements Pagea
// or references to arrays which have references to pages
// or references to arrays which have references to arrays which have references to pages
// or ... (I think you get the idea...)
- processListOfPageReferences(getDocumentCatalog().getPages().getKids());
-
+ processListOfPageReferences(getDocumentCatalog().getPages().getKids());
}
private void processListOfPageReferences(List<Object> pageNodes)
@@ -279,10 +261,9 @@ public class PDDocument implements Pagea
public void addSignature(PDSignature sigObject, SignatureInterface signatureInterface) throws IOException, SignatureException
{
- SignatureOptions defaultOptions = new SignatureOptions();
- defaultOptions.setPage(1);
-
- addSignature(sigObject, signatureInterface,defaultOptions);
+ SignatureOptions defaultOptions = new SignatureOptions();
+ defaultOptions.setPage(1);
+ addSignature(sigObject, signatureInterface,defaultOptions);
}
/**
@@ -295,155 +276,175 @@ public class PDDocument implements Pagea
*/
public void addSignature(PDSignature sigObject, SignatureInterface signatureInterface, SignatureOptions options) throws IOException, SignatureException
{
- // Content reservieren
- // Um auch grosse Zertifikatsketten unterbringen zu koennen,
- // wird ein sehr grosser Bereich reserviert
- sigObject.setContents(new byte[0x2500 * 2 + 2]);
-
- // ByteRange reservieren
- sigObject.setByteRange(new int[] {0,1000000000,1000000000,1000000000});
-
- getDocument().setSignatureInterface(signatureInterface);
-
- // #########################################
- // # SignatureForm fuer Signatur erstellen #
- // # und mit an das Dokument haengen. #
- // #########################################
-
- // Erste Seite besorgen
- PDDocumentCatalog root = getDocumentCatalog();
- PDPageNode rootPages = root.getPages();
- List<PDPage> kids = new ArrayList<PDPage>();
- rootPages.getAllKids(kids);
-
- int size = (int)rootPages.getCount();
- PDPage page = null;
- if (size == 0)
- throw new SignatureException(SignatureException.INVALID_PAGE_FOR_SIGNATURE, "The PDF file has no pages");
- if (options.getPage()>size)
- page = kids.get(size-1);
- else if(options.getPage()<=0)
- page = kids.get(0);
- else
- page = kids.get(options.getPage()-1);
+ // Reserve content
+ // We need to reserve some space for the signature. Some signatures including
+ // big certificate chain and we need enough space to store it.
+ int preferedSignatureSize = options.getPreferedSignatureSize();
+ if (preferedSignatureSize > 0)
+ {
+ sigObject.setContents(new byte[preferedSignatureSize * 2 + 2]);
+ }
+ else
+ {
+ sigObject.setContents(new byte[0x2500 * 2 + 2]);
+ }
+
+ // Reserve ByteRange
+ sigObject.setByteRange(new int[] {0,1000000000,1000000000,1000000000});
-
- // AcroForm aus dem Root dict besorgen und Annotation einfügen
- PDAcroForm acroForm = root.getAcroForm();
- root.getCOSObject().setNeedToBeUpdate(true);
-
- if (acroForm==null)
- {
- acroForm = new PDAcroForm(this);
- root.setAcroForm(acroForm);
- } else
- acroForm.getCOSObject().setNeedToBeUpdate(true);
+ getDocument().setSignatureInterface(signatureInterface);
- /*
- * For invisible signatures, the annotation has a rectangle array with values [ 0 0 0 0 ].
- * This annotation is usually attached to the viewed page when the signature is created.
- * Despite not having an appearance, the annotation AP and N dictionaries may be present
- * in some versions of Acrobat. If present, N references the DSBlankXObj (blank) XObject.
- */
-
- // Annotation / Field für die Signatur erzeugen
- PDSignatureField signatureField = new PDSignatureField(acroForm);
- signatureField.setSignature(sigObject); // Signaturobjekt vermerken
- signatureField.getWidget().setPage(page); // Rückverkettung
+ // #########################################
+ // # Create SignatureForm for signature #
+ // # and appending it to the document #
+ // #########################################
+
+ // Get the first page
+ PDDocumentCatalog root = getDocumentCatalog();
+ PDPageNode rootPages = root.getPages();
+ List<PDPage> kids = new ArrayList<PDPage>();
+ rootPages.getAllKids(kids);
+
+ int size = (int)rootPages.getCount();
+ PDPage page = null;
+ if (size == 0)
+ {
+ throw new SignatureException(SignatureException.INVALID_PAGE_FOR_SIGNATURE, "The PDF file has no pages");
+ }
+ if (options.getPage()>size)
+ {
+ page = kids.get(size-1);
+ }
+ else if(options.getPage()<=0)
+ {
+ page = kids.get(0);
+ }
+ else
+ {
+ page = kids.get(options.getPage()-1);
+ }
- // AcroForm Fields setzen
- List acroFormFields = acroForm.getFields();
- COSDictionary acroFormDict = acroForm.getDictionary();
- acroFormDict.setDirect(true);
- acroFormDict.setInt("SigFlags", 3);
- acroFormFields.add(signatureField);
-
- // Objekte aus der visuellen Signatur besorgen
- COSDocument visualSignature = options.getVisualSignature();
- // Fallunterscheidung zwischen sichtbarer und unsichtbarer Signatur vorbereiten
- if (visualSignature == null) // unsichtbare Signatur
- {
- // Rectangle fuer unsichtbare Signatur auf 0 0 0 0 setzen
- signatureField.getWidget().setRectangle(new PDRectangle()); // rectangle array [ 0 0 0 0 ]
- // AcroForm leere DefaultRessource setzen
- acroFormDict.setItem("DR", null);
- // Leeres Appearance-Dictionary setzten
- PDAppearanceDictionary ap = new PDAppearanceDictionary();
- COSStream apsStream = new COSStream(getDocument().getScratchFile());
- apsStream.createUnfilteredStream();
- PDAppearanceStream aps = new PDAppearanceStream(apsStream);
- COSDictionary cosObject = (COSDictionary)aps.getCOSObject();
- cosObject.setItem(COSName.SUBTYPE, COSName.getPDFName("Form"));
- cosObject.setItem(COSName.BBOX, new PDRectangle());
+ // Get the AcroForm from the Root-Dictionary and append the annotation
+ PDAcroForm acroForm = root.getAcroForm();
+ root.getCOSObject().setNeedToBeUpdate(true);
- ap.setNormalAppearance(aps);
- ap.getDictionary().setDirect(true);
- signatureField.getWidget().setAppearance(ap);
- }
- else // sichtbare Signatur
- {
- // Visuelle Objekte besorgen
- List<COSObject> cosObjects = visualSignature.getObjects();
-
- boolean annotNotFound = true;
- boolean sigFieldNotFound = true;
-
- for ( COSObject cosObject : cosObjects )
+ if (acroForm==null)
+ {
+ acroForm = new PDAcroForm(this);
+ root.setAcroForm(acroForm);
+ }
+ else
{
- COSBase base = cosObject.getObject();
- if (base != null && base instanceof COSDictionary)
- {
- COSBase ft = ((COSDictionary)base).getItem(COSName.getPDFName("FT"));
- COSBase type = ((COSDictionary)base).getItem(COSName.TYPE);
- COSBase apDict = ((COSDictionary)base).getItem(COSName.AP);
+ acroForm.getCOSObject().setNeedToBeUpdate(true);
+ }
+
+ /*
+ * For invisible signatures, the annotation has a rectangle array with values [ 0 0 0 0 ].
+ * This annotation is usually attached to the viewed page when the signature is created.
+ * Despite not having an appearance, the annotation AP and N dictionaries may be present
+ * in some versions of Acrobat. If present, N references the DSBlankXObj (blank) XObject.
+ */
+
+ // Create Annotation / Field for signature
+ PDSignatureField signatureField = new PDSignatureField(acroForm);
+ signatureField.setSignature(sigObject); // append the signature object
+ signatureField.getWidget().setPage(page); // backward linking
+
+ // Set the AcroForm Fields
+ List acroFormFields = acroForm.getFields();
+ COSDictionary acroFormDict = acroForm.getDictionary();
+ acroFormDict.setDirect(true);
+ acroFormDict.setInt(COSName.SIG_FLAGS, 3);
+ acroFormFields.add(signatureField);
+
+ // Get the object from the visual signature
+ COSDocument visualSignature = options.getVisualSignature();
+
+ // Distinction of case for visual and non-visual signature
+ if (visualSignature == null) // non-visual signature
+ {
+ // Set rectangle for non-visual signature to 0 0 0 0
+ signatureField.getWidget().setRectangle(new PDRectangle()); // rectangle array [ 0 0 0 0 ]
+ // Clear AcroForm / Set DefaultRessource
+ acroFormDict.setItem(COSName.DR, null);
+ // Set empty Appearance-Dictionary
+ PDAppearanceDictionary ap = new PDAppearanceDictionary();
+ COSStream apsStream = new COSStream(getDocument().getScratchFile());
+ apsStream.createUnfilteredStream();
+ PDAppearanceStream aps = new PDAppearanceStream(apsStream);
+ COSDictionary cosObject = (COSDictionary)aps.getCOSObject();
+ cosObject.setItem(COSName.SUBTYPE, COSName.FORM);
+ cosObject.setItem(COSName.BBOX, new PDRectangle());
- // Nach Signatur-Annotation suchen
- if (annotNotFound && COSName.getPDFName("Annot").equals(type))
+ ap.setNormalAppearance(aps);
+ ap.getDictionary().setDirect(true);
+ signatureField.getWidget().setAppearance(ap);
+ }
+ else // visual signature
+ {
+ // Obtain visual signature object
+ List<COSObject> cosObjects = visualSignature.getObjects();
+
+ boolean annotNotFound = true;
+ boolean sigFieldNotFound = true;
+
+ for ( COSObject cosObject : cosObjects )
{
- COSDictionary cosBaseDict = (COSDictionary)base;
+ COSBase base = cosObject.getObject();
+ if (base != null && base instanceof COSDictionary)
+ {
+ COSBase ft = ((COSDictionary)base).getItem(COSName.FT);
+ COSBase type = ((COSDictionary)base).getItem(COSName.TYPE);
+ COSBase apDict = ((COSDictionary)base).getItem(COSName.AP);
+
+ // Search for signature annotation
+ if (annotNotFound && COSName.ANNOT.equals(type))
+ {
+ COSDictionary cosBaseDict = (COSDictionary)base;
- // Rectangle fuer visuelle Signatur auslesen und setzen
- COSArray rectAry = (COSArray)cosBaseDict.getItem(COSName.getPDFName("Rect"));
- PDRectangle rect = new PDRectangle(rectAry);
- signatureField.getWidget().setRectangle(rect);
- annotNotFound = false;
- }
+ // Read and set the Rectangle for visual signature
+ COSArray rectAry = (COSArray)cosBaseDict.getItem(COSName.RECT);
+ PDRectangle rect = new PDRectangle(rectAry);
+ signatureField.getWidget().setRectangle(rect);
+ annotNotFound = false;
+ }
- // Nach Signatur-Field suchen
- if (sigFieldNotFound && COSName.getPDFName("Sig").equals(ft) && apDict != null)
- {
- COSDictionary cosBaseDict = (COSDictionary)base;
+ // Search for Signature-Field
+ if (sigFieldNotFound && COSName.SIG.equals(ft) && apDict != null)
+ {
+ COSDictionary cosBaseDict = (COSDictionary)base;
- // Appearance Dictionary auslesen und setzen
- PDAppearanceDictionary ap = new PDAppearanceDictionary((COSDictionary)cosBaseDict.getItem(COSName.AP));
- ap.getDictionary().setDirect(true);
- signatureField.getWidget().setAppearance(ap);
+ // Appearance Dictionary auslesen und setzen
+ PDAppearanceDictionary ap = new PDAppearanceDictionary((COSDictionary)cosBaseDict.getItem(COSName.AP));
+ ap.getDictionary().setDirect(true);
+ signatureField.getWidget().setAppearance(ap);
- // AcroForm DefaultRessource auslesen und setzen
- COSBase dr = cosBaseDict.getItem(COSName.getPDFName("DR"));
- dr.setDirect(true);
- dr.setNeedToBeUpdate(true);
- acroFormDict.setItem("DR", dr);
- sigFieldNotFound=false;
+ // AcroForm DefaultRessource auslesen und setzen
+ COSBase dr = cosBaseDict.getItem(COSName.DR);
+ dr.setDirect(true);
+ dr.setNeedToBeUpdate(true);
+ acroFormDict.setItem(COSName.DR, dr);
+ sigFieldNotFound=false;
+ }
+ }
}
- }
- }
- if (annotNotFound || sigFieldNotFound )
- throw new SignatureException(SignatureException.VISUAL_SIGNATURE_INVALID, "Could not read all needed objects from template");
- }
-
- // Seite besorgen und Signatur-Annotation anbringen
- List annotations = page.getAnnotations();
- if (annotations== null)
- {
- annotations = new COSArrayList();
- }
- annotations.add(signatureField.getWidget());
- page.setAnnotations(annotations);
- page.getCOSObject().setNeedToBeUpdate(true);
+ if (annotNotFound || sigFieldNotFound )
+ {
+ throw new SignatureException(SignatureException.VISUAL_SIGNATURE_INVALID, "Could not read all needed objects from template");
+ }
+ }
+ // Get the annotations of the page and append the signature-annotation to it
+ List annotations = page.getAnnotations();
+ if (annotations== null)
+ {
+ annotations = new COSArrayList();
+ }
+ annotations.add(signatureField.getWidget());
+ page.setAnnotations(annotations);
+ page.getCOSObject().setNeedToBeUpdate(true);
}
/**
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/digitalsignature/SignatureOptions.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/digitalsignature/SignatureOptions.java?rev=1139570&r1=1139569&r2=1139570&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/digitalsignature/SignatureOptions.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/digitalsignature/SignatureOptions.java Sat Jun 25 16:51:57 2011
@@ -25,28 +25,77 @@ import org.apache.pdfbox.pdfparser.Visua
public class SignatureOptions
{
- private COSDocument visualSignature;
+ private COSDocument visualSignature;
- private int pageNo;
+ private int preferedSignatureSize;
+
+ private int pageNo;
- public void setPage(int pageNo)
- {
- this.pageNo = pageNo;
- }
+ /**
+ * Set the page number.
+ *
+ * @param pageNo the page number
+ *
+ */
+ public void setPage(int pageNo)
+ {
+ this.pageNo = pageNo;
+ }
- public int getPage() {
- return pageNo;
- }
+ /**
+ * Get the page number.
+ *
+ * @return the page number
+ */
+ public int getPage()
+ {
+ return pageNo;
+ }
- public void setVisualSignature(InputStream is) throws IOException
- {
- VisualSignatureParser visParser = new VisualSignatureParser(is);
- visParser.parse();
- visualSignature = visParser.getDocument();
- }
+ /**
+ * Reads the visual signature from the given input stream.
+ *
+ * @param is the input stream containing the visual signature
+ *
+ * @throws IOException when something went wrong during parsing
+ */
+ public void setVisualSignature(InputStream is) throws IOException
+ {
+ VisualSignatureParser visParser = new VisualSignatureParser(is);
+ visParser.parse();
+ visualSignature = visParser.getDocument();
+ }
- public COSDocument getVisualSignature()
- {
- return visualSignature;
- }
+ /**
+ * Get the visual signature.
+ *
+ * @return the visual signature
+ */
+ public COSDocument getVisualSignature()
+ {
+ return visualSignature;
+ }
+
+ /**
+ * Get the preferred size of the signature.
+ *
+ * @return the preferred size
+ */
+ public int getPreferedSignatureSize()
+ {
+ return preferedSignatureSize;
+ }
+
+ /**
+ * Set the preferred size of the signature.
+ *
+ * @param size the size of the signature
+ */
+ public void setPreferedSignatureSize(int size)
+ {
+ if (size > 0)
+ {
+ preferedSignatureSize = size;
+ }
+ }
}