use of com.tom_roush.pdfbox.pdmodel.interactive.form.PDSignatureField in project PdfBox-Android by TomRoush.
the class PDDocument method getSignatureFields.
/**
* Retrieve all signature fields from the document.
*
* @return a <code>List</code> of <code>PDSignatureField</code>s
* @throws IOException if no document catalog can be found.
*/
public List<PDSignatureField> getSignatureFields() throws IOException {
List<PDSignatureField> fields = new ArrayList<PDSignatureField>();
PDAcroForm acroForm = getDocumentCatalog().getAcroForm();
if (acroForm != null) {
for (PDField field : acroForm.getFieldTree()) {
if (field instanceof PDSignatureField) {
fields.add((PDSignatureField) field);
}
}
}
return fields;
}
use of com.tom_roush.pdfbox.pdmodel.interactive.form.PDSignatureField in project PdfBox-Android by TomRoush.
the class PDDocument method addSignature.
/**
* This will add a signature to the document. If the 0-based page number in the options
* parameter is smaller than 0 or larger than max, the nearest valid page number will be used
* (i.e. 0 or max) and no exception will be thrown.
* <p>
* Only one signature may be added in a document. To sign several times,
* load document, add signature, save incremental and close again.
*
* @param sigObject is the PDSignatureField model
* @param signatureInterface is an interface whose implementation provides
* signing capabilities. Can be null if external signing if used.
* @param options signature options
* @throws IOException if there is an error creating required fields
* @throws IllegalStateException if one attempts to add several signature
* fields.
*/
public void addSignature(PDSignature sigObject, SignatureInterface signatureInterface, SignatureOptions options) throws IOException {
if (signatureAdded) {
throw new IllegalStateException("Only one signature may be added in a document");
}
signatureAdded = true;
// 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 preferredSignatureSize = options.getPreferredSignatureSize();
if (preferredSignatureSize > 0) {
sigObject.setContents(new byte[preferredSignatureSize]);
} else {
sigObject.setContents(new byte[SignatureOptions.DEFAULT_SIGNATURE_SIZE]);
}
// Reserve ByteRange, will be overwritten in COSWriter
sigObject.setByteRange(RESERVE_BYTE_RANGE);
signInterface = signatureInterface;
// Create SignatureForm for signature and append it to the document
// Get the first valid page
int pageCount = getNumberOfPages();
if (pageCount == 0) {
throw new IllegalStateException("Cannot sign an empty document");
}
int startIndex = Math.min(Math.max(options.getPage(), 0), pageCount - 1);
PDPage page = getPage(startIndex);
// Get the AcroForm from the Root-Dictionary and append the annotation
PDDocumentCatalog catalog = getDocumentCatalog();
PDAcroForm acroForm = catalog.getAcroForm();
catalog.getCOSObject().setNeedToBeUpdated(true);
if (acroForm == null) {
acroForm = new PDAcroForm(this);
catalog.setAcroForm(acroForm);
} else {
acroForm.getCOSObject().setNeedToBeUpdated(true);
}
PDSignatureField signatureField = null;
if (!(acroForm.getCOSObject().getDictionaryObject(COSName.FIELDS) instanceof COSArray)) {
acroForm.getCOSObject().setItem(COSName.FIELDS, new COSArray());
} else {
COSArray fieldArray = (COSArray) acroForm.getCOSObject().getDictionaryObject(COSName.FIELDS);
fieldArray.setNeedToBeUpdated(true);
signatureField = findSignatureField(acroForm.getFieldIterator(), sigObject);
}
if (signatureField == null) {
signatureField = new PDSignatureField(acroForm);
// append the signature object
signatureField.setValue(sigObject);
// backward linking
signatureField.getWidgets().get(0).setPage(page);
} else {
sigObject.getCOSObject().setNeedToBeUpdated(true);
}
// TODO This "overwrites" the settings of the original signature field which might not be intended by the user
// better make it configurable (not all users need/want PDF/A but their own setting):
// to conform PDF/A-1 requirement:
// The /F key's Print flag bit shall be set to 1 and
// its Hidden, Invisible and NoView flag bits shall be set to 0
signatureField.getWidgets().get(0).setPrinted(true);
// Set the AcroForm Fields
List<PDField> acroFormFields = acroForm.getFields();
acroForm.getCOSObject().setDirect(true);
acroForm.setSignaturesExist(true);
acroForm.setAppendOnly(true);
boolean checkFields = checkSignatureField(acroForm.getFieldIterator(), signatureField);
if (checkFields) {
signatureField.getCOSObject().setNeedToBeUpdated(true);
} else {
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) {
prepareNonVisibleSignature(signatureField);
return;
}
prepareVisibleSignature(signatureField, acroForm, visualSignature);
// Create Annotation / Field for signature
List<PDAnnotation> annotations = page.getAnnotations();
// Make /Annots a direct object to avoid problem if it is an existing indirect object:
// it would not be updated in incremental save, and if we'd set the /Annots array "to be updated"
// while keeping it indirect, Adobe Reader would claim that the document had been modified.
page.setAnnotations(annotations);
// take care that page and acroforms do not share the same array (if so, we don't need to add it twice)
if (!(annotations instanceof COSArrayList && acroFormFields instanceof COSArrayList && ((COSArrayList<?>) annotations).toList().equals(((COSArrayList<?>) acroFormFields).toList()) && checkFields)) {
PDAnnotationWidget widget = signatureField.getWidgets().get(0);
// use check to prevent the annotation widget from appearing twice
if (checkSignatureAnnotation(annotations, widget)) {
widget.getCOSObject().setNeedToBeUpdated(true);
} else {
annotations.add(widget);
}
}
page.getCOSObject().setNeedToBeUpdated(true);
}
use of com.tom_roush.pdfbox.pdmodel.interactive.form.PDSignatureField in project PdfBox-Android by TomRoush.
the class PDDocument method addSignatureField.
/**
* This will add a list of signature fields to the document.
*
* @param sigFields are the PDSignatureFields that should be added to the document
* @param signatureInterface is an interface whose implementation provides
* signing capabilities. Can be null if external signing if used.
* @param options signature options
* @throws IOException if there is an error creating required fields
* @deprecated The method is misleading, because only one signature may be
* added in a document. The method will be removed in the future.
*/
@Deprecated
public void addSignatureField(List<PDSignatureField> sigFields, SignatureInterface signatureInterface, SignatureOptions options) throws IOException {
PDDocumentCatalog catalog = getDocumentCatalog();
catalog.getCOSObject().setNeedToBeUpdated(true);
PDAcroForm acroForm = catalog.getAcroForm();
if (acroForm == null) {
acroForm = new PDAcroForm(this);
catalog.setAcroForm(acroForm);
}
COSDictionary acroFormDict = acroForm.getCOSObject();
acroFormDict.setDirect(true);
acroFormDict.setNeedToBeUpdated(true);
if (!acroForm.isSignaturesExist()) {
// 1 if at least one signature field is available
acroForm.setSignaturesExist(true);
}
List<PDField> acroformFields = acroForm.getFields();
for (PDSignatureField sigField : sigFields) {
sigField.getCOSObject().setNeedToBeUpdated(true);
// Check if the field already exists
boolean checkSignatureField = checkSignatureField(acroForm.getFieldIterator(), sigField);
if (checkSignatureField) {
sigField.getCOSObject().setNeedToBeUpdated(true);
} else {
acroformFields.add(sigField);
}
// Check if we need to add a signature
if (sigField.getSignature() != null) {
sigField.getCOSObject().setNeedToBeUpdated(true);
if (options == null) {
// TODO ??
}
addSignature(sigField.getSignature(), signatureInterface, options);
}
}
}
use of com.tom_roush.pdfbox.pdmodel.interactive.form.PDSignatureField in project PdfBox-Android by TomRoush.
the class PDFTemplateCreator method buildPDF.
/**
* Build a PDF with a visible signature step by step, and return it as a stream.
*
* @param properties
* @return InputStream
* @throws IOException
*/
public InputStream buildPDF(PDVisibleSignDesigner properties) throws IOException {
Log.i("PdfBox-Android", "pdf building has been started");
PDFTemplateStructure pdfStructure = pdfBuilder.getStructure();
// we create array of [Text, ImageB, ImageC, ImageI]
pdfBuilder.createProcSetArray();
// create page
pdfBuilder.createPage(properties);
PDPage page = pdfStructure.getPage();
// create template
pdfBuilder.createTemplate(page);
PDDocument template = pdfStructure.getTemplate();
// create /AcroForm
pdfBuilder.createAcroForm(template);
PDAcroForm acroForm = pdfStructure.getAcroForm();
// AcroForm contains signature fields
pdfBuilder.createSignatureField(acroForm);
PDSignatureField pdSignatureField = pdfStructure.getSignatureField();
// create signature
// TODO
// The line below has no effect with the CreateVisibleSignature example.
// The signature field is needed as a "holder" for the /AP tree,
// but the /P and /V PDSignatureField entries are ignored by PDDocument.addSignature
pdfBuilder.createSignature(pdSignatureField, page, "");
// that is /AcroForm/DR entry
pdfBuilder.createAcroFormDictionary(acroForm, pdSignatureField);
// create AffineTransform
pdfBuilder.createAffineTransform(properties.getTransform());
AffineTransform transform = pdfStructure.getAffineTransform();
// rectangle, formatter, image. /AcroForm/DR/XObject contains that form
pdfBuilder.createSignatureRectangle(pdSignatureField, properties);
pdfBuilder.createFormatterRectangle(properties.getFormatterRectangleParameters());
PDRectangle bbox = pdfStructure.getFormatterRectangle();
pdfBuilder.createSignatureImage(template, properties.getImage());
// create form stream, form and resource.
pdfBuilder.createHolderFormStream(template);
PDStream holderFormStream = pdfStructure.getHolderFormStream();
pdfBuilder.createHolderFormResources();
PDResources holderFormResources = pdfStructure.getHolderFormResources();
pdfBuilder.createHolderForm(holderFormResources, holderFormStream, bbox);
// that is /AP entry the appearance dictionary.
pdfBuilder.createAppearanceDictionary(pdfStructure.getHolderForm(), pdSignatureField);
// inner form stream, form and resource (holder form contains inner form)
pdfBuilder.createInnerFormStream(template);
pdfBuilder.createInnerFormResource();
PDResources innerFormResource = pdfStructure.getInnerFormResources();
pdfBuilder.createInnerForm(innerFormResource, pdfStructure.getInnerFormStream(), bbox);
PDFormXObject innerForm = pdfStructure.getInnerForm();
// inner form must be in the holder form as we wrote
pdfBuilder.insertInnerFormToHolderResources(innerForm, holderFormResources);
// Image form is in this structure: /AcroForm/DR/FRM/Resources/XObject/n2
pdfBuilder.createImageFormStream(template);
PDStream imageFormStream = pdfStructure.getImageFormStream();
pdfBuilder.createImageFormResources();
PDResources imageFormResources = pdfStructure.getImageFormResources();
pdfBuilder.createImageForm(imageFormResources, innerFormResource, imageFormStream, bbox, transform, pdfStructure.getImage());
pdfBuilder.createBackgroundLayerForm(innerFormResource, bbox);
// now inject procSetArray
pdfBuilder.injectProcSetArray(innerForm, page, innerFormResource, imageFormResources, holderFormResources, pdfStructure.getProcSet());
COSName imageFormName = pdfStructure.getImageFormName();
COSName imageName = pdfStructure.getImageName();
COSName innerFormName = pdfStructure.getInnerFormName();
// now create Streams of AP
pdfBuilder.injectAppearanceStreams(holderFormStream, imageFormStream, imageFormStream, imageFormName, imageName, innerFormName, properties);
pdfBuilder.createVisualSignature(template);
pdfBuilder.createWidgetDictionary(pdSignatureField, holderFormResources);
InputStream in = getVisualSignatureAsStream(pdfStructure.getVisualSignature());
Log.i("PdfBox-Android", "stream returning started, size= " + in.available());
// we must close the document
template.close();
// return result of the stream
return in;
}
use of com.tom_roush.pdfbox.pdmodel.interactive.form.PDSignatureField in project PdfBox-Android by TomRoush.
the class PDVisibleSigBuilder method createSignatureField.
@Override
public void createSignatureField(PDAcroForm acroForm) throws IOException {
PDSignatureField sf = new PDSignatureField(acroForm);
pdfStructure.setSignatureField(sf);
Log.i("PdfBox-Android", "Signature field has been created");
}
Aggregations