1 //========================================================================
2 //
3 // Form.cc
4 //
5 // This file is licensed under the GPLv2 or later
6 //
7 // Copyright 2006-2008 Julien Rebetez <julienr@svn.gnome.org>
8 // Copyright 2007-2012 Albert Astals Cid <aacid@kde.org>
9 // Copyright 2007-2008, 2011 Carlos Garcia Campos <carlosgc@gnome.org>
10 // Copyright 2007, 2013 Adrian Johnson <ajohnson@redneon.com>
11 // Copyright 2007 Iñigo Martínez <inigomartinez@gmail.com>
12 // Copyright 2008, 2011 Pino Toscano <pino@kde.org>
13 // Copyright 2008 Michael Vrable <mvrable@cs.ucsd.edu>
14 // Copyright 2009 Matthias Drochner <M.Drochner@fz-juelich.de>
15 // Copyright 2009 KDAB via Guillermo Amaral <gamaral@amaral.com.mx>
16 // Copyright 2010, 2012 Mark Riedesel <mark@klowner.com>
17 // Copyright 2012 Fabio D'Urso <fabiodurso@hotmail.it>
18 //
19 //========================================================================
20 
21 #include <config.h>
22 
23 #ifdef USE_GCC_PRAGMAS
24 #pragma implementation
25 #endif
26 
27 #include <set>
28 #include <stddef.h>
29 #include <string.h>
30 #include "goo/gmem.h"
31 #include "goo/GooString.h"
32 #include "Error.h"
33 #include "Object.h"
34 #include "Array.h"
35 #include "Dict.h"
36 #include "Gfx.h"
37 #include "Form.h"
38 #include "PDFDoc.h"
39 #include "XRef.h"
40 #include "PDFDocEncoding.h"
41 #include "Annot.h"
42 #include "Link.h"
43 
44 //return a newly allocated char* containing an UTF16BE string of size length
pdfDocEncodingToUTF16(GooString * orig,int * length)45 char* pdfDocEncodingToUTF16 (GooString* orig, int* length)
46 {
47   //double size, a unicode char takes 2 char, add 2 for the unicode marker
48   *length = 2+2*orig->getLength();
49   char *result = new char[(*length)];
50   char *cstring = orig->getCString();
51   //unicode marker
52   result[0] = 0xfe;
53   result[1] = 0xff;
54   //convert to utf16
55   for(int i=2,j=0; i<(*length); i+=2,j++) {
56     Unicode u = pdfDocEncoding[(unsigned int)((unsigned char)cstring[j])]&0xffff;
57     result[i] = (u >> 8) & 0xff;
58     result[i+1] = u & 0xff;
59   }
60   return result;
61 }
62 
convertToUtf16(GooString * pdfDocEncodingString)63 static GooString *convertToUtf16(GooString *pdfDocEncodingString)
64 {
65   int tmp_length;
66   char* tmp_str = pdfDocEncodingToUTF16(pdfDocEncodingString, &tmp_length);
67   delete pdfDocEncodingString;
68   pdfDocEncodingString = new GooString(tmp_str, tmp_length);
69   delete [] tmp_str;
70   return pdfDocEncodingString;
71 }
72 
73 
FormWidget(PDFDoc * docA,Object * aobj,unsigned num,Ref aref,FormField * fieldA)74 FormWidget::FormWidget(PDFDoc *docA, Object *aobj, unsigned num, Ref aref, FormField *fieldA)
75 {
76   ref = aref;
77   ID = 0;
78   childNum = num;
79   doc = docA;
80   xref = doc->getXRef();
81   aobj->copy(&obj);
82   type = formUndef;
83   field = fieldA;
84   widget = NULL;
85 }
86 
~FormWidget()87 FormWidget::~FormWidget()
88 {
89   if (widget)
90     widget->decRefCnt();
91   obj.free ();
92 }
93 
94 #ifdef DEBUG_FORMS
print(int indent)95 void FormWidget::print(int indent) {
96   printf ("%*s+ (%d %d): [widget]\n", indent, "", ref.num, ref.gen);
97 }
98 #endif
99 
createWidgetAnnotation()100 void FormWidget::createWidgetAnnotation() {
101   if (widget)
102     return;
103 
104   Object obj1;
105   obj1.initRef(ref.num, ref.gen);
106   widget = new AnnotWidget(doc, obj.getDict(), &obj1, field);
107   obj1.free();
108 }
109 
inRect(double x,double y) const110 GBool FormWidget::inRect(double x, double y) const {
111   return widget ? widget->inRect(x, y) : gFalse;
112 }
113 
getRect(double * x1,double * y1,double * x2,double * y2) const114 void FormWidget::getRect(double *x1, double *y1, double *x2, double *y2) const {
115   if (widget)
116     widget->getRect(x1, y1, x2, y2);
117 }
118 
getFontSize() const119 double FormWidget::getFontSize() const {
120   return widget ? widget->getFontSize() : 0.;
121 }
122 
isReadOnly() const123 bool FormWidget::isReadOnly() const
124 {
125   return field->isReadOnly();
126 }
127 
encodeID(unsigned pageNum,unsigned fieldNum)128 int FormWidget::encodeID (unsigned pageNum, unsigned fieldNum)
129 {
130   return (pageNum << 4*sizeof(unsigned)) + fieldNum;
131 }
132 
decodeID(unsigned id,unsigned * pageNum,unsigned * fieldNum)133 void FormWidget::decodeID (unsigned id, unsigned* pageNum, unsigned* fieldNum)
134 {
135   *pageNum = id >> 4*sizeof(unsigned);
136   *fieldNum = (id << 4*sizeof(unsigned)) >> 4*sizeof(unsigned);
137 }
138 
getPartialName() const139 GooString *FormWidget::getPartialName() const {
140   return field->getPartialName();
141 }
142 
getAlternateUiName() const143 GooString *FormWidget::getAlternateUiName() const {
144   return field->getAlternateUiName();
145 }
146 
getMappingName() const147 GooString *FormWidget::getMappingName() const {
148   return field->getMappingName();
149 }
150 
getFullyQualifiedName()151 GooString *FormWidget::getFullyQualifiedName() {
152   return field->getFullyQualifiedName();
153 }
154 
getActivationAction()155 LinkAction *FormWidget::getActivationAction() {
156   return widget ? widget->getAction() : NULL;
157 }
158 
getAdditionalAction(Annot::FormAdditionalActionsType type)159 LinkAction *FormWidget::getAdditionalAction(Annot::FormAdditionalActionsType type) {
160   return widget ? widget->getFormAdditionalAction(type) : NULL;
161 }
162 
FormWidgetButton(PDFDoc * docA,Object * aobj,unsigned num,Ref ref,FormField * p)163 FormWidgetButton::FormWidgetButton (PDFDoc *docA, Object *aobj, unsigned num, Ref ref, FormField *p) :
164 	FormWidget(docA, aobj, num, ref, p)
165 {
166   type = formButton;
167   parent = static_cast<FormFieldButton*>(field);
168   onStr = NULL;
169 
170   Object obj1, obj2;
171 
172   // Find the name of the ON state in the AP dictionnary
173   // The reference say the Off state, if it existe, _must_ be stored in the AP dict under the name /Off
174   // The "on" state may be stored under any other name
175   if (obj.dictLookup("AP", &obj1)->isDict()) {
176     if (obj1.dictLookup("N", &obj2)->isDict()) {
177       for (int i = 0; i < obj2.dictGetLength(); i++) {
178         char *key = obj2.dictGetKey(i);
179         if (strcmp (key, "Off") != 0) {
180           onStr = new GooString (key);
181           break;
182         }
183       }
184     }
185     obj2.free();
186   }
187   obj1.free();
188 }
189 
getOnStr()190 char *FormWidgetButton::getOnStr() {
191   if (onStr)
192     return onStr->getCString();
193 
194   // 12.7.4.2.3 Check Boxes
195   //  Yes should be used as the name for the on state
196   return parent->getButtonType() == formButtonCheck ? (char *)"Yes" : NULL;
197 }
198 
~FormWidgetButton()199 FormWidgetButton::~FormWidgetButton ()
200 {
201   delete onStr;
202 }
203 
getButtonType() const204 FormButtonType FormWidgetButton::getButtonType () const
205 {
206   return parent->getButtonType ();
207 }
208 
setAppearanceState(const char * state)209 void FormWidgetButton::setAppearanceState(const char *state) {
210   if (!widget)
211     return;
212   widget->setAppearanceState(state);
213 }
214 
updateWidgetAppearance()215 void FormWidgetButton::updateWidgetAppearance()
216 {
217   // The appearance stream must NOT be regenerated for this widget type
218 }
219 
setState(GBool astate)220 void FormWidgetButton::setState (GBool astate)
221 {
222   //pushButtons don't have state
223   if (parent->getButtonType() == formButtonPush)
224     return;
225 
226   // Silently return if can't set ON state
227   if (astate && !onStr)
228     return;
229 
230   parent->setState(astate ? onStr->getCString() : (char *)"Off");
231   // Parent will call setAppearanceState()
232 }
233 
getState()234 GBool FormWidgetButton::getState ()
235 {
236   return onStr ? parent->getState(onStr->getCString()) : gFalse;
237 }
238 
239 
FormWidgetText(PDFDoc * docA,Object * aobj,unsigned num,Ref ref,FormField * p)240 FormWidgetText::FormWidgetText (PDFDoc *docA, Object *aobj, unsigned num, Ref ref, FormField *p) :
241 	FormWidget(docA, aobj, num, ref, p)
242 {
243   type = formText;
244   parent = static_cast<FormFieldText*>(field);
245 }
246 
getContent()247 GooString* FormWidgetText::getContent ()
248 {
249   return parent->getContent();
250 }
251 
getContentCopy()252 GooString* FormWidgetText::getContentCopy ()
253 {
254   return parent->getContentCopy();
255 }
256 
updateWidgetAppearance()257 void FormWidgetText::updateWidgetAppearance()
258 {
259   if (widget)
260     widget->updateAppearanceStream();
261 }
262 
isMultiline() const263 bool FormWidgetText::isMultiline () const
264 {
265   return parent->isMultiline();
266 }
267 
isPassword() const268 bool FormWidgetText::isPassword () const
269 {
270   return parent->isPassword();
271 }
272 
isFileSelect() const273 bool FormWidgetText::isFileSelect () const
274 {
275   return parent->isFileSelect();
276 }
277 
noSpellCheck() const278 bool FormWidgetText::noSpellCheck () const
279 {
280   return parent->noSpellCheck();
281 }
282 
noScroll() const283 bool FormWidgetText::noScroll () const
284 {
285   return parent->noScroll();
286 }
287 
isComb() const288 bool FormWidgetText::isComb () const
289 {
290   return parent->isComb();
291 }
292 
isRichText() const293 bool FormWidgetText::isRichText () const
294 {
295   return parent->isRichText();
296 }
297 
getMaxLen() const298 int FormWidgetText::getMaxLen () const
299 {
300   return parent->getMaxLen ();
301 }
302 
setContent(GooString * new_content)303 void FormWidgetText::setContent(GooString* new_content)
304 {
305   if (isReadOnly()) {
306     error(errInternal, -1, "FormWidgetText::setContentCopy called on a read only field\n");
307     return;
308   }
309 
310   parent->setContentCopy(new_content);
311 }
312 
FormWidgetChoice(PDFDoc * docA,Object * aobj,unsigned num,Ref ref,FormField * p)313 FormWidgetChoice::FormWidgetChoice(PDFDoc *docA, Object *aobj, unsigned num, Ref ref, FormField *p) :
314 	FormWidget(docA, aobj, num, ref, p)
315 {
316   type = formChoice;
317   parent = static_cast<FormFieldChoice*>(field);
318 }
319 
~FormWidgetChoice()320 FormWidgetChoice::~FormWidgetChoice()
321 {
322 }
323 
_checkRange(int i)324 bool FormWidgetChoice::_checkRange (int i)
325 {
326   if (i < 0 || i >= parent->getNumChoices()) {
327     error(errInternal, -1, "FormWidgetChoice::_checkRange i out of range : {0:d}", i);
328     return false;
329   }
330   return true;
331 }
332 
select(int i)333 void FormWidgetChoice::select (int i)
334 {
335   if (isReadOnly()) {
336     error(errInternal, -1, "FormWidgetChoice::select called on a read only field\n");
337     return;
338   }
339   if (!_checkRange(i)) return;
340   parent->select(i);
341 }
342 
toggle(int i)343 void FormWidgetChoice::toggle (int i)
344 {
345   if (isReadOnly()) {
346     error(errInternal, -1, "FormWidgetChoice::toggle called on a read only field\n");
347     return;
348   }
349   if (!_checkRange(i)) return;
350   parent->toggle(i);
351 }
352 
deselectAll()353 void FormWidgetChoice::deselectAll ()
354 {
355   if (isReadOnly()) {
356     error(errInternal, -1, "FormWidgetChoice::deselectAll called on a read only field\n");
357     return;
358   }
359   parent->deselectAll();
360 }
361 
getEditChoice()362 GooString* FormWidgetChoice::getEditChoice ()
363 {
364   if (!hasEdit()) {
365     error(errInternal, -1, "FormFieldChoice::getEditChoice called on a non-editable choice\n");
366     return NULL;
367   }
368   return parent->getEditChoice();
369 }
370 
updateWidgetAppearance()371 void FormWidgetChoice::updateWidgetAppearance()
372 {
373   if (widget)
374     widget->updateAppearanceStream();
375 }
376 
isSelected(int i)377 bool FormWidgetChoice::isSelected (int i)
378 {
379   if (!_checkRange(i)) return false;
380   return parent->isSelected(i);
381 }
382 
setEditChoice(GooString * new_content)383 void FormWidgetChoice::setEditChoice (GooString* new_content)
384 {
385   if (isReadOnly()) {
386     error(errInternal, -1, "FormWidgetText::setEditChoice called on a read only field\n");
387     return;
388   }
389   if (!hasEdit()) {
390     error(errInternal, -1, "FormFieldChoice::setEditChoice : trying to edit an non-editable choice\n");
391     return;
392   }
393 
394   parent->setEditChoice(new_content);
395 }
396 
getNumChoices()397 int FormWidgetChoice::getNumChoices()
398 {
399   return parent->getNumChoices();
400 }
401 
getChoice(int i)402 GooString* FormWidgetChoice::getChoice(int i)
403 {
404   return parent->getChoice(i);
405 }
406 
isCombo() const407 bool FormWidgetChoice::isCombo () const
408 {
409   return parent->isCombo();
410 }
411 
hasEdit() const412 bool FormWidgetChoice::hasEdit () const
413 {
414   return parent->hasEdit();
415 }
416 
isMultiSelect() const417 bool FormWidgetChoice::isMultiSelect () const
418 {
419   return parent->isMultiSelect();
420 }
421 
noSpellCheck() const422 bool FormWidgetChoice::noSpellCheck () const
423 {
424   return parent->noSpellCheck();
425 }
426 
commitOnSelChange() const427 bool FormWidgetChoice::commitOnSelChange () const
428 {
429   return parent->commitOnSelChange();
430 }
431 
isListBox() const432 bool FormWidgetChoice::isListBox () const
433 {
434   return parent->isListBox();
435 }
436 
FormWidgetSignature(PDFDoc * docA,Object * aobj,unsigned num,Ref ref,FormField * p)437 FormWidgetSignature::FormWidgetSignature(PDFDoc *docA, Object *aobj, unsigned num, Ref ref, FormField *p) :
438 	FormWidget(docA, aobj, num, ref, p)
439 {
440   type = formSignature;
441   parent = static_cast<FormFieldSignature*>(field);
442 }
443 
updateWidgetAppearance()444 void FormWidgetSignature::updateWidgetAppearance()
445 {
446   // Unimplemented
447 }
448 
449 
450 //========================================================================
451 // FormField
452 //========================================================================
453 
FormField(PDFDoc * docA,Object * aobj,const Ref & aref,FormField * parentA,std::set<int> * usedParents,FormFieldType ty)454 FormField::FormField(PDFDoc *docA, Object *aobj, const Ref& aref, FormField *parentA, std::set<int> *usedParents, FormFieldType ty)
455 {
456   doc = docA;
457   xref = doc->getXRef();
458   aobj->copy(&obj);
459   Dict* dict = obj.getDict();
460   ref.num = ref.gen = 0;
461   type = ty;
462   parent = parentA;
463   numChildren = 0;
464   children = NULL;
465   terminal = false;
466   widgets = NULL;
467   readOnly = false;
468   defaultAppearance = NULL;
469   fullyQualifiedName = NULL;
470   quadding = quaddingLeftJustified;
471   hasQuadding = gFalse;
472 
473   ref = aref;
474 
475   Object obj1;
476   //childs
477   if (dict->lookup("Kids", &obj1)->isArray()) {
478     // Load children
479     for (int i = 0 ; i < obj1.arrayGetLength(); i++) {
480       Object childRef, childObj;
481 
482       if (!obj1.arrayGetNF(i, &childRef)->isRef()) {
483         error (errSyntaxError, -1, "Invalid form field renference");
484         childRef.free();
485         continue;
486       }
487       if (!obj1.arrayGet(i, &childObj)->isDict()) {
488         error (errSyntaxError, -1, "Form field child is not a dictionary");
489         childObj.free();
490         childRef.free();
491         continue;
492       }
493 
494       const Ref ref = childRef.getRef();
495       if (usedParents->find(ref.num) == usedParents->end()) {
496         Object obj2, obj3;
497         // Field child: it could be a form field or a widget or composed dict
498         if (childObj.dictLookupNF("Parent", &obj2)->isRef() || childObj.dictLookup("Parent", &obj3)->isDict()) {
499           // Child is a form field or composed dict
500           // We create the field, if it's composed
501           // it will create the widget as a child
502           std::set<int> usedParentsAux = *usedParents;
503           usedParentsAux.insert(ref.num);
504           obj2.free();
505           obj3.free();
506 
507           if (terminal) {
508             error(errSyntaxWarning, -1, "Field can't have both Widget AND Field as kids\n");
509             continue;
510           }
511 
512           numChildren++;
513           children = (FormField**)greallocn(children, numChildren, sizeof(FormField*));
514           children[numChildren - 1] = Form::createFieldFromDict(&childObj, doc, ref, this, &usedParentsAux);
515         } else if (childObj.dictLookup("Subtype", &obj2)->isName("Widget")) {
516           // Child is a widget annotation
517           if (!terminal && numChildren > 0) {
518             error(errSyntaxWarning, -1, "Field can't have both Widget AND Field as kids\n");
519             obj2.free();
520             obj3.free();
521             continue;
522           }
523           _createWidget(&childObj, ref);
524         }
525         obj2.free();
526         obj3.free();
527       }
528       childObj.free();
529       childRef.free();
530     }
531   } else {
532     // No children, if it's a composed dict, create the child widget
533     obj1.free();
534     if (dict->lookup("Subtype", &obj1)->isName("Widget"))
535       _createWidget(&obj, ref);
536   }
537   obj1.free();
538 
539   //flags
540   if (Form::fieldLookup(dict, "Ff", &obj1)->isInt()) {
541     int flags = obj1.getInt();
542     if (flags & 0x1) { // 1 -> ReadOnly
543       readOnly = true;
544     }
545     if (flags & 0x2) { // 2 -> Required
546       //TODO
547     }
548     if (flags & 0x4) { // 3 -> NoExport
549       //TODO
550     }
551   }
552   obj1.free();
553 
554   // Variable Text
555   if (Form::fieldLookup(dict, "DA", &obj1)->isString())
556     defaultAppearance = obj1.getString()->copy();
557   obj1.free();
558 
559   if (Form::fieldLookup(dict, "Q", &obj1)->isInt()) {
560     quadding = static_cast<VariableTextQuadding>(obj1.getInt());
561     hasQuadding = gTrue;
562   }
563   obj1.free();
564 
565   if (dict->lookup("T", &obj1)->isString()) {
566     partialName = obj1.getString()->copy();
567   } else {
568     partialName = NULL;
569   }
570   obj1.free();
571 
572   if (dict->lookup("TU", &obj1)->isString()) {
573     alternateUiName = obj1.getString()->copy();
574   } else {
575     alternateUiName = NULL;
576   }
577   obj1.free();
578 
579   if(dict->lookup("TM", &obj1)->isString()) {
580     mappingName = obj1.getString()->copy();
581   } else {
582     mappingName = NULL;
583   }
584   obj1.free();
585 }
586 
~FormField()587 FormField::~FormField()
588 {
589   if (!terminal) {
590     if(children) {
591       for (int i=0; i<numChildren; i++)
592         delete children[i];
593       gfree(children);
594     }
595   } else {
596     for (int i = 0; i < numChildren; ++i)
597       delete widgets[i];
598     gfree (widgets);
599   }
600   obj.free();
601 
602   delete defaultAppearance;
603   delete partialName;
604   delete alternateUiName;
605   delete mappingName;
606   delete fullyQualifiedName;
607 }
608 
609 #ifdef DEBUG_FORMS
print(int indent)610 void FormField::print(int indent)
611 {
612   printf ("%*s- (%d %d): [container] terminal: %s children: %d\n", indent, "", ref.num, ref.gen,
613           terminal ? "Yes" : "No", numChildren);
614 }
615 
printTree(int indent)616 void FormField::printTree(int indent)
617 {
618   print(indent);
619   if (terminal) {
620     for (int i = 0; i < numChildren; i++)
621       widgets[i]->print(indent + 4);
622   } else {
623     for (int i = 0; i < numChildren; i++)
624       children[i]->printTree(indent + 4);
625   }
626 }
627 #endif
628 
fillChildrenSiblingsID()629 void FormField::fillChildrenSiblingsID()
630 {
631   if (terminal)
632     return;
633   for (int i = 0; i < numChildren; i++) {
634     children[i]->fillChildrenSiblingsID();
635   }
636 }
637 
createWidgetAnnotations()638 void FormField::createWidgetAnnotations() {
639   if (terminal) {
640     for (int i = 0; i < numChildren; i++)
641       widgets[i]->createWidgetAnnotation();
642   } else {
643     for (int i = 0; i < numChildren; i++)
644       children[i]->createWidgetAnnotations();
645   }
646 }
647 
_createWidget(Object * obj,Ref aref)648 void FormField::_createWidget (Object *obj, Ref aref)
649 {
650   terminal = true;
651   numChildren++;
652   widgets = (FormWidget**)greallocn(widgets, numChildren, sizeof(FormWidget*));
653   //ID = index in "widgets" table
654   switch (type) {
655   case formButton:
656     widgets[numChildren-1] = new FormWidgetButton(doc, obj, numChildren-1, aref, this);
657     break;
658   case formText:
659     widgets[numChildren-1] = new FormWidgetText(doc, obj, numChildren-1, aref, this);
660     break;
661   case formChoice:
662     widgets[numChildren-1] = new FormWidgetChoice(doc, obj, numChildren-1, aref, this);
663     break;
664   case formSignature:
665     widgets[numChildren-1] = new FormWidgetSignature(doc, obj, numChildren-1, aref, this);
666     break;
667   default:
668     error(errSyntaxWarning, -1, "SubType on non-terminal field, invalid document?");
669     numChildren--;
670     terminal = false;
671   }
672 }
673 
findWidgetByRef(Ref aref)674 FormWidget* FormField::findWidgetByRef (Ref aref)
675 {
676   if (terminal) {
677     for(int i=0; i<numChildren; i++) {
678       if (widgets[i]->getRef().num == aref.num
679           && widgets[i]->getRef().gen == aref.gen)
680         return widgets[i];
681     }
682   } else {
683     for(int i=0; i<numChildren; i++) {
684       FormWidget* result = children[i]->findWidgetByRef(aref);
685       if(result) return result;
686     }
687   }
688   return NULL;
689 }
690 
getFullyQualifiedName()691 GooString* FormField::getFullyQualifiedName() {
692   Object obj1, obj2;
693   Object parent;
694   GooString *parent_name;
695   GooString *full_name;
696   GBool unicode_encoded = gFalse;
697 
698   if (fullyQualifiedName)
699     return fullyQualifiedName;
700 
701   full_name = new GooString();
702 
703   obj.copy(&obj1);
704   while (obj1.dictLookup("Parent", &parent)->isDict()) {
705     if (parent.dictLookup("T", &obj2)->isString()) {
706       parent_name = obj2.getString();
707 
708       if (unicode_encoded) {
709         full_name->insert(0, "\0.", 2); // 2-byte unicode period
710         if (parent_name->hasUnicodeMarker()) {
711           full_name->insert(0, parent_name->getCString() + 2, parent_name->getLength() - 2); // Remove the unicode BOM
712         } else {
713           int tmp_length;
714           char* tmp_str = pdfDocEncodingToUTF16(parent_name, &tmp_length);
715           full_name->insert(0, tmp_str + 2, tmp_length - 2); // Remove the unicode BOM
716           delete [] tmp_str;
717         }
718       } else {
719         full_name->insert(0, '.'); // 1-byte ascii period
720         if (parent_name->hasUnicodeMarker()) {
721           unicode_encoded = gTrue;
722           full_name = convertToUtf16(full_name);
723           full_name->insert(0, parent_name->getCString() + 2, parent_name->getLength() - 2); // Remove the unicode BOM
724         } else {
725           full_name->insert(0, parent_name);
726         }
727       }
728       obj2.free();
729     }
730     obj1.free();
731     parent.copy(&obj1);
732     parent.free();
733   }
734   obj1.free();
735   parent.free();
736 
737   if (partialName) {
738     if (unicode_encoded) {
739       if (partialName->hasUnicodeMarker()) {
740         full_name->append(partialName->getCString() + 2, partialName->getLength() - 2); // Remove the unicode BOM
741       } else {
742         int tmp_length;
743         char* tmp_str = pdfDocEncodingToUTF16(partialName, &tmp_length);
744         full_name->append(tmp_str + 2, tmp_length - 2); // Remove the unicode BOM
745         delete [] tmp_str;
746       }
747     } else {
748       if (partialName->hasUnicodeMarker()) {
749           unicode_encoded = gTrue;
750           full_name = convertToUtf16(full_name);
751           full_name->append(partialName->getCString() + 2, partialName->getLength() - 2); // Remove the unicode BOM
752       } else {
753         full_name->append(partialName);
754       }
755     }
756   } else {
757     int len = full_name->getLength();
758     // Remove the last period
759     if (unicode_encoded) {
760       if (len > 1) {
761         full_name->del(len - 2, 2);
762       }
763     } else {
764       if (len > 0) {
765         full_name->del(len - 1, 1);
766       }
767     }
768   }
769 
770   if (unicode_encoded) {
771     full_name->insert(0, 0xff);
772     full_name->insert(0, 0xfe);
773   }
774 
775   fullyQualifiedName = full_name;
776   return fullyQualifiedName;
777 }
778 
updateChildrenAppearance()779 void FormField::updateChildrenAppearance()
780 {
781   // Recursively update each child's appearance
782   if (terminal) {
783     for (int i = 0; i < numChildren; i++)
784       widgets[i]->updateWidgetAppearance();
785   } else {
786     for (int i = 0; i < numChildren; i++)
787       children[i]->updateChildrenAppearance();
788   }
789 }
790 
791 //------------------------------------------------------------------------
792 // FormFieldButton
793 //------------------------------------------------------------------------
FormFieldButton(PDFDoc * docA,Object * aobj,const Ref & ref,FormField * parent,std::set<int> * usedParents)794 FormFieldButton::FormFieldButton(PDFDoc *docA, Object *aobj, const Ref& ref, FormField *parent, std::set<int> *usedParents)
795   : FormField(docA, aobj, ref, parent, usedParents, formButton)
796 {
797   Dict* dict = obj.getDict();
798   active_child = -1;
799   noAllOff = false;
800   siblings = NULL;
801   numSiblings = 0;
802   appearanceState.initNull();
803 
804   Object obj1;
805   btype = formButtonCheck;
806   if (Form::fieldLookup(dict, "Ff", &obj1)->isInt()) {
807     int flags = obj1.getInt();
808 
809     if (flags & 0x10000) { // 17 -> push button
810       btype = formButtonPush;
811     } else if (flags & 0x8000) { // 16 -> radio button
812       btype = formButtonRadio;
813       if (flags & 0x4000) { // 15 -> noToggleToOff
814         noAllOff = true;
815       }
816     }
817     if (flags & 0x1000000) { // 26 -> radiosInUnison
818       error(errUnimplemented, -1, "FormFieldButton:: radiosInUnison flag unimplemented, please report a bug with a testcase\n");
819     }
820   }
821 
822   if (btype != formButtonPush) {
823     // Even though V is inheritable we are interested in the value of this
824     // field, if not present it's probably because it's a button in a set.
825     dict->lookup("V", &appearanceState);
826   }
827 }
828 
829 #ifdef DEBUG_FORMS
_getButtonType(FormButtonType type)830 static char *_getButtonType(FormButtonType type)
831 {
832   switch (type) {
833   case formButtonPush:
834     return "push";
835   case formButtonCheck:
836     return "check";
837   case formButtonRadio:
838     return "radio";
839   default:
840     break;
841   }
842   return "unknown";
843 }
844 
print(int indent)845 void FormFieldButton::print(int indent)
846 {
847   printf ("%*s- (%d %d): [%s] terminal: %s children: %d\n", indent, "", ref.num, ref.gen,
848           _getButtonType(btype), terminal ? "Yes" : "No", numChildren);
849 }
850 #endif
851 
setNumSiblings(int num)852 void FormFieldButton::setNumSiblings (int num)
853 {
854   numSiblings = num;
855   siblings = (FormFieldButton**)greallocn(siblings, numSiblings, sizeof(FormFieldButton*));
856 }
857 
fillChildrenSiblingsID()858 void FormFieldButton::fillChildrenSiblingsID()
859 {
860   if (!terminal) {
861     for(int i=0; i<numChildren; i++) {
862       FormFieldButton *child = dynamic_cast<FormFieldButton*>(children[i]);
863       if (child != NULL) {
864         // Fill the siblings of this node childs
865         child->setNumSiblings(numChildren-1);
866         for(int j=0, counter=0; j<numChildren; j++) {
867           FormFieldButton *otherChild = dynamic_cast<FormFieldButton*>(children[j]);
868           if (i == j) continue;
869           if (child == otherChild) continue;
870           child->setSibling(counter, otherChild);
871           counter++;
872         }
873 
874         // now call ourselves on the child
875         // to fill its children data
876         child->fillChildrenSiblingsID();
877       }
878     }
879   }
880 }
881 
setState(char * state)882 GBool FormFieldButton::setState(char *state)
883 {
884   if (readOnly) {
885     error(errInternal, -1, "FormFieldButton::setState called on a readOnly field\n");
886     return gFalse;
887   }
888 
889   // A check button could behave as a radio button
890   // when it's in a set of more than 1 buttons
891   if (btype != formButtonRadio && btype != formButtonCheck)
892     return gFalse;
893 
894   if (terminal && parent && parent->getType() == formButton && appearanceState.isNull()) {
895     // It's button in a set, set state on parent
896     if (static_cast<FormFieldButton*>(parent)->setState(state)) {
897       return gTrue;
898     }
899     return gFalse;
900   }
901 
902   GBool isOn = strcmp(state, "Off") != 0;
903 
904   if (!isOn && noAllOff)
905     return gFalse; // Don't allow to set all radio to off
906 
907   char *current = getAppearanceState();
908   GBool currentFound = gFalse, newFound = gFalse;
909 
910   for (int i = 0; i < numChildren; i++) {
911     FormWidgetButton *widget;
912 
913     // If radio button is a terminal field we want the widget at i, but
914     // if it's not terminal, the child widget is a composed dict, so
915     // we want the ony child widget of the children at i
916     if (terminal)
917       widget = static_cast<FormWidgetButton*>(widgets[i]);
918     else
919       widget = static_cast<FormWidgetButton*>(children[i]->getWidget(0));
920 
921     if (!widget->getOnStr())
922       continue;
923 
924     char *onStr = widget->getOnStr();
925     if (current && strcmp(current, onStr) == 0) {
926       widget->setAppearanceState("Off");
927       if (!isOn)
928         break;
929       currentFound = gTrue;
930     }
931 
932     if (isOn && strcmp(state, onStr) == 0) {
933       widget->setAppearanceState(state);
934       newFound = gTrue;
935     }
936 
937     if (currentFound && newFound)
938       break;
939   }
940 
941   updateState(state);
942 
943   return gTrue;
944 }
945 
getState(char * state)946 GBool FormFieldButton::getState(char *state) {
947   if (appearanceState.isName(state))
948     return gTrue;
949 
950   return (parent && parent->getType() == formButton) ? static_cast<FormFieldButton*>(parent)->getState(state) : gFalse;
951 }
952 
updateState(char * state)953 void FormFieldButton::updateState(char *state) {
954   Object obj1;
955 
956   appearanceState.free();
957   appearanceState.initName(state);
958 
959   appearanceState.copy(&obj1);
960   obj.getDict()->set("V", &obj1);
961   xref->setModifiedObject(&obj, ref);
962 }
963 
~FormFieldButton()964 FormFieldButton::~FormFieldButton()
965 {
966   appearanceState.free();
967   if (siblings)
968     gfree(siblings);
969 }
970 
971 //------------------------------------------------------------------------
972 // FormFieldText
973 //------------------------------------------------------------------------
FormFieldText(PDFDoc * docA,Object * aobj,const Ref & ref,FormField * parent,std::set<int> * usedParents)974 FormFieldText::FormFieldText(PDFDoc *docA, Object *aobj, const Ref& ref, FormField *parent, std::set<int> *usedParents)
975   : FormField(docA, aobj, ref, parent, usedParents, formText)
976 {
977   Dict* dict = obj.getDict();
978   Object obj1;
979   content = NULL;
980   multiline = password = fileSelect = doNotSpellCheck = doNotScroll = comb = richText = false;
981   maxLen = 0;
982 
983   if (Form::fieldLookup(dict, "Ff", &obj1)->isInt()) {
984     int flags = obj1.getInt();
985     if (flags & 0x1000) // 13 -> Multiline
986       multiline = true;
987     if (flags & 0x2000) // 14 -> Password
988       password = true;
989     if (flags & 0x100000) // 21 -> FileSelect
990       fileSelect = true;
991     if (flags & 0x400000)// 23 -> DoNotSpellCheck
992       doNotSpellCheck = true;
993     if (flags & 0x800000) // 24 -> DoNotScroll
994       doNotScroll = true;
995     if (flags & 0x1000000) // 25 -> Comb
996       comb = true;
997     if (flags & 0x2000000)// 26 -> RichText
998       richText = true;
999   }
1000   obj1.free();
1001 
1002   if (Form::fieldLookup(dict, "MaxLen", &obj1)->isInt()) {
1003     maxLen = obj1.getInt();
1004   }
1005   obj1.free();
1006 
1007   if (Form::fieldLookup(dict, "V", &obj1)->isString()) {
1008     if (obj1.getString()->hasUnicodeMarker()) {
1009       if (obj1.getString()->getLength() > 2)
1010         content = obj1.getString()->copy();
1011     } else if (obj1.getString()->getLength() > 0) {
1012       //non-unicode string -- assume pdfDocEncoding and try to convert to UTF16BE
1013       int tmp_length;
1014       char* tmp_str = pdfDocEncodingToUTF16(obj1.getString(), &tmp_length);
1015       content = new GooString(tmp_str, tmp_length);
1016       delete [] tmp_str;
1017     }
1018   }
1019   obj1.free();
1020 }
1021 
1022 #ifdef DEBUG_FORMS
print(int indent)1023 void FormFieldText::print(int indent)
1024 {
1025   printf ("%*s- (%d %d): [text] terminal: %s children: %d\n", indent, "", ref.num, ref.gen,
1026           terminal ? "Yes" : "No", numChildren);
1027 }
1028 #endif
1029 
getContentCopy()1030 GooString* FormFieldText::getContentCopy ()
1031 {
1032   if (!content) return NULL;
1033   return new GooString(content);
1034 }
1035 
setContentCopy(GooString * new_content)1036 void FormFieldText::setContentCopy (GooString* new_content)
1037 {
1038   delete content;
1039   content = NULL;
1040 
1041   if (new_content) {
1042     content = new_content->copy();
1043 
1044     //append the unicode marker <FE FF> if needed
1045     if (!content->hasUnicodeMarker()) {
1046       content->insert(0, 0xff);
1047       content->insert(0, 0xfe);
1048     }
1049   }
1050 
1051   Object obj1;
1052   obj1.initString(content ? content->copy() : new GooString(""));
1053   obj.getDict()->set("V", &obj1);
1054   xref->setModifiedObject(&obj, ref);
1055   updateChildrenAppearance();
1056 }
1057 
~FormFieldText()1058 FormFieldText::~FormFieldText()
1059 {
1060   delete content;
1061 }
1062 
1063 
1064 //------------------------------------------------------------------------
1065 // FormFieldChoice
1066 //------------------------------------------------------------------------
FormFieldChoice(PDFDoc * docA,Object * aobj,const Ref & ref,FormField * parent,std::set<int> * usedParents)1067 FormFieldChoice::FormFieldChoice(PDFDoc *docA, Object *aobj, const Ref& ref, FormField *parent, std::set<int> *usedParents)
1068   : FormField(docA, aobj, ref, parent, usedParents, formChoice)
1069 {
1070   numChoices = 0;
1071   choices = NULL;
1072   editedChoice = NULL;
1073   topIdx = 0;
1074 
1075   Dict* dict = obj.getDict();
1076   Object obj1;
1077 
1078   combo = edit = multiselect = doNotSpellCheck = doCommitOnSelChange = false;
1079 
1080   if (Form::fieldLookup(dict, "Ff", &obj1)->isInt()) {
1081     int flags = obj1.getInt();
1082     if (flags & 0x20000) // 18 -> Combo
1083       combo = true;
1084     if (flags & 0x40000) // 19 -> Edit
1085       edit = true;
1086     if (flags & 0x200000) // 22 -> MultiSelect
1087       multiselect = true;
1088     if (flags & 0x400000) // 23 -> DoNotSpellCheck
1089       doNotSpellCheck = true;
1090     if (flags & 0x4000000) // 27 -> CommitOnSelChange
1091       doCommitOnSelChange = true;
1092   }
1093   obj1.free();
1094 
1095   if (dict->lookup("TI", &obj1)->isInt())
1096     topIdx = obj1.getInt();
1097   obj1.free();
1098 
1099   if (dict->lookup("Opt", &obj1)->isArray()) {
1100     Object obj2;
1101 
1102     numChoices = obj1.arrayGetLength();
1103     choices = new ChoiceOpt[numChoices];
1104     memset(choices, 0, sizeof(ChoiceOpt) * numChoices);
1105 
1106     for (int i = 0; i < numChoices; i++) {
1107       if (obj1.arrayGet(i, &obj2)->isString()) {
1108         choices[i].optionName = obj2.getString()->copy();
1109       } else if (obj2.isArray()) { // [Export_value, Displayed_text]
1110         Object obj3;
1111 
1112         if (obj2.arrayGetLength() < 2) {
1113           error(errSyntaxError, -1, "FormWidgetChoice:: invalid Opt entry -- array's length < 2\n");
1114           continue;
1115         }
1116         if (obj2.arrayGet(0, &obj3)->isString())
1117           choices[i].exportVal = obj3.getString()->copy();
1118         else
1119           error(errSyntaxError, -1, "FormWidgetChoice:: invalid Opt entry -- exported value not a string\n");
1120         obj3.free();
1121 
1122         if (obj2.arrayGet(1, &obj3)->isString())
1123           choices[i].optionName = obj3.getString()->copy();
1124         else
1125           error(errSyntaxError, -1, "FormWidgetChoice:: invalid Opt entry -- choice name not a string\n");
1126         obj3.free();
1127       } else {
1128         error(errSyntaxError, -1, "FormWidgetChoice:: invalid {0:d} Opt entry\n", i);
1129       }
1130       obj2.free();
1131     }
1132   } else {
1133     //empty choice
1134   }
1135   obj1.free();
1136 
1137   // Find selected items
1138   // Note: PDF specs say that /V has precedence over /I, but acroread seems to
1139   // do the opposite. We do the same.
1140   if (Form::fieldLookup(dict, "I", &obj1)->isArray()) {
1141     for (int i = 0; i < obj1.arrayGetLength(); i++) {
1142       Object obj2;
1143       if (obj1.arrayGet(i, &obj2)->isInt() && obj2.getInt() >= 0 && obj2.getInt() < numChoices) {
1144         choices[obj2.getInt()].selected = true;
1145       }
1146       obj2.free();
1147     }
1148   } else {
1149     obj1.free();
1150     // Note: According to PDF specs, /V should *never* contain the exportVal.
1151     // However, if /Opt is an array of (exportVal,optionName) pairs, acroread
1152     // seems to expect the exportVal instead of the optionName and so we do too.
1153     if (Form::fieldLookup(dict, "V", &obj1)->isString()) {
1154       GBool optionFound = gFalse;
1155 
1156       for (int i = 0; i < numChoices; i++) {
1157         if (choices[i].exportVal) {
1158           if (choices[i].exportVal->cmp(obj1.getString()) == 0) {
1159             optionFound = gTrue;
1160           }
1161         } else if (choices[i].optionName) {
1162           if (choices[i].optionName->cmp(obj1.getString()) == 0) {
1163             optionFound = gTrue;
1164           }
1165         }
1166 
1167         if (optionFound) {
1168           choices[i].selected = true;
1169           break; // We've determined that this option is selected. No need to keep on scanning
1170         }
1171       }
1172 
1173       // Set custom value if /V doesn't refer to any predefined option and the field is user-editable
1174       if (!optionFound && edit) {
1175         editedChoice = obj1.getString()->copy();
1176       }
1177     } else if (obj1.isArray()) {
1178       for (int i = 0; i < numChoices; i++) {
1179         for (int j = 0; j < obj1.arrayGetLength(); j++) {
1180           Object obj2;
1181           obj1.arrayGet(j, &obj2);
1182           GBool matches = gFalse;
1183 
1184           if (choices[i].exportVal) {
1185             if (choices[i].exportVal->cmp(obj2.getString()) == 0) {
1186               matches = gTrue;
1187             }
1188           } else if (choices[i].optionName) {
1189             if (choices[i].optionName->cmp(obj2.getString()) == 0) {
1190               matches = gTrue;
1191             }
1192           }
1193 
1194           obj2.free();
1195 
1196           if (matches) {
1197             choices[i].selected = true;
1198             break; // We've determined that this option is selected. No need to keep on scanning
1199           }
1200         }
1201       }
1202     }
1203   }
1204   obj1.free();
1205 }
1206 
~FormFieldChoice()1207 FormFieldChoice::~FormFieldChoice()
1208 {
1209   for (int i = 0; i < numChoices; i++) {
1210     delete choices[i].exportVal;
1211     delete choices[i].optionName;
1212   }
1213   delete [] choices;
1214   delete editedChoice;
1215 }
1216 
1217 #ifdef DEBUG_FORMS
print(int indent)1218 void FormFieldChoice::print(int indent)
1219 {
1220   printf ("%*s- (%d %d): [choice] terminal: %s children: %d\n", indent, "", ref.num, ref.gen,
1221           terminal ? "Yes" : "No", numChildren);
1222 }
1223 #endif
1224 
updateSelection()1225 void FormFieldChoice::updateSelection() {
1226   Object objV, objI, obj1;
1227   objI.initNull();
1228 
1229   if (edit && editedChoice) {
1230     // This is an editable combo-box with user-entered text
1231     objV.initString(editedChoice->copy());
1232   } else {
1233     const int numSelected = getNumSelected();
1234 
1235     // Create /I array only if multiple selection is allowed (as per PDF spec)
1236     if (multiselect) {
1237       objI.initArray(xref);
1238     }
1239 
1240     if (numSelected == 0) {
1241       // No options are selected
1242       objV.initString(new GooString(""));
1243     } else if (numSelected == 1) {
1244       // Only one option is selected
1245       for (int i = 0; i < numChoices; i++) {
1246         if (choices[i].selected) {
1247           if (multiselect) {
1248             objI.arrayAdd(obj1.initInt(i));
1249           }
1250 
1251           if (choices[i].exportVal) {
1252             objV.initString(choices[i].exportVal->copy());
1253           } else if (choices[i].optionName) {
1254             objV.initString(choices[i].optionName->copy());
1255           }
1256 
1257           break; // We've just written the selected option. No need to keep on scanning
1258         }
1259       }
1260     } else {
1261       // More than one option is selected
1262       objV.initArray(xref);
1263       for (int i = 0; i < numChoices; i++) {
1264         if (choices[i].selected) {
1265           if (multiselect) {
1266             objI.arrayAdd(obj1.initInt(i));
1267           }
1268 
1269           if (choices[i].exportVal) {
1270             objV.arrayAdd(obj1.initString(choices[i].exportVal->copy()));
1271           } else if (choices[i].optionName) {
1272             objV.arrayAdd(obj1.initString(choices[i].optionName->copy()));
1273           }
1274         }
1275       }
1276     }
1277   }
1278 
1279   obj.getDict()->set("V", &objV);
1280   obj.getDict()->set("I", &objI);
1281   xref->setModifiedObject(&obj, ref);
1282   updateChildrenAppearance();
1283 }
1284 
unselectAll()1285 void FormFieldChoice::unselectAll ()
1286 {
1287   for (int i = 0; i < numChoices; i++) {
1288     choices[i].selected = false;
1289   }
1290 }
1291 
deselectAll()1292 void FormFieldChoice::deselectAll () {
1293   delete editedChoice;
1294   editedChoice = NULL;
1295 
1296   unselectAll();
1297   updateSelection();
1298 }
1299 
toggle(int i)1300 void FormFieldChoice::toggle (int i)
1301 {
1302   delete editedChoice;
1303   editedChoice = NULL;
1304 
1305   choices[i].selected = !choices[i].selected;
1306   updateSelection();
1307 }
1308 
select(int i)1309 void FormFieldChoice::select (int i)
1310 {
1311   delete editedChoice;
1312   editedChoice = NULL;
1313 
1314   if (!multiselect)
1315     unselectAll();
1316 
1317   choices[i].selected = true;
1318   updateSelection();
1319 }
1320 
setEditChoice(GooString * new_content)1321 void FormFieldChoice::setEditChoice (GooString* new_content)
1322 {
1323   delete editedChoice;
1324   editedChoice = NULL;
1325 
1326   unselectAll();
1327 
1328   if (new_content) {
1329     editedChoice = new_content->copy();
1330 
1331     //append the unicode marker <FE FF> if needed
1332     if (!editedChoice->hasUnicodeMarker()) {
1333       editedChoice->insert(0, 0xff);
1334       editedChoice->insert(0, 0xfe);
1335     }
1336   }
1337   updateSelection();
1338 }
1339 
getEditChoice()1340 GooString* FormFieldChoice::getEditChoice ()
1341 {
1342   return editedChoice;
1343 }
1344 
getNumSelected()1345 int FormFieldChoice::getNumSelected ()
1346 {
1347   int cnt = 0;
1348   for(int i=0; i<numChoices; i++) {
1349     if (choices[i].selected)
1350       cnt++;
1351   }
1352   return cnt;
1353 }
1354 
getSelectedChoice()1355 GooString *FormFieldChoice::getSelectedChoice() {
1356   if (edit && editedChoice)
1357     return editedChoice;
1358 
1359   for (int i = 0; i < numChoices; i++) {
1360     if (choices[i].optionName && choices[i].selected)
1361       return choices[i].optionName;
1362   }
1363 
1364   return NULL;
1365 }
1366 
1367 //------------------------------------------------------------------------
1368 // FormFieldSignature
1369 //------------------------------------------------------------------------
FormFieldSignature(PDFDoc * docA,Object * dict,const Ref & ref,FormField * parent,std::set<int> * usedParents)1370 FormFieldSignature::FormFieldSignature(PDFDoc *docA, Object *dict, const Ref& ref, FormField *parent, std::set<int> *usedParents)
1371   : FormField(docA, dict, ref, parent, usedParents, formSignature)
1372 {
1373 }
1374 
~FormFieldSignature()1375 FormFieldSignature::~FormFieldSignature()
1376 {
1377 
1378 }
1379 
1380 #ifdef DEBUG_FORMS
print(int indent)1381 void FormFieldSignature::print(int indent)
1382 {
1383   printf ("%*s- (%d %d): [signature] terminal: %s children: %d\n", indent, "", ref.num, ref.gen,
1384           terminal ? "Yes" : "No", numChildren);
1385 }
1386 #endif
1387 
1388 //------------------------------------------------------------------------
1389 // Form
1390 //------------------------------------------------------------------------
1391 
Form(PDFDoc * docA,Object * acroFormA)1392 Form::Form(PDFDoc *docA, Object* acroFormA)
1393 {
1394   Object obj1;
1395 
1396   doc = docA;
1397   xref = doc->getXRef();
1398   acroForm = acroFormA;
1399 
1400   size = 0;
1401   numFields = 0;
1402   rootFields = NULL;
1403   quadding = quaddingLeftJustified;
1404   defaultAppearance = NULL;
1405   defaultResources = NULL;
1406 
1407   acroForm->dictLookup("NeedAppearances", &obj1);
1408   needAppearances = (obj1.isBool() && obj1.getBool());
1409   obj1.free();
1410 
1411   if (acroForm->dictLookup("DA", &obj1)->isString())
1412     defaultAppearance = obj1.getString()->copy();
1413   obj1.free();
1414 
1415   if (acroForm->dictLookup("Q", &obj1)->isInt())
1416     quadding = static_cast<VariableTextQuadding>(obj1.getInt());
1417   obj1.free();
1418 
1419   acroForm->dictLookup("DR", &resDict);
1420   if (resDict.isDict()) {
1421     // At a minimum, this dictionary shall contain a Font entry
1422     if (resDict.dictLookup("Font", &obj1)->isDict())
1423       defaultResources = new GfxResources(xref, resDict.getDict(), NULL);
1424     obj1.free();
1425   }
1426   if (!defaultResources) {
1427     resDict.free();
1428     resDict.initNull();
1429   }
1430 
1431   acroForm->dictLookup("Fields", &obj1);
1432   if (obj1.isArray()) {
1433     Array *array = obj1.getArray();
1434     Object obj2;
1435 
1436     for(int i=0; i<array->getLength(); i++) {
1437       Object oref;
1438       array->get(i, &obj2);
1439       array->getNF(i, &oref);
1440       if (!oref.isRef()) {
1441         error(errSyntaxWarning, -1, "Direct object in rootFields");
1442 	obj2.free();
1443 	oref.free();
1444         continue;
1445       }
1446 
1447       if (!obj2.isDict()) {
1448         error(errSyntaxWarning, -1, "Reference in Fields array to an invalid or non existant object");
1449 	obj2.free();
1450 	oref.free();
1451 	continue;
1452       }
1453 
1454       if (numFields >= size) {
1455         size += 16;
1456         rootFields = (FormField**)greallocn(rootFields,size,sizeof(FormField*));
1457       }
1458 
1459       std::set<int> usedParents;
1460       rootFields[numFields++] = createFieldFromDict (&obj2, doc, oref.getRef(), NULL, &usedParents);
1461 
1462       obj2.free();
1463       oref.free();
1464     }
1465   } else {
1466     error(errSyntaxError, -1, "Can't get Fields array\n");
1467   }
1468   obj1.free ();
1469 
1470 #ifdef DEBUG_FORMS
1471   for (int i = 0; i < numFields; i++)
1472     rootFields[i]->printTree();
1473 #endif
1474 }
1475 
~Form()1476 Form::~Form() {
1477   int i;
1478   for(i = 0; i< numFields; ++i)
1479     delete rootFields[i];
1480   gfree (rootFields);
1481   delete defaultAppearance;
1482   delete defaultResources;
1483   resDict.free();
1484 }
1485 
1486 // Look up an inheritable field dictionary entry.
fieldLookup(Dict * field,const char * key,Object * obj,std::set<int> * usedParents)1487 static Object *fieldLookup(Dict *field, const char *key, Object *obj, std::set<int> *usedParents) {
1488   Dict *dict;
1489   Object parent;
1490 
1491   dict = field;
1492   if (!dict->lookup(key, obj)->isNull()) {
1493     return obj;
1494   }
1495   obj->free();
1496   dict->lookupNF("Parent", &parent);
1497   if (parent.isRef()) {
1498     const Ref ref = parent.getRef();
1499     if (usedParents->find(ref.num) == usedParents->end()) {
1500       usedParents->insert(ref.num);
1501 
1502       Object obj2;
1503       parent.fetch(dict->getXRef(), &obj2);
1504       if (obj2.isDict()) {
1505         fieldLookup(obj2.getDict(), key, obj, usedParents);
1506       } else {
1507         obj->initNull();
1508       }
1509       obj2.free();
1510     }
1511   } else if (parent.isDict()) {
1512     fieldLookup(parent.getDict(), key, obj, usedParents);
1513   } else {
1514     obj->initNull();
1515   }
1516   parent.free();
1517   return obj;
1518 }
1519 
fieldLookup(Dict * field,const char * key,Object * obj)1520 Object *Form::fieldLookup(Dict *field, const char *key, Object *obj) {
1521   std::set<int> usedParents;
1522   return ::fieldLookup(field, key, obj, &usedParents);
1523 }
1524 
createFieldFromDict(Object * obj,PDFDoc * docA,const Ref & pref,FormField * parent,std::set<int> * usedParents)1525 FormField *Form::createFieldFromDict (Object* obj, PDFDoc *docA, const Ref& pref, FormField *parent, std::set<int> *usedParents)
1526 {
1527     Object obj2;
1528     FormField *field;
1529 
1530     if (Form::fieldLookup(obj->getDict (), "FT", &obj2)->isName("Btn")) {
1531       field = new FormFieldButton(docA, obj, pref, parent, usedParents);
1532     } else if (obj2.isName("Tx")) {
1533       field = new FormFieldText(docA, obj, pref, parent, usedParents);
1534     } else if (obj2.isName("Ch")) {
1535       field = new FormFieldChoice(docA, obj, pref, parent, usedParents);
1536     } else if (obj2.isName("Sig")) {
1537       field = new FormFieldSignature(docA, obj, pref, parent, usedParents);
1538     } else { //we don't have an FT entry => non-terminal field
1539       field = new FormField(docA, obj, pref, parent, usedParents);
1540     }
1541     obj2.free();
1542 
1543     return field;
1544 }
1545 
postWidgetsLoad()1546 void Form::postWidgetsLoad()
1547 {
1548   // We create the widget annotations associated to
1549   // every form widget here, because the AnnotWidget constructor
1550   // needs the form object that gets from the catalog. When constructing
1551   // a FormWidget the Catalog is still creating the form object
1552   for (int i = 0; i < numFields; i++) {
1553     rootFields[i]->fillChildrenSiblingsID();
1554     rootFields[i]->createWidgetAnnotations();
1555   }
1556 }
1557 
findWidgetByRef(Ref aref)1558 FormWidget* Form::findWidgetByRef (Ref aref)
1559 {
1560   for(int i=0; i<numFields; i++) {
1561     FormWidget *result = rootFields[i]->findWidgetByRef(aref);
1562     if(result) return result;
1563   }
1564   return NULL;
1565 }
1566 
1567 //------------------------------------------------------------------------
1568 // FormPageWidgets
1569 //------------------------------------------------------------------------
1570 
FormPageWidgets(Annots * annots,unsigned int page,Form * form)1571 FormPageWidgets::FormPageWidgets (Annots *annots, unsigned int page, Form *form)
1572 {
1573   numWidgets = 0;
1574   widgets = NULL;
1575 
1576   if (annots && annots->getNumAnnots() > 0 && form) {
1577     size = annots->getNumAnnots();
1578     widgets = (FormWidget**)greallocn(widgets, size, sizeof(FormWidget*));
1579 
1580     /* For each entry in the page 'Annots' dict, try to find
1581        a matching form field */
1582     for (int i = 0; i < size; ++i) {
1583       Annot *annot = annots->getAnnot(i);
1584 
1585       if (annot->getType() != Annot::typeWidget)
1586         continue;
1587 
1588       if (!annot->getHasRef()) {
1589         /* Since all entry in a form field's kid dict needs to be
1590            indirect references, if this annot isn't indirect, it isn't
1591            related to a form field */
1592         continue;
1593       }
1594 
1595       Ref r = annot->getRef();
1596 
1597       /* Try to find a form field which either has this Annot in its Kids entry
1598           or  is merged with this Annot */
1599       FormWidget* tmp = form->findWidgetByRef(r);
1600       if (tmp) {
1601         // We've found a corresponding form field, link it
1602         tmp->setID(FormWidget::encodeID(page, numWidgets));
1603         widgets[numWidgets++] = tmp;
1604       }
1605     }
1606   }
1607 }
1608 
~FormPageWidgets()1609 FormPageWidgets::~FormPageWidgets()
1610 {
1611   gfree (widgets);
1612 }
1613