Search in sources :

Example 1 with COSArray

use of com.tom_roush.pdfbox.cos.COSArray 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);
}
Also used : PDField(com.tom_roush.pdfbox.pdmodel.interactive.form.PDField) PDAnnotation(com.tom_roush.pdfbox.pdmodel.interactive.annotation.PDAnnotation) COSDocument(com.tom_roush.pdfbox.cos.COSDocument) PDAcroForm(com.tom_roush.pdfbox.pdmodel.interactive.form.PDAcroForm) COSArrayList(com.tom_roush.pdfbox.pdmodel.common.COSArrayList) COSArray(com.tom_roush.pdfbox.cos.COSArray) PDAnnotationWidget(com.tom_roush.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget) PDSignatureField(com.tom_roush.pdfbox.pdmodel.interactive.form.PDSignatureField)

Example 2 with COSArray

use of com.tom_roush.pdfbox.cos.COSArray in project PdfBox-Android by TomRoush.

the class PDFMergerUtility method acroFormLegacyMode.

/*
     * Merge the contents of the source form into the destination form for the
     * destination file.
     *
     * @param cloner the object cloner for the destination document
     * @param destAcroForm the destination form
     * @param srcAcroForm the source form
     * @throws IOException If an error occurs while adding the field.
     */
private void acroFormLegacyMode(PDFCloneUtility cloner, PDAcroForm destAcroForm, PDAcroForm srcAcroForm) throws IOException {
    List<PDField> srcFields = srcAcroForm.getFields();
    COSArray destFields;
    if (srcFields != null && !srcFields.isEmpty()) {
        // if a form is merged multiple times using PDFBox the newly generated
        // fields starting with dummyFieldName may already exist. We need to determine the last unique
        // number used and increment that.
        final String prefix = "dummyFieldName";
        final int prefixLength = prefix.length();
        for (PDField destField : destAcroForm.getFieldTree()) {
            String fieldName = destField.getPartialName();
            if (fieldName.startsWith(prefix)) {
                nextFieldNum = Math.max(nextFieldNum, Integer.parseInt(fieldName.substring(prefixLength, fieldName.length())) + 1);
            }
        }
        // get the destinations root fields. Could be that the entry doesn't exist
        // or is of wrong type
        COSBase base = destAcroForm.getCOSObject().getItem(COSName.FIELDS);
        if (base instanceof COSArray) {
            destFields = (COSArray) base;
        } else {
            destFields = new COSArray();
        }
        for (PDField srcField : srcAcroForm.getFields()) {
            COSDictionary dstField = (COSDictionary) cloner.cloneForNewDocument(srcField.getCOSObject());
            // to prevent merge conflicts.
            if (destAcroForm.getField(srcField.getFullyQualifiedName()) != null) {
                dstField.setString(COSName.T, prefix + nextFieldNum++);
            }
            destFields.add(dstField);
        }
        destAcroForm.getCOSObject().setItem(COSName.FIELDS, destFields);
    }
}
Also used : PDField(com.tom_roush.pdfbox.pdmodel.interactive.form.PDField) COSArray(com.tom_roush.pdfbox.cos.COSArray) COSDictionary(com.tom_roush.pdfbox.cos.COSDictionary) COSBase(com.tom_roush.pdfbox.cos.COSBase)

Example 3 with COSArray

use of com.tom_roush.pdfbox.cos.COSArray in project PdfBox-Android by TomRoush.

the class PDFMergerUtility method mergeFields.

private void mergeFields(PDFCloneUtility cloner, PDField destField, PDField srcField) {
    if (destField instanceof PDNonTerminalField && srcField instanceof PDNonTerminalField) {
        Log.i("PdfBox-Android", "Skipping non terminal field " + srcField.getFullyQualifiedName());
        return;
    }
    if (destField.getFieldType() == "Tx" && destField.getFieldType() == "Tx") {
        // if the field already has multiple widgets we can add to the array
        if (destField.getCOSObject().containsKey(COSName.KIDS)) {
            COSArray widgets = destField.getCOSObject().getCOSArray(COSName.KIDS);
            for (PDAnnotationWidget srcWidget : srcField.getWidgets()) {
                try {
                    widgets.add(cloner.cloneForNewDocument(srcWidget.getCOSObject()));
                } catch (IOException ioe) {
                    Log.w("PdfBox-Android", "Unable to clone widget for source field " + srcField.getFullyQualifiedName());
                }
            }
        } else {
            COSArray widgets = new COSArray();
            try {
                COSDictionary widgetAsCOS = (COSDictionary) cloner.cloneForNewDocument(destField.getWidgets().get(0));
                cleanupWidgetCOSDictionary(widgetAsCOS, true);
                widgetAsCOS.setItem(COSName.PARENT, destField);
                widgets.add(widgetAsCOS);
                for (PDAnnotationWidget srcWidget : srcField.getWidgets()) {
                    try {
                        widgetAsCOS = (COSDictionary) cloner.cloneForNewDocument(srcWidget.getCOSObject());
                        cleanupWidgetCOSDictionary(widgetAsCOS, false);
                        widgetAsCOS.setItem(COSName.PARENT, destField);
                        widgets.add(widgetAsCOS);
                    } catch (IOException ioe) {
                        Log.w("PdfBox-Android", "Unable to clone widget for source field " + srcField.getFullyQualifiedName());
                    }
                }
                destField.getCOSObject().setItem(COSName.KIDS, widgets);
                cleanupFieldCOSDictionary(destField.getCOSObject());
            } catch (IOException ioe) {
                Log.w("PdfBox-Android", "Unable to clone widget for destination field " + destField.getFullyQualifiedName());
            }
        }
    } else {
        Log.i("PdfBox-Android", "Only merging two text fields is currently supported");
        Log.i("PdfBox-Android", "Skipping merging of " + srcField.getFullyQualifiedName() + " into " + destField.getFullyQualifiedName());
    }
}
Also used : COSArray(com.tom_roush.pdfbox.cos.COSArray) COSDictionary(com.tom_roush.pdfbox.cos.COSDictionary) PDAnnotationWidget(com.tom_roush.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget) PDNonTerminalField(com.tom_roush.pdfbox.pdmodel.interactive.form.PDNonTerminalField) IOException(java.io.IOException)

Example 4 with COSArray

use of com.tom_roush.pdfbox.cos.COSArray in project PdfBox-Android by TomRoush.

the class BaseParser method parseCOSArray.

/**
 * This will parse a PDF array object.
 *
 * @return The parsed PDF array.
 *
 * @throws IOException If there is an error parsing the stream.
 */
protected COSArray parseCOSArray() throws IOException {
    long startPosition = seqSource.getPosition();
    readExpectedChar('[');
    COSArray po = new COSArray();
    COSBase pbo;
    skipSpaces();
    int i;
    while (((i = seqSource.peek()) > 0) && ((char) i != ']')) {
        pbo = parseDirObject();
        if (pbo instanceof COSObject) {
            // We have to check if the expected values are there or not PDFBOX-385
            if (po.size() > 0 && po.get(po.size() - 1) instanceof COSInteger) {
                COSInteger genNumber = (COSInteger) po.remove(po.size() - 1);
                if (po.size() > 0 && po.get(po.size() - 1) instanceof COSInteger) {
                    COSInteger number = (COSInteger) po.remove(po.size() - 1);
                    COSObjectKey key = new COSObjectKey(number.longValue(), genNumber.intValue());
                    pbo = getObjectFromPool(key);
                } else {
                    // the object reference is somehow wrong
                    pbo = null;
                }
            } else {
                pbo = null;
            }
        }
        if (pbo != null) {
            po.add(pbo);
        } else {
            // it could be a bad object in the array which is just skipped
            Log.w("PdfBox-Android", "Corrupt object reference at offset " + seqSource.getPosition() + ", start offset: " + startPosition);
            // This could also be an "endobj" or "endstream" which means we can assume that
            // the array has ended.
            String isThisTheEnd = readString();
            seqSource.unread(isThisTheEnd.getBytes(ISO_8859_1));
            if (ENDOBJ_STRING.equals(isThisTheEnd) || ENDSTREAM_STRING.equals(isThisTheEnd)) {
                return po;
            }
        }
        skipSpaces();
    }
    // read ']'
    seqSource.read();
    skipSpaces();
    return po;
}
Also used : COSObjectKey(com.tom_roush.pdfbox.cos.COSObjectKey) COSInteger(com.tom_roush.pdfbox.cos.COSInteger) COSArray(com.tom_roush.pdfbox.cos.COSArray) COSObject(com.tom_roush.pdfbox.cos.COSObject) COSBase(com.tom_roush.pdfbox.cos.COSBase) COSString(com.tom_roush.pdfbox.cos.COSString)

Example 5 with COSArray

use of com.tom_roush.pdfbox.cos.COSArray in project PdfBox-Android by TomRoush.

the class Overlay method processPages.

private void processPages(PDDocument document) throws IOException {
    int pageCounter = 0;
    for (PDPage page : document.getPages()) {
        pageCounter++;
        COSDictionary pageDictionary = page.getCOSObject();
        COSBase originalContent = pageDictionary.getDictionaryObject(COSName.CONTENTS);
        COSArray newContentArray = new COSArray();
        LayoutPage layoutPage = getLayoutPage(pageCounter, document.getNumberOfPages());
        if (layoutPage == null) {
            continue;
        }
        switch(position) {
            case FOREGROUND:
                // save state
                newContentArray.add(createStream("q\n"));
                addOriginalContent(originalContent, newContentArray);
                // restore state
                newContentArray.add(createStream("Q\n"));
                // overlay content last
                overlayPage(page, layoutPage, newContentArray);
                break;
            case BACKGROUND:
                // overlay content first
                overlayPage(page, layoutPage, newContentArray);
                addOriginalContent(originalContent, newContentArray);
                break;
            default:
                throw new IOException("Unknown type of position:" + position);
        }
        pageDictionary.setItem(COSName.CONTENTS, newContentArray);
    }
}
Also used : PDPage(com.tom_roush.pdfbox.pdmodel.PDPage) COSDictionary(com.tom_roush.pdfbox.cos.COSDictionary) COSArray(com.tom_roush.pdfbox.cos.COSArray) COSBase(com.tom_roush.pdfbox.cos.COSBase) IOException(java.io.IOException)

Aggregations

COSArray (com.tom_roush.pdfbox.cos.COSArray)293 COSBase (com.tom_roush.pdfbox.cos.COSBase)108 COSDictionary (com.tom_roush.pdfbox.cos.COSDictionary)68 COSString (com.tom_roush.pdfbox.cos.COSString)44 ArrayList (java.util.ArrayList)44 COSArrayList (com.tom_roush.pdfbox.pdmodel.common.COSArrayList)28 COSName (com.tom_roush.pdfbox.cos.COSName)27 IOException (java.io.IOException)18 COSNumber (com.tom_roush.pdfbox.cos.COSNumber)17 COSObject (com.tom_roush.pdfbox.cos.COSObject)17 COSFloat (com.tom_roush.pdfbox.cos.COSFloat)16 COSInteger (com.tom_roush.pdfbox.cos.COSInteger)14 Test (org.junit.Test)13 PDRectangle (com.tom_roush.pdfbox.pdmodel.common.PDRectangle)10 List (java.util.List)9 COSStream (com.tom_roush.pdfbox.cos.COSStream)8 PDDocument (com.tom_roush.pdfbox.pdmodel.PDDocument)8 Map (java.util.Map)7 AWTColor (com.tom_roush.harmony.awt.AWTColor)6 PDAnnotation (com.tom_roush.pdfbox.pdmodel.interactive.annotation.PDAnnotation)6