poppler/Form.cc | 88 +++++++++++++++++++++++++++++++------------------------- poppler/Form.h | 14 +++++--- 2 files changed, 58 insertions(+), 44 deletions(-)
New commits: commit 555fa897b275ca7195f22a727b049c8c4f2d74cd Author: Albert Astals Cid <[email protected]> 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; } _______________________________________________ poppler mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/poppler
