Hello,

I happened to come across signatures just like the one Andreas Kühne posted in 
September. As I need to be able to handle these signatures fairly soon (at 
least it looks like a greater hassle to persuade my users not to use the 
secunet application that creates these signatures), I created a small helper 
method that adds these signature fields not referenced in the annotation arrays 
of the document pages; this helper has to be applied to an AcroFields instance 
right after getting it from the PdfReader. Essentially it replaces the data 
collected by AcroFields.fill() with an extended set of fields in a way inspired 
by the that very method. 

It seems to work alright in my first tests, even though there might be some 
object releasing still to do; and obviously the duplicate code inside that 
method is not artful coding.

Primarily I do wonder, though, whether iText might have any trouble when later 
confronted with these additional entries among its fields, especially 
considering the PdfStamper and PdfCopy* classes when writing derived PDF 
documents.

Regards,   Michael.


Paulo Soares <psoares <at> glintt.com> writes:

> I'm not sure if this is a bug from iText but this things appear now and then 
> and,
> like it or not, if it works in Acrobat it must be right. I'll "fix" it.
> 
> Paulo
> 
> > -----Original Message-----
> > From: itext-questions-bounces <at> lists.sourceforge.net
> > [mailto:itext-questions-bounces <at> lists.sourceforge.net] On
> > Behalf Of Andreas Kuehne
> > Sent: Tuesday, September 09, 2008 4:08 PM
> > To: Post all your questions about iText here
> > Subject: [iText-questions] Signature not found : Bug or feature ?
> >
> > Hi,
> >
> > I'm not sure whether I'm going to submit a bug or request a
> > new feature :
> >
> > The AcroFields class has method returning all signatures (
> > getSignatureNames() ).
> >
> > Now I came across a pdf with a signature that doesn't get
> > returned by getSignatureNames(). On the other hand the
> > Acrobat Reader shows the signature without any problems.
> >
> > Analyzing the code shows that AcroFields are expected to be
> > related to a page. But the signature doesn't !
> > So my question is :
> >
> > Is it a bug to expect every signature to be assigned to a
> > page ( what isn't neccessarily so ) ?
> > Or do AcroFields are expected to be page-related 'by nature',
> > so my signature is just no AcroField and I must look for
> > another way to retrieve the signature ?
> >
> > The problematic signed PDF is attached.
> >
> > Opinions welcome
> >
> > Andreas

-- 
"Feel free" - 10 GB Mailbox, 100 FreeSMS/Monat ...
Jetzt GMX TopMail testen: http://www.gmx.net/de/go/topmail
/* $Id:$
 */
package com.lowagie.text.pdf;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import com.lowagie.text.pdf.AcroFields.Item;

public class AcroFieldsHelper
{
    public static void fill(AcroFields acroFields) {
        acroFields.fields = new HashMap();
        PdfDictionary top = 
(PdfDictionary)PdfReader.getPdfObjectRelease(acroFields.reader.getCatalog().get(PdfName.ACROFORM));
        if (top == null)
            return;
        PdfArray arrfds = 
(PdfArray)PdfReader.getPdfObjectRelease(top.get(PdfName.FIELDS));
        if (arrfds == null || arrfds.size() == 0)
            return;
        Map fields = collectFields(arrfds, null);
        System.out.println("Acrofields found: " + fields);
        arrfds = null;
        for (int k = 1; k <= acroFields.reader.getNumberOfPages(); ++k) {
            PdfDictionary page = acroFields.reader.getPageNRelease(k);
            PdfArray annots = 
(PdfArray)PdfReader.getPdfObjectRelease(page.get(PdfName.ANNOTS), page);
            if (annots == null)
                continue;
            ArrayList arr = annots.getArrayList();
            for (int j = 0; j < arr.size(); ++j) {
                System.out.println("\nAnnotation " + arr.get(j));
                PdfObject annoto = 
PdfReader.getPdfObject((PdfObject)arr.get(j), annots);
                if (!(annoto instanceof PdfDictionary)) {
                    PdfReader.releaseLastXrefPartial((PdfObject)arr.get(j));
                    continue;
                }
                PdfDictionary annot = (PdfDictionary)annoto;
                if (!PdfName.WIDGET.equals(annot.get(PdfName.SUBTYPE))) {
                    PdfReader.releaseLastXrefPartial((PdfObject)arr.get(j));
                    continue;
                }
                PdfDictionary widget = annot;
                PdfDictionary dic = new PdfDictionary();
                dic.putAll(annot);
                String name = "";
                PdfDictionary value = null;
                PdfObject lastV = null;
                while (annot != null) {
                    dic.mergeDifferent(annot);
                    PdfString t = 
(PdfString)PdfReader.getPdfObject(annot.get(PdfName.T));
                    if (t != null)
                        name = t.toUnicodeString() + "." + name;
                    if (lastV == null && annot.get(PdfName.V) != null)
                        lastV = 
PdfReader.getPdfObjectRelease(annot.get(PdfName.V));
                    if (value == null &&  t != null) {
                        value = annot;
                        if (annot.get(PdfName.V) == null && lastV  != null)
                            value.put(PdfName.V, lastV);
                    }
                    PdfObject parent = annot.get(PdfName.PARENT);
                    if (parent instanceof PdfIndirectReference)
                    {
                        System.out.println(" has parent " + parent);
                        Integer number = new 
Integer(((PdfIndirectReference)parent).getNumber());
                        fields.remove(number);
                    }
                    annot = (PdfDictionary)PdfReader.getPdfObject(parent, 
annot);
                }
                if (name.length() > 0)
                    name = name.substring(0, name.length() - 1);
                Item item = (Item)acroFields.fields.get(name);
                if (item == null) {
                    item = new Item();
                    acroFields.fields.put(name, item);
                }
                if (value == null)
                    item.values.add(widget);
                else
                    item.values.add(value);
                item.widgets.add(widget);
                item.widget_refs.add(arr.get(j)); // must be a reference
                if (top != null)
                    dic.mergeDifferent(top);
                item.merged.add(dic);
                item.page.add(new Integer(k));
                item.tabOrder.add(new Integer(j));
            }
        }
        System.out.println("Acrofields unaccounted for: " + fields);
        for(Iterator itUnbound = fields.entrySet().iterator(); 
itUnbound.hasNext(); )
        {
            Map.Entry unboundEntry = (Map.Entry)itUnbound.next();
            System.out.println("\nUnbound " + unboundEntry.getValue());
            PdfDictionary field = (PdfDictionary) 
PdfReader.getPdfObject((PdfObject) unboundEntry.getValue());
            PdfDictionary dic = new PdfDictionary();
            dic.putAll(field);
            String name = "";
            PdfDictionary value = null;
            PdfObject lastV = null;
            while (field != null) {
                dic.mergeDifferent(field);
                PdfString t = 
(PdfString)PdfReader.getPdfObject(field.get(PdfName.T));
                if (t != null)
                    name = t.toUnicodeString() + "." + name;
                if (lastV == null && field.get(PdfName.V) != null)
                    lastV = PdfReader.getPdfObjectRelease(field.get(PdfName.V));
                if (value == null &&  t != null) {
                    value = field;
                    if (field.get(PdfName.V) == null && lastV  != null)
                        value.put(PdfName.V, lastV);
                }
                PdfObject parent = field.get(PdfName.PARENT);
                if (parent instanceof PdfIndirectReference)
                {
                    System.out.println(" has parent " + parent);
                    Integer number = new 
Integer(((PdfIndirectReference)parent).getNumber());
                    fields.remove(number);
                }
                field = (PdfDictionary)PdfReader.getPdfObject(parent, field);
            }
            if (name.length() > 0)
                name = name.substring(0, name.length() - 1);
            Item item = (Item)acroFields.fields.get(name);
            if (item == null) {
                item = new Item();
                acroFields.fields.put(name, item);
            }
            if (value == null)
                item.values.add(field);
            else
                item.values.add(value);
            item.widgets.add(field);
            item.widget_refs.add(unboundEntry.getValue()); // must be a 
reference
            if (top != null)
                dic.mergeDifferent(top);
            item.merged.add(dic);
            item.page.add(new Integer(-1));
            item.tabOrder.add(new Integer(-1));
        }
    }

    
    
    static Map collectFields(PdfArray pdfArray, Map fields)
    {
        if (fields == null)
            fields = new HashMap();
        
        for (int j = 0; j < pdfArray.size(); ++j) {
            PdfIndirectReference fieldReference = 
pdfArray.getAsIndirectObject(j);
            Integer number = new Integer(fieldReference.getNumber());
            if (!fields.containsKey(number))
            {
                fields.put(number, fieldReference);
                PdfDictionary field = (PdfDictionary) 
PdfReader.getPdfObjectRelease(fieldReference);
                PdfArray contained = 
(PdfArray)PdfReader.getPdfObjectRelease(field.get(PdfName.FIELDS));
                if (contained != null)
                    fields = collectFields(contained, fields);
            }
        }
        
        return fields;
    }
}
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
iText-questions mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/itext-questions

Buy the iText book: http://www.1t3xt.com/docs/book.php

Reply via email to