[poppler] poppler/Form.cc poppler/Form.h
Albert Astals Cid
aacid at kemper.freedesktop.org
Sat Nov 20 11:15:01 PST 2010
poppler/Form.cc | 88 +++++++++++++++++++++++++++++++-------------------------
poppler/Form.h | 14 +++++---
2 files changed, 58 insertions(+), 44 deletions(-)
New commits:
commit 555fa897b275ca7195f22a727b049c8c4f2d74cd
Author: Albert Astals Cid <aacid at kde.org>
Date: Sat Nov 20 19:14:38 2010 +0000
Detect loops in FormField creation
diff --git a/poppler/Form.cc b/poppler/Form.cc
index 78e46ef..74e8d90 100644
--- a/poppler/Form.cc
+++ b/poppler/Form.cc
@@ -759,7 +759,7 @@ FormWidgetSignature::FormWidgetSignature(XRef *xrefA, Object *aobj, unsigned num
// FormField
//========================================================================
-FormField::FormField(XRef* xrefA, Object *aobj, const Ref& aref, FormFieldType ty)
+FormField::FormField(XRef* xrefA, Object *aobj, const Ref& aref, std::set<int> *usedParents, FormFieldType ty)
{
xref = xrefA;
aobj->copy(&obj);
@@ -789,32 +789,43 @@ FormField::FormField(XRef* xrefA, Object *aobj, const Ref& aref, FormFieldType t
}
Object childRef;
array->getNF(i, &childRef);
- //field child
- if (dict->lookup ("FT", &obj3)->isName()) {
- // If I'm not a generic container field and my children
- // are widgets, create widgets for them
- Object obj4;
-
- if (obj2.dictLookup("Subtype",&obj4)->isName()) {
- _createWidget(&obj2, childRef.getRef());
- }
- obj4.free();
- } else if(obj2.dictLookup("FT", &obj3)->isName() || obj2.dictLookup("Kids", &obj3)->isArray()) {
- if(terminal) error(-1, "Field can't have both Widget AND Field as kids\n");
+ if (childRef.isRef()) {
+ const Ref ref = childRef.getRef();
+ if (usedParents->find(ref.num) == usedParents->end()) {
+ //field child
+ if (dict->lookup ("FT", &obj3)->isName()) {
+ // If I'm not a generic container field and my children
+ // are widgets, create widgets for them
+ Object obj4;
+
+ if (obj2.dictLookup("Subtype",&obj4)->isName()) {
+ _createWidget(&obj2, childRef.getRef());
+ }
+ obj4.free();
+ } else if(obj2.dictLookup("FT", &obj3)->isName() || obj2.dictLookup("Kids", &obj3)->isArray()) {
+ std::set<int> usedParentsAux = *usedParents;
+ usedParentsAux.insert(ref.num);
+ if(terminal) error(-1, "Field can't have both Widget AND Field as kids\n");
- numChildren++;
- children = (FormField**)greallocn(children, numChildren, sizeof(FormField*));
+ numChildren++;
+ children = (FormField**)greallocn(children, numChildren, sizeof(FormField*));
- obj3.free();
- children[numChildren-1] = Form::createFieldFromDict (&obj2, xrefA, childRef.getRef());
- }
- // 1 - we will handle 'collapsed' fields (field + annot in the same dict)
- // as if the annot was in the Kids array of the field
- else if (obj2.dictLookup("Subtype",&obj3)->isName()) {
- _createWidget(&obj2, childRef.getRef());
+ obj3.free();
+ children[numChildren-1] = Form::createFieldFromDict (&obj2, xrefA, childRef.getRef(), &usedParentsAux);
+ }
+ // 1 - we will handle 'collapsed' fields (field + annot in the same dict)
+ // as if the annot was in the Kids array of the field
+ else if (obj2.dictLookup("Subtype",&obj3)->isName()) {
+ _createWidget(&obj2, childRef.getRef());
+ }
+ obj3.free();
+ } else {
+ error(-1, "Found loop in FormField creation");
+ }
+ } else {
+ error(-1, "FormField child is not a Ref as expected");
}
obj2.free();
- obj3.free();
}
}
obj1.free();
@@ -926,8 +937,8 @@ FormWidget* FormField::findWidgetByRef (Ref aref)
//------------------------------------------------------------------------
// FormFieldButton
//------------------------------------------------------------------------
-FormFieldButton::FormFieldButton(XRef *xrefA, Object *aobj, const Ref& ref)
- : FormField(xrefA, aobj, ref, formButton)
+FormFieldButton::FormFieldButton(XRef *xrefA, Object *aobj, const Ref& ref, std::set<int> *usedParents)
+ : FormField(xrefA, aobj, ref, usedParents, formButton)
{
Dict* dict = obj.getDict();
active_child = -1;
@@ -1020,8 +1031,8 @@ FormFieldButton::~FormFieldButton()
//------------------------------------------------------------------------
// FormFieldText
//------------------------------------------------------------------------
-FormFieldText::FormFieldText(XRef *xrefA, Object *aobj, const Ref& ref)
- : FormField(xrefA, aobj, ref, formText)
+FormFieldText::FormFieldText(XRef *xrefA, Object *aobj, const Ref& ref, std::set<int> *usedParents)
+ : FormField(xrefA, aobj, ref, usedParents, formText)
{
Dict* dict = obj.getDict();
Object obj1;
@@ -1077,8 +1088,8 @@ FormFieldText::~FormFieldText()
//------------------------------------------------------------------------
// FormFieldChoice
//------------------------------------------------------------------------
-FormFieldChoice::FormFieldChoice(XRef *xrefA, Object *aobj, const Ref& ref)
- : FormField(xrefA, aobj, ref, formChoice)
+FormFieldChoice::FormFieldChoice(XRef *xrefA, Object *aobj, const Ref& ref, std::set<int> *usedParents)
+ : FormField(xrefA, aobj, ref, usedParents, formChoice)
{
numChoices = 0;
choices = NULL;
@@ -1171,8 +1182,8 @@ void FormFieldChoice::_createChoicesTab ()
//------------------------------------------------------------------------
// FormFieldSignature
//------------------------------------------------------------------------
-FormFieldSignature::FormFieldSignature(XRef *xrefA, Object *dict, const Ref& ref)
- : FormField(xrefA, dict, ref, formSignature)
+FormFieldSignature::FormFieldSignature(XRef *xrefA, Object *dict, const Ref& ref, std::set<int> *usedParents)
+ : FormField(xrefA, dict, ref, usedParents, formSignature)
{
}
@@ -1228,7 +1239,8 @@ Form::Form(XRef *xrefA, Object* acroFormA)
rootFields = (FormField**)greallocn(rootFields,size,sizeof(FormField*));
}
- rootFields[numFields++] = createFieldFromDict (&obj2, xrefA, oref.getRef());
+ std::set<int> usedParents;
+ rootFields[numFields++] = createFieldFromDict (&obj2, xrefA, oref.getRef(), &usedParents);
obj2.free();
oref.free();
@@ -1285,21 +1297,21 @@ Object *Form::fieldLookup(Dict *field, char *key, Object *obj) {
return ::fieldLookup(field, key, obj, &usedParents);
}
-FormField *Form::createFieldFromDict (Object* obj, XRef *xrefA, const Ref& pref)
+FormField *Form::createFieldFromDict (Object* obj, XRef *xrefA, const Ref& pref, std::set<int> *usedParents)
{
Object obj2;
FormField *field;
if (Form::fieldLookup(obj->getDict (), "FT", &obj2)->isName("Btn")) {
- field = new FormFieldButton(xrefA, obj, pref);
+ field = new FormFieldButton(xrefA, obj, pref, usedParents);
} else if (obj2.isName("Tx")) {
- field = new FormFieldText(xrefA, obj, pref);
+ field = new FormFieldText(xrefA, obj, pref, usedParents);
} else if (obj2.isName("Ch")) {
- field = new FormFieldChoice(xrefA, obj, pref);
+ field = new FormFieldChoice(xrefA, obj, pref, usedParents);
} else if (obj2.isName("Sig")) {
- field = new FormFieldSignature(xrefA, obj, pref);
+ field = new FormFieldSignature(xrefA, obj, pref, usedParents);
} else { //we don't have an FT entry => non-terminal field
- field = new FormField(xrefA, obj, pref);
+ field = new FormField(xrefA, obj, pref, usedParents);
}
obj2.free();
diff --git a/poppler/Form.h b/poppler/Form.h
index eb76fbb..106c556 100644
--- a/poppler/Form.h
+++ b/poppler/Form.h
@@ -20,6 +20,8 @@
#include "Object.h"
+#include <set>
+
class GooString;
class Array;
class Dict;
@@ -256,7 +258,7 @@ protected:
class FormField {
public:
- FormField(XRef* xrefa, Object *aobj, const Ref& aref, FormFieldType t=formUndef);
+ FormField(XRef* xrefa, Object *aobj, const Ref& aref, std::set<int> *usedParents, FormFieldType t=formUndef);
virtual ~FormField();
@@ -301,7 +303,7 @@ private:
class FormFieldButton: public FormField {
public:
- FormFieldButton(XRef *xrefA, Object *dict, const Ref& ref);
+ FormFieldButton(XRef *xrefA, Object *dict, const Ref& ref, std::set<int> *usedParents);
FormButtonType getButtonType () { return btype; }
@@ -326,7 +328,7 @@ protected:
class FormFieldText: public FormField {
public:
- FormFieldText(XRef *xrefA, Object *dict, const Ref& ref);
+ FormFieldText(XRef *xrefA, Object *dict, const Ref& ref, std::set<int> *usedParents);
GooString* getContent () { return content; }
GooString* getContentCopy ();
@@ -360,7 +362,7 @@ protected:
class FormFieldChoice: public FormField {
public:
- FormFieldChoice(XRef *xrefA, Object *aobj, const Ref& ref);
+ FormFieldChoice(XRef *xrefA, Object *aobj, const Ref& ref, std::set<int> *usedParents);
virtual ~FormFieldChoice();
@@ -423,7 +425,7 @@ protected:
class FormFieldSignature: public FormField {
public:
- FormFieldSignature(XRef *xrefA, Object *dict, const Ref& ref);
+ FormFieldSignature(XRef *xrefA, Object *dict, const Ref& ref, std::set<int> *usedParents);
virtual ~FormFieldSignature();
};
@@ -445,7 +447,7 @@ public:
/* Creates a new Field of the type specified in obj's dict.
used in Form::Form and FormField::FormField */
- static FormField *createFieldFromDict (Object* obj, XRef *xref, const Ref& aref);
+ static FormField *createFieldFromDict (Object* obj, XRef *xref, const Ref& aref, std::set<int> *usedParents);
Object *getObj () const { return acroForm; }
GBool getNeedAppearances () const { return needAppearances; }
More information about the poppler
mailing list