//========================================================================
//
// Form.cc
//
// This file is licensed under the GPLv2 or later
//
// Copyright 2006-2008 Julien Rebetez <julienr@svn.gnome.org>
// Copyright 2007-2012, 2015-2019 Albert Astals Cid <aacid@kde.org>
// Copyright 2007-2008, 2011 Carlos Garcia Campos <carlosgc@gnome.org>
// Copyright 2007, 2013, 2016 Adrian Johnson <ajohnson@redneon.com>
// Copyright 2007 Iñigo Martínez <inigomartinez@gmail.com>
// Copyright 2008, 2011 Pino Toscano <pino@kde.org>
// Copyright 2008 Michael Vrable <mvrable@cs.ucsd.edu>
// Copyright 2009 Matthias Drochner <M.Drochner@fz-juelich.de>
// Copyright 2009 KDAB via Guillermo Amaral <gamaral@amaral.com.mx>
// Copyright 2010, 2012 Mark Riedesel <mark@klowner.com>
// Copyright 2012 Fabio D'Urso <fabiodurso@hotmail.it>
// Copyright 2015 André Guerreiro <aguerreiro1985@gmail.com>
// Copyright 2015 André Esser <bepandre@hotmail.com>
// Copyright 2017 Hans-Ulrich Jüttner <huj@froreich-bioscientia.de>
// Copyright 2017 Bernd Kuhls <berndkuhls@hotmail.com>
// Copyright 2018 Andre Heinecke <aheinecke@intevation.de>
// Copyright 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>. Work sponsored by the LiMux project of the city of Munich
// Copyright 2018 Chinmoy Ranjan Pradhan <chinmoyrp65@protonmail.com>
// Copyright 2018 Adam Reichold <adam.reichold@t-online.de>
// Copyright 2018 Nelson Benítez León <nbenitezl@gmail.com>
//
//========================================================================

#include <config.h>

#include <set>
#include <limits>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "goo/gmem.h"
#include "goo/GooString.h"
#include "Error.h"
#include "Object.h"
#include "Array.h"
#include "Dict.h"
#include "Gfx.h"
#include "Form.h"
#include "PDFDoc.h"
#include "DateInfo.h"
#ifdef ENABLE_NSS3
#include "SignatureHandler.h"
#endif
#include "SignatureInfo.h"
#include "XRef.h"
#include "PDFDocEncoding.h"
#include "Annot.h"
#include "Link.h"
#include "Lexer.h"

//return a newly allocated char* containing an UTF16BE string of size length
char* pdfDocEncodingToUTF16 (const GooString* orig, int* length)
{
  //double size, a unicode char takes 2 char, add 2 for the unicode marker
  *length = 2+2*orig->getLength();
  char *result = new char[(*length)];
  const char *cstring = orig->c_str();
  //unicode marker
  result[0] = (char)0xfe;
  result[1] = (char)0xff;
  //convert to utf16
  for(int i=2,j=0; i<(*length); i+=2,j++) {
    Unicode u = pdfDocEncoding[(unsigned int)((unsigned char)cstring[j])]&0xffff;
    result[i] = (u >> 8) & 0xff;
    result[i+1] = u & 0xff;
  }
  return result;
}

static GooString *convertToUtf16(GooString *pdfDocEncodingString)
{
  int tmp_length;
  char* tmp_str = pdfDocEncodingToUTF16(pdfDocEncodingString, &tmp_length);
  delete pdfDocEncodingString;
  pdfDocEncodingString = new GooString(tmp_str, tmp_length);
  delete [] tmp_str;
  return pdfDocEncodingString;
}


FormWidget::FormWidget(PDFDoc *docA, Object *aobj, unsigned num, Ref aref, FormField *fieldA)
{
  ref = aref;
  ID = 0;
  childNum = num;
  doc = docA;
  xref = doc->getXRef();
  obj = aobj->copy();
  type = formUndef;
  field = fieldA;
  widget = nullptr;
}

FormWidget::~FormWidget()
{
  if (widget)
    widget->decRefCnt();
}

void FormWidget::print(int indent) {
  printf ("%*s+ (%d %d): [widget]\n", indent, "", ref.num, ref.gen);
}

void FormWidget::createWidgetAnnotation() {
  if (widget)
    return;

  Object obj1(ref);
  widget = new AnnotWidget(doc, &obj, &obj1, field);
}

bool FormWidget::inRect(double x, double y) const {
  return widget ? widget->inRect(x, y) : false;
}

void FormWidget::getRect(double *x1, double *y1, double *x2, double *y2) const {
  if (widget)
    widget->getRect(x1, y1, x2, y2);
}

bool FormWidget::isReadOnly() const
{
  return field->isReadOnly();
}

void FormWidget::setReadOnly(bool value)
{
  field->setReadOnly(value);
}

int FormWidget::encodeID (unsigned pageNum, unsigned fieldNum)
{
  return (pageNum << 4*sizeof(unsigned)) + fieldNum;
}

void FormWidget::decodeID (unsigned id, unsigned* pageNum, unsigned* fieldNum)
{
  *pageNum = id >> 4*sizeof(unsigned);
  *fieldNum = (id << 4*sizeof(unsigned)) >> 4*sizeof(unsigned);
}

const GooString *FormWidget::getPartialName() const {
  return field->getPartialName();
}

void FormWidget::setPartialName(const GooString &name)
{
  field->setPartialName(name);
}

const GooString *FormWidget::getAlternateUiName() const {
  return field->getAlternateUiName();
}

const GooString *FormWidget::getMappingName() const {
  return field->getMappingName();
}

GooString *FormWidget::getFullyQualifiedName() {
  return field->getFullyQualifiedName();
}

LinkAction *FormWidget::getActivationAction() {
  return widget ? widget->getAction() : nullptr;
}

LinkAction *FormWidget::getAdditionalAction(Annot::FormAdditionalActionsType type) {
  return widget ? widget->getFormAdditionalAction(type) : nullptr;
}

FormWidgetButton::FormWidgetButton (PDFDoc *docA, Object *aobj, unsigned num, Ref ref, FormField *p) :
	FormWidget(docA, aobj, num, ref, p)
{
  type = formButton;
  onStr = nullptr;

  // Find the name of the ON state in the AP dictionary
  // The reference say the Off state, if it exists, _must_ be stored in the AP dict under the name /Off
  // The "on" state may be stored under any other name
  Object obj1 = obj.dictLookup("AP");
  if (obj1.isDict()) {
    Object obj2 = obj1.dictLookup("N");
    if (obj2.isDict()) {
      for (int i = 0; i < obj2.dictGetLength(); i++) {
        const char *key = obj2.dictGetKey(i);
        if (strcmp (key, "Off") != 0) {
          onStr = new GooString (key);
          break;
        }
      }
    }
  }
}

const char *FormWidgetButton::getOnStr() const {
  if (onStr)
    return onStr->c_str();

  // 12.7.4.2.3 Check Boxes
  //  Yes should be used as the name for the on state
  return parent()->getButtonType() == formButtonCheck ? "Yes" : nullptr;
}

FormWidgetButton::~FormWidgetButton ()
{
  delete onStr;
}

FormButtonType FormWidgetButton::getButtonType () const
{
  return parent()->getButtonType ();
}

void FormWidgetButton::setAppearanceState(const char *state) {
  if (!widget)
    return;
  widget->setAppearanceState(state);
}

void FormWidgetButton::updateWidgetAppearance()
{
  // The appearance stream must NOT be regenerated for this widget type
}

void FormWidgetButton::setState (bool astate)
{
  //pushButtons don't have state
  if (parent()->getButtonType() == formButtonPush)
    return;

  // Silently return if can't set ON state
  if (astate && !getOnStr())
    return;

  parent()->setState(astate ? getOnStr() : (char *)"Off");
  // Parent will call setAppearanceState()
}

bool FormWidgetButton::getState () const
{
  return getOnStr() ? parent()->getState( getOnStr() ) : false;
}

FormFieldButton *FormWidgetButton::parent() const
{
  return static_cast<FormFieldButton*>(field);
}


FormWidgetText::FormWidgetText (PDFDoc *docA, Object *aobj, unsigned num, Ref ref, FormField *p) :
	FormWidget(docA, aobj, num, ref, p)
{
  type = formText;
}

const GooString* FormWidgetText::getContent () const
{
  return parent()->getContent();
}

void FormWidgetText::updateWidgetAppearance()
{
  if (widget)
    widget->updateAppearanceStream();
}

bool FormWidgetText::isMultiline () const 
{ 
  return parent()->isMultiline();
}

bool FormWidgetText::isPassword () const 
{ 
  return parent()->isPassword();
}

bool FormWidgetText::isFileSelect () const 
{ 
  return parent()->isFileSelect();
}

bool FormWidgetText::noSpellCheck () const 
{ 
  return parent()->noSpellCheck();
}

bool FormWidgetText::noScroll () const 
{ 
  return parent()->noScroll();
}

bool FormWidgetText::isComb () const 
{ 
  return parent()->isComb();
}

bool FormWidgetText::isRichText () const 
{ 
  return parent()->isRichText();
}

int FormWidgetText::getMaxLen () const
{
  return parent()->getMaxLen ();
}

double FormWidgetText::getTextFontSize()
{
  return parent()->getTextFontSize();
}

void FormWidgetText::setTextFontSize(int fontSize)
{
  parent()->setTextFontSize(fontSize);
}

void FormWidgetText::setContent(const GooString* new_content)
{
  parent()->setContentCopy(new_content);
}

FormFieldText *FormWidgetText::parent() const
{
  return static_cast<FormFieldText*>(field);
}

FormWidgetChoice::FormWidgetChoice(PDFDoc *docA, Object *aobj, unsigned num, Ref ref, FormField *p) :
	FormWidget(docA, aobj, num, ref, p)
{
  type = formChoice;
}

FormWidgetChoice::~FormWidgetChoice()
{
}

bool FormWidgetChoice::_checkRange (int i) const
{
  if (i < 0 || i >= parent()->getNumChoices()) {
    error(errInternal, -1, "FormWidgetChoice::_checkRange i out of range : {0:d}", i);
    return false;
  } 
  return true;
}

void FormWidgetChoice::select (int i)
{
  if (!_checkRange(i)) return;
  parent()->select(i);
}

void FormWidgetChoice::toggle (int i)
{
  if (!_checkRange(i)) return;
  parent()->toggle(i);
}

void FormWidgetChoice::deselectAll ()
{
  parent()->deselectAll();
}

const GooString* FormWidgetChoice::getEditChoice () const
{
  if (!hasEdit()) {
    error(errInternal, -1, "FormFieldChoice::getEditChoice called on a non-editable choice\n");
    return nullptr;
  }
  return parent()->getEditChoice();
}

void FormWidgetChoice::updateWidgetAppearance()
{
  if (widget)
    widget->updateAppearanceStream();
}

bool FormWidgetChoice::isSelected (int i) const
{
  if (!_checkRange(i)) return false;
  return parent()->isSelected(i);
}

void FormWidgetChoice::setEditChoice (const GooString* new_content)
{
  if (!hasEdit()) {
    error(errInternal, -1, "FormFieldChoice::setEditChoice : trying to edit an non-editable choice\n");
    return;
  }

  parent()->setEditChoice(new_content);
}

int FormWidgetChoice::getNumChoices() const
{ 
  return parent()->getNumChoices();
}

const GooString* FormWidgetChoice::getChoice(int i) const
{ 
  return parent()->getChoice(i);
}

bool FormWidgetChoice::isCombo () const 
{ 
  return parent()->isCombo();
}

bool FormWidgetChoice::hasEdit () const 
{ 
  return parent()->hasEdit();
}

bool FormWidgetChoice::isMultiSelect () const 
{ 
  return parent()->isMultiSelect();
}

bool FormWidgetChoice::noSpellCheck () const 
{ 
  return parent()->noSpellCheck();
}

bool FormWidgetChoice::commitOnSelChange () const 
{ 
  return parent()->commitOnSelChange();
}

bool FormWidgetChoice::isListBox () const
{
  return parent()->isListBox();
}

FormFieldChoice *FormWidgetChoice::parent() const
{
  return static_cast<FormFieldChoice*>(field);
}

FormWidgetSignature::FormWidgetSignature(PDFDoc *docA, Object *aobj, unsigned num, Ref ref, FormField *p) :
	FormWidget(docA, aobj, num, ref, p)
{
  type = formSignature;
}

const GooString *FormWidgetSignature::getSignature() const
{
    return static_cast<FormFieldSignature*>(field)->getSignature();
}

SignatureInfo *FormWidgetSignature::validateSignature(bool doVerifyCert, bool forceRevalidation, time_t validationTime)
{
  return static_cast<FormFieldSignature*>(field)->validateSignature(doVerifyCert, forceRevalidation, validationTime);
}

std::vector<Goffset> FormWidgetSignature::getSignedRangeBounds()
{
  Object* obj = static_cast<FormFieldSignature*>(field)->getByteRange();
  std::vector<Goffset> range_vec;
  if (obj->isArray())
  {
    if (obj->arrayGetLength() == 4)
    {
      for (int i = 0; i < 2; ++i)
      {
        Object offsetObj(obj->arrayGet(2*i));
        Object lenObj(obj->arrayGet(2*i+1));
        if (offsetObj.isIntOrInt64() && lenObj.isIntOrInt64())
        {
          Goffset offset = offsetObj.getIntOrInt64();
          Goffset len = lenObj.getIntOrInt64();
          range_vec.push_back(offset);
          range_vec.push_back(offset+len);
        }
      }
    }
  }
  return range_vec;
}

GooString* FormWidgetSignature::getCheckedSignature(Goffset *checkedFileSize)
{
  Goffset start = 0;
  Goffset end = 0;
  const std::vector<Goffset> ranges = getSignedRangeBounds();
  if (ranges.size() == 4)
  {
    start = ranges[1];
    end = ranges[2];
  }
  if (end >= start+6)
  {
    BaseStream* stream = doc->getBaseStream();
    *checkedFileSize = stream->getLength();
    Goffset len = end-start;
    stream->setPos(end-1);
    int c2 = stream->lookChar();
    stream->setPos(start);
    int c1 = stream->getChar();
    // PDF signatures are first ASN1 DER, then hex encoded PKCS#7 structures,
    // possibly padded with 0 characters and enclosed in '<' and '>'.
    // The ASN1 DER encoding of a PKCS#7 structure must start with the tag 0x30
    // for SEQUENCE. The next byte must be 0x80 for ASN1 DER indefinite length
    // encoding or (0x80 + n) for ASN1 DER definite length encoding
    // where n is the number of subsequent "length bytes" which big-endian
    // encode the length of the content of the SEQUENCE following them.
    if (len <= std::numeric_limits<int>::max() && *checkedFileSize > end && c1 == '<' && c2 == '>')
    {
      GooString gstr;
      ++start;
      --end;
      len = end-start;
      Goffset pos = 0;
      do
      {
        c1 = stream->getChar();
        if (c1 == EOF)
          return nullptr;
        gstr.append(static_cast<char>(c1));
      } while (++pos < len);
      if (gstr.getChar(0) == '3' && gstr.getChar(1) == '0')
      {
        if (gstr.getChar(2) == '8' && gstr.getChar(3) == '0')
        {
          // ASN1 DER indefinite length encoding:
          // We only check that all characters up to the enclosing '>'
          // are hex characters and that there are two hex encoded 0 bytes
          // just before the enclosing '>' marking the end of the indefinite
          // length encoding.
          int paddingCount = 0;
          while (gstr.getChar(len-1) == '0' && gstr.getChar(len-2) == '0')
          {
            ++paddingCount;
            len -= 2;
          }
          if (paddingCount < 2 || len%2 == 1)
            len = 0;
        }
        else if (gstr.getChar(2) == '8')
        {
          // ASN1 DER definite length encoding:
          // We calculate the length of the following bytes from the length bytes and
          // check that after the length bytes and the following calculated number of
          // bytes all bytes up to the enclosing '>' character are hex encoded 0 bytes.
          int lenBytes = gstr.getChar(3) - '0';
          if (lenBytes > 0 && lenBytes <= 4)
          {
            int sigLen = 0;
            for (int i = 0; i < 2*lenBytes; ++i)
            {
              sigLen <<= 4;
              char c = gstr.getChar(i+4);
              if (isdigit(c))
                sigLen += c - '0';
              else if (isxdigit(c) && c >= 'a')
                sigLen += c - 'a' + 10;
              else if (isxdigit(c) && c >= 'A')
                sigLen += c - 'A' + 10;
              else
              {
                len = 0;
                break;
              }
            }
            if (sigLen > 0 && 2*(sigLen+lenBytes) <= len-4)
            {
              for (int i = 2*(sigLen+lenBytes)+4; i < len; ++i)
              {
                if (gstr.getChar(i) != '0')
                {
                  len = 0;
                  break;
                }
              }
            }
            else
              len = 0;
          }
        }
        for (int i = 0; i < len; ++i)
        {
          if (!isxdigit(gstr.getChar(i)))
            len = 0;
        }
        if (len > 0)
        {
          return new GooString(&gstr, 0, len);
        }
      }
    }
  }
  return nullptr;
}

void FormWidgetSignature::updateWidgetAppearance()
{
  // Unimplemented
}


//========================================================================
// FormField
//========================================================================

FormField::FormField(PDFDoc *docA, Object &&aobj, const Ref aref, FormField *parentA, std::set<int> *usedParents, FormFieldType ty)
{
  doc = docA;
  xref = doc->getXRef();
  obj = std::move(aobj);
  Dict* dict = obj.getDict();
  ref.num = ref.gen = 0;
  type = ty;
  parent = parentA;
  numChildren = 0;
  children = nullptr;
  terminal = false;
  widgets = nullptr;
  readOnly = false;
  defaultAppearance = nullptr;
  fullyQualifiedName = nullptr;
  quadding = quaddingLeftJustified;
  hasQuadding = false;

  ref = aref;

  //childs
  Object obj1 = dict->lookup("Kids");
  if (obj1.isArray()) {
    // Load children
    for (int i = 0 ; i < obj1.arrayGetLength(); i++) {
      const Object &childRef = obj1.arrayGetNF(i);
      if (!childRef.isRef()) {
        error (errSyntaxError, -1, "Invalid form field renference");
        continue;
      }
      Object childObj = obj1.arrayGet(i);
      if (!childObj.isDict()) {
        error (errSyntaxError, -1, "Form field child is not a dictionary");
        continue;
      }

      const Ref ref = childRef.getRef();
      if (usedParents->find(ref.num) == usedParents->end()) {
        // Field child: it could be a form field or a widget or composed dict
        Object obj2 = childObj.dictLookupNF("Parent").copy();
	Object obj3 = childObj.dictLookup("Parent");
        if (obj2.isRef() || obj3.isDict()) {
          // Child is a form field or composed dict
          // We create the field, if it's composed
          // it will create the widget as a child
          std::set<int> usedParentsAux = *usedParents;
          usedParentsAux.insert(ref.num);

          if (terminal) {
            error(errSyntaxWarning, -1, "Field can't have both Widget AND Field as kids\n");
            continue;
          }

          numChildren++;
          children = (FormField**)greallocn(children, numChildren, sizeof(FormField*));
          children[numChildren - 1] = Form::createFieldFromDict(std::move(childObj), doc, ref, this, &usedParentsAux);
        } else {
	  obj2 = childObj.dictLookup("Subtype");
	  if (obj2.isName("Widget")) {
	    // Child is a widget annotation
	    if (!terminal && numChildren > 0) {
	      error(errSyntaxWarning, -1, "Field can't have both Widget AND Field as kids\n");
	      continue;
	    }
	    _createWidget(&childObj, ref);
	  }
	}
      }
    }
  } else {
    // No children, if it's a composed dict, create the child widget
    obj1 = dict->lookup("Subtype");
    if (obj1.isName("Widget"))
      _createWidget(&obj, ref);
  }

  //flags
  obj1 = Form::fieldLookup(dict, "Ff");
  if (obj1.isInt()) {
    int flags = obj1.getInt();
    if (flags & 0x1) { // 1 -> ReadOnly
      readOnly = true;
    }
    if (flags & 0x2) { // 2 -> Required
      //TODO
    }
    if (flags & 0x4) { // 3 -> NoExport
      //TODO
    }
  }

  // Variable Text
  obj1 = Form::fieldLookup(dict, "DA");
  if (obj1.isString())
    defaultAppearance = obj1.getString()->copy();

  obj1 = Form::fieldLookup(dict, "Q");
  if (obj1.isInt()) {
    quadding = static_cast<VariableTextQuadding>(obj1.getInt());
    hasQuadding = true;
  }

  obj1 = dict->lookup("T");
  if (obj1.isString()) {
    partialName = obj1.getString()->copy();
  } else {
    partialName = nullptr;
  }

  obj1 = dict->lookup("TU");
  if (obj1.isString()) {
    alternateUiName = obj1.getString()->copy();
  } else {
    alternateUiName = nullptr;
  }

  obj1 = dict->lookup("TM");
  if(obj1.isString()) {
    mappingName = obj1.getString()->copy();
  } else {
    mappingName = nullptr;
  }
}

void FormField::setPartialName(const GooString &name)
{
  delete partialName;
  partialName = name.copy();

  obj.getDict()->set("T", Object(name.copy()));
  xref->setModifiedObject(&obj, ref);
}

FormField::~FormField()
{
  if (!terminal) {
    if(children) {
      for (int i=0; i<numChildren; i++)
        delete children[i];
      gfree(children);
    }
  } else {
    for (int i = 0; i < numChildren; ++i)
      delete widgets[i];
    gfree (widgets);
  }

  delete defaultAppearance;
  delete partialName;
  delete alternateUiName;
  delete mappingName;
  delete fullyQualifiedName;
}

void FormField::print(int indent)
{
  printf ("%*s- (%d %d): [container] terminal: %s children: %d\n", indent, "", ref.num, ref.gen,
          terminal ? "Yes" : "No", numChildren);
}

void FormField::printTree(int indent)
{
  print(indent);
  if (terminal) {
    for (int i = 0; i < numChildren; i++)
      widgets[i]->print(indent + 4);
  } else {
    for (int i = 0; i < numChildren; i++)
      children[i]->printTree(indent + 4);
  }
}

void FormField::fillChildrenSiblingsID()
{
  if (terminal)
    return;
  for (int i = 0; i < numChildren; i++) {
    children[i]->fillChildrenSiblingsID();
  }
}

void FormField::createWidgetAnnotations() {
  if (terminal) {
    for (int i = 0; i < numChildren; i++)
      widgets[i]->createWidgetAnnotation();
  } else {
    for (int i = 0; i < numChildren; i++)
      children[i]->createWidgetAnnotations();
  }
}

void FormField::_createWidget (Object *obj, Ref aref)
{
  terminal = true;
  numChildren++;
  widgets = (FormWidget**)greallocn(widgets, numChildren, sizeof(FormWidget*));
  //ID = index in "widgets" table
  switch (type) {
  case formButton:
    widgets[numChildren-1] = new FormWidgetButton(doc, obj, numChildren-1, aref, this);
    break;
  case formText:
    widgets[numChildren-1] = new FormWidgetText(doc, obj, numChildren-1, aref, this);
    break;
  case formChoice:
    widgets[numChildren-1] = new FormWidgetChoice(doc, obj, numChildren-1, aref, this);
    break;
  case formSignature:
    widgets[numChildren-1] = new FormWidgetSignature(doc, obj, numChildren-1, aref, this);
    break;
  default:
    error(errSyntaxWarning, -1, "SubType on non-terminal field, invalid document?");
    numChildren--;
  }
}

FormWidget* FormField::findWidgetByRef (Ref aref)
{
  if (terminal) {
    for(int i=0; i<numChildren; i++) {
      if (widgets[i]->getRef().num == aref.num 
          && widgets[i]->getRef().gen == aref.gen)
        return widgets[i];
    }
  } else {
    for(int i=0; i<numChildren; i++) {
      FormWidget* result = children[i]->findWidgetByRef(aref);
      if(result) return result;
    }
  }
  return nullptr;
}

GooString* FormField::getFullyQualifiedName() {
  Object obj1;
  Object parent;
  const GooString *parent_name;
  GooString *full_name;
  bool unicode_encoded = false;

  if (fullyQualifiedName)
    return fullyQualifiedName;

  full_name = new GooString();

  obj1 = obj.copy();
  while (parent = obj1.dictLookup("Parent"), parent.isDict()) {
    Object obj2 = parent.dictLookup("T");
    if (obj2.isString()) {
      parent_name = obj2.getString();

      if (unicode_encoded) {
        full_name->insert(0, "\0.", 2); // 2-byte unicode period
        if (parent_name->hasUnicodeMarker()) {
          full_name->insert(0, parent_name->c_str() + 2, parent_name->getLength() - 2); // Remove the unicode BOM
        } else {
          int tmp_length;
          char* tmp_str = pdfDocEncodingToUTF16(parent_name, &tmp_length);
          full_name->insert(0, tmp_str + 2, tmp_length - 2); // Remove the unicode BOM
          delete [] tmp_str;
        }
      } else {
        full_name->insert(0, '.'); // 1-byte ascii period
        if (parent_name->hasUnicodeMarker()) {          
          unicode_encoded = true;
          full_name = convertToUtf16(full_name);
          full_name->insert(0, parent_name->c_str() + 2, parent_name->getLength() - 2); // Remove the unicode BOM
        } else {
          full_name->insert(0, parent_name);
        }
      }
    }
    obj1 = parent.copy();
  }

  if (partialName) {
    if (unicode_encoded) {
      if (partialName->hasUnicodeMarker()) {
        full_name->append(partialName->c_str() + 2, partialName->getLength() - 2); // Remove the unicode BOM
      } else {
        int tmp_length;
        char* tmp_str = pdfDocEncodingToUTF16(partialName, &tmp_length);
        full_name->append(tmp_str + 2, tmp_length - 2); // Remove the unicode BOM
        delete [] tmp_str;
      }
    } else {
      if (partialName->hasUnicodeMarker()) {
          unicode_encoded = true;        
          full_name = convertToUtf16(full_name);
          full_name->append(partialName->c_str() + 2, partialName->getLength() - 2); // Remove the unicode BOM
      } else {
        full_name->append(partialName);
      }
    }
  } else {
    int len = full_name->getLength();
    // Remove the last period
    if (unicode_encoded) {
      if (len > 1) {
        full_name->del(len - 2, 2);
      }
    } else {
      if (len > 0) {
        full_name->del(len - 1, 1);
      }
    }
  }
  
  if (unicode_encoded) {
    full_name->prependUnicodeMarker();
  }

  fullyQualifiedName = full_name;
  return fullyQualifiedName;
}

void FormField::updateChildrenAppearance()
{
  // Recursively update each child's appearance
  if (terminal) {
    for (int i = 0; i < numChildren; i++)
      widgets[i]->updateWidgetAppearance();
  } else {
    for (int i = 0; i < numChildren; i++)
      children[i]->updateChildrenAppearance();
  }
}

void FormField::setReadOnly (bool value)
{
  if (value == readOnly) {
    return;
  }

  readOnly = value;

  Dict* dict = obj.getDict();

  const Object obj1 = Form::fieldLookup(dict, "Ff");
  int flags = 0;
  if (obj1.isInt()) {
    flags = obj1.getInt();
  }
  if (value) {
    flags |= 1;
  } else {
    flags &= ~1;
  }

  dict->set("Ff", Object(flags));
  xref->setModifiedObject(&obj, ref);
  updateChildrenAppearance();
}

//------------------------------------------------------------------------
// FormFieldButton
//------------------------------------------------------------------------
FormFieldButton::FormFieldButton(PDFDoc *docA, Object &&aobj, const Ref ref, FormField *parent, std::set<int> *usedParents)
  : FormField(docA, std::move(aobj), ref, parent, usedParents, formButton)
{
  Dict* dict = obj.getDict();
  active_child = -1;
  noAllOff = false;
  siblings = nullptr;
  numSiblings = 0;
  appearanceState.setToNull();

  btype = formButtonCheck;
  Object obj1 = Form::fieldLookup(dict, "Ff");
  if (obj1.isInt()) {
    int flags = obj1.getInt();
    
    if (flags & 0x10000) { // 17 -> push button
      btype = formButtonPush;
    } else if (flags & 0x8000) { // 16 -> radio button
      btype = formButtonRadio;
      if (flags & 0x4000) { // 15 -> noToggleToOff
        noAllOff = true;
      }
    } 
    if (flags & 0x1000000) { // 26 -> radiosInUnison
      error(errUnimplemented, -1, "FormFieldButton:: radiosInUnison flag unimplemented, please report a bug with a testcase\n");
    } 
  }

  if (btype != formButtonPush) {
    // Even though V is inheritable we are interested in the value of this
    // field, if not present it's probably because it's a button in a set.
    appearanceState = dict->lookup("V");
  }
}

static const char *_getButtonType(FormButtonType type)
{
  switch (type) {
  case formButtonPush:
    return "push";
  case formButtonCheck:
    return "check";
  case formButtonRadio:
    return "radio";
  default:
    break;
  }
  return "unknown";
}

void FormFieldButton::print(int indent)
{
  printf ("%*s- (%d %d): [%s] terminal: %s children: %d\n", indent, "", ref.num, ref.gen,
          _getButtonType(btype), terminal ? "Yes" : "No", numChildren);
}

void FormFieldButton::setNumSiblings (int num)
{ 
  numSiblings = num; 
  siblings = (FormFieldButton**)greallocn(siblings, numSiblings, sizeof(FormFieldButton*));
}

void FormFieldButton::fillChildrenSiblingsID()
{
  if (!terminal) {
    for(int i=0; i<numChildren; i++) {
      FormFieldButton *child = dynamic_cast<FormFieldButton*>(children[i]);
      if (child != nullptr) {
        // Fill the siblings of this node childs
        child->setNumSiblings(numChildren-1);
        for(int j=0, counter=0; j<numChildren; j++) {
          FormFieldButton *otherChild = dynamic_cast<FormFieldButton*>(children[j]);
          if (i == j) continue;
          if (child == otherChild) continue;
          child->setSibling(counter, otherChild);
          counter++;
        }

        // now call ourselves on the child
        // to fill its children data
        child->fillChildrenSiblingsID();
      }
    }
  }
}

bool FormFieldButton::setState(const char *state)
{
  // A check button could behave as a radio button
  // when it's in a set of more than 1 buttons
  if (btype != formButtonRadio && btype != formButtonCheck)
    return false;

  if (terminal && parent && parent->getType() == formButton && appearanceState.isNull()) {
    // It's button in a set, set state on parent
    if (static_cast<FormFieldButton*>(parent)->setState(state)) {
      return true;
    }
    return false;
  }

  bool isOn = strcmp(state, "Off") != 0;

  if (!isOn && noAllOff)
    return false; // Don't allow to set all radio to off

  const char *current = getAppearanceState();
  bool currentFound = false, newFound = false;

  for (int i = 0; i < numChildren; i++) {
    FormWidgetButton *widget;

    // If radio button is a terminal field we want the widget at i, but
    // if it's not terminal, the child widget is a composed dict, so
    // we want the ony child widget of the children at i
    if (terminal)
      widget = static_cast<FormWidgetButton*>(widgets[i]);
    else
      widget = static_cast<FormWidgetButton*>(children[i]->getWidget(0));

    if (!widget->getOnStr())
      continue;

    const char *onStr = widget->getOnStr();
    if (current && strcmp(current, onStr) == 0) {
      widget->setAppearanceState("Off");
      if (!isOn)
        break;
      currentFound = true;
    }

    if (isOn && strcmp(state, onStr) == 0) {
      widget->setAppearanceState(state);
      newFound = true;
    }

    if (currentFound && newFound)
      break;
  }

  updateState(state);

  return true;
}

bool FormFieldButton::getState(const char *state) const {
  if (appearanceState.isName(state))
    return true;

  return (parent && parent->getType() == formButton) ? static_cast<FormFieldButton*>(parent)->getState(state) : false;
}

void FormFieldButton::updateState(const char *state) {
  appearanceState = Object(objName, state);
  obj.getDict()->set("V", appearanceState.copy());
  xref->setModifiedObject(&obj, ref);
}

FormFieldButton::~FormFieldButton()
{
  if (siblings)
    gfree(siblings);
}

//------------------------------------------------------------------------
// FormFieldText
//------------------------------------------------------------------------
FormFieldText::FormFieldText(PDFDoc *docA, Object &&aobj, const Ref ref, FormField *parent, std::set<int> *usedParents)
  : FormField(docA, std::move(aobj), ref, parent, usedParents, formText)
{
  Dict* dict = obj.getDict();
  Object obj1;
  content = nullptr;
  multiline = password = fileSelect = doNotSpellCheck = doNotScroll = comb = richText = false;
  maxLen = 0;

  obj1 = Form::fieldLookup(dict, "Ff");
  if (obj1.isInt()) {
    int flags = obj1.getInt();
    if (flags & 0x1000) // 13 -> Multiline
      multiline = true;
    if (flags & 0x2000) // 14 -> Password
      password = true;
    if (flags & 0x100000) // 21 -> FileSelect
      fileSelect = true;
    if (flags & 0x400000)// 23 -> DoNotSpellCheck
      doNotSpellCheck = true;
    if (flags & 0x800000) // 24 -> DoNotScroll
      doNotScroll = true;
    if (flags & 0x1000000) // 25 -> Comb
      comb = true;
    if (flags & 0x2000000)// 26 -> RichText
      richText = true;
  }

  obj1 = Form::fieldLookup(dict, "MaxLen");
  if (obj1.isInt()) {
    maxLen = obj1.getInt();
  }

  obj1 = Form::fieldLookup(dict, "V");
  if (obj1.isString()) {
    if (obj1.getString()->hasUnicodeMarker()) {
      if (obj1.getString()->getLength() > 2)
        content = obj1.getString()->copy();
    } else if (obj1.getString()->getLength() > 0) {
      //non-unicode string -- assume pdfDocEncoding and try to convert to UTF16BE
      int tmp_length;
      char* tmp_str = pdfDocEncodingToUTF16(obj1.getString(), &tmp_length);
      content = new GooString(tmp_str, tmp_length);
      delete [] tmp_str;
    }
  }
}

void FormFieldText::print(int indent)
{
  printf ("%*s- (%d %d): [text] terminal: %s children: %d\n", indent, "", ref.num, ref.gen,
          terminal ? "Yes" : "No", numChildren);
}

void FormFieldText::setContentCopy (const GooString* new_content)
{
  delete content;
  content = nullptr;

  if (new_content) {
    content = new_content->copy();

    //append the unicode marker <FE FF> if needed
    if (!content->hasUnicodeMarker()) {
      content->prependUnicodeMarker();
    }
  }

  obj.getDict()->set("V", Object(content ? content->copy() : new GooString("")));
  xref->setModifiedObject(&obj, ref);
  updateChildrenAppearance();
}

FormFieldText::~FormFieldText()
{
  delete content;
}

double FormFieldText::getTextFontSize()
{
  GooList* daToks = new GooList();
  int idx = parseDA(daToks);
  double fontSize = -1;
  if (idx >= 0) {
    char* p = nullptr;
    fontSize = strtod(static_cast<GooString*>(daToks->get(idx))->c_str(), &p);
    if (!p || *p)
      fontSize = -1;
  }
  deleteGooList<GooString>(daToks);
  return fontSize;
}

void FormFieldText::setTextFontSize(int fontSize)
{
  if (fontSize > 0 && obj.isDict()) {
    GooList* daToks = new GooList();
    int idx = parseDA(daToks);
    if (idx == -1) {
      error(errSyntaxError, -1, "FormFieldText:: invalid DA object\n");
      deleteGooList<GooString>(daToks);
      return;
    }
    if (defaultAppearance)
      delete defaultAppearance;
    defaultAppearance = new GooString;
    for (int i = 0; i < daToks->getLength(); ++i) {
      if (i > 0)
        defaultAppearance->append(' ');
      if (i == idx) {
        defaultAppearance->appendf("{0:d}", fontSize);
      } else {
        defaultAppearance->append(static_cast<GooString*>(daToks->get(i)));
      }
    }
    deleteGooList<GooString>(daToks);
    obj.dictSet("DA", Object(defaultAppearance->copy()));
    xref->setModifiedObject(&obj, ref);
    updateChildrenAppearance();
  }
}

int FormFieldText::tokenizeDA(const GooString* da, GooList* daToks, const char* searchTok)
{
  int idx = -1;
  if(da && daToks) {
    int i = 0;
    int j = 0;
    while (i < da->getLength()) {
      while (i < da->getLength() && Lexer::isSpace(da->getChar(i))) {
        ++i;
      }
      if (i < da->getLength()) {
        for (j = i + 1; j < da->getLength() && !Lexer::isSpace(da->getChar(j)); ++j) {
        }
        GooString* tok = new GooString(da, i, j - i);
        if (searchTok && !tok->cmp(searchTok))
          idx = daToks->getLength();
        daToks->push_back(tok);
        i = j;
      }
    }
  }
  return idx;
}

int FormFieldText::parseDA(GooList* daToks)
{
  int idx = -1;
  if (obj.isDict()) {
    Object objDA(obj.dictLookup("DA"));
    if (objDA.isString()) {
      const GooString* da = objDA.getString();
      idx = tokenizeDA(da, daToks, "Tf") - 1;
    }
  }
  return idx;
}


//------------------------------------------------------------------------
// FormFieldChoice
//------------------------------------------------------------------------
FormFieldChoice::FormFieldChoice(PDFDoc *docA, Object &&aobj, const Ref ref, FormField *parent, std::set<int> *usedParents)
  : FormField(docA, std::move(aobj), ref, parent, usedParents, formChoice)
{
  numChoices = 0;
  choices = nullptr;
  editedChoice = nullptr;
  topIdx = 0;

  Dict* dict = obj.getDict();
  Object obj1;

  combo = edit = multiselect = doNotSpellCheck = doCommitOnSelChange = false;

  obj1 = Form::fieldLookup(dict, "Ff");
  if (obj1.isInt()) {
    int flags = obj1.getInt();
    if (flags & 0x20000) // 18 -> Combo
      combo = true; 
    if (flags & 0x40000) // 19 -> Edit
      edit = true;
    if (flags & 0x200000) // 22 -> MultiSelect
      multiselect = true;
    if (flags & 0x400000) // 23 -> DoNotSpellCheck
      doNotSpellCheck = true;
    if (flags & 0x4000000) // 27 -> CommitOnSelChange
      doCommitOnSelChange = true;
  }

  obj1 = dict->lookup("TI");
  if (obj1.isInt())
    topIdx = obj1.getInt();

  obj1 = dict->lookup("Opt");
  if (obj1.isArray()) {
    numChoices = obj1.arrayGetLength();
    choices = new ChoiceOpt[numChoices];
    memset(choices, 0, sizeof(ChoiceOpt) * numChoices);

    for (int i = 0; i < numChoices; i++) {
      Object obj2 = obj1.arrayGet(i);
      if (obj2.isString()) {
        choices[i].optionName = obj2.getString()->copy();
      } else if (obj2.isArray()) { // [Export_value, Displayed_text]
        if (obj2.arrayGetLength() < 2) {
          error(errSyntaxError, -1, "FormWidgetChoice:: invalid Opt entry -- array's length < 2\n");
          continue;
        }
        Object obj3 = obj2.arrayGet(0);
        if (obj3.isString())
          choices[i].exportVal = obj3.getString()->copy();
        else
          error(errSyntaxError, -1, "FormWidgetChoice:: invalid Opt entry -- exported value not a string\n");

        obj3 = obj2.arrayGet(1);
        if (obj3.isString())
          choices[i].optionName = obj3.getString()->copy();
        else
          error(errSyntaxError, -1, "FormWidgetChoice:: invalid Opt entry -- choice name not a string\n");
      } else {
        error(errSyntaxError, -1, "FormWidgetChoice:: invalid {0:d} Opt entry\n", i);
      }
    }
  } else {
    //empty choice
  }

  // Find selected items
  // Note: PDF specs say that /V has precedence over /I, but acroread seems to
  // do the opposite. We do the same.
  obj1 = Form::fieldLookup(dict, "I");
  if (obj1.isArray()) {
    for (int i = 0; i < obj1.arrayGetLength(); i++) {
      Object obj2 = obj1.arrayGet(i);
      if (obj2.isInt() && obj2.getInt() >= 0 && obj2.getInt() < numChoices) {
        choices[obj2.getInt()].selected = true;
      }
    }
  } else {
    // Note: According to PDF specs, /V should *never* contain the exportVal.
    // However, if /Opt is an array of (exportVal,optionName) pairs, acroread
    // seems to expect the exportVal instead of the optionName and so we do too.
    obj1 = Form::fieldLookup(dict, "V");
    if (obj1.isString()) {
      bool optionFound = false;

      for (int i = 0; i < numChoices; i++) {
        if (choices[i].exportVal) {
          if (choices[i].exportVal->cmp(obj1.getString()) == 0) {
            optionFound = true;
          }
        } else if (choices[i].optionName) {
          if (choices[i].optionName->cmp(obj1.getString()) == 0) {
            optionFound = true;
          }
        }

        if (optionFound) {
          choices[i].selected = true;
          break; // We've determined that this option is selected. No need to keep on scanning
        }
      }

      // Set custom value if /V doesn't refer to any predefined option and the field is user-editable
      if (!optionFound && edit) {
        editedChoice = obj1.getString()->copy();
      }
    } else if (obj1.isArray()) {
      for (int i = 0; i < numChoices; i++) {
        for (int j = 0; j < obj1.arrayGetLength(); j++) {
          Object obj2 = obj1.arrayGet(j);
          bool matches = false;

          if (choices[i].exportVal) {
            if (choices[i].exportVal->cmp(obj2.getString()) == 0) {
              matches = true;
            }
          } else if (choices[i].optionName) {
            if (choices[i].optionName->cmp(obj2.getString()) == 0) {
              matches = true;
            }
          }

          if (matches) {
            choices[i].selected = true;
            break; // We've determined that this option is selected. No need to keep on scanning
          }
        }
      }
    }
  }
}

FormFieldChoice::~FormFieldChoice()
{
  for (int i = 0; i < numChoices; i++) {
    delete choices[i].exportVal;
    delete choices[i].optionName;
  }
  delete [] choices;
  delete editedChoice;
}

void FormFieldChoice::print(int indent)
{
  printf ("%*s- (%d %d): [choice] terminal: %s children: %d\n", indent, "", ref.num, ref.gen,
          terminal ? "Yes" : "No", numChildren);
}

void FormFieldChoice::updateSelection() {
  Object objV;
  Object objI(objNull);

  if (edit && editedChoice) {
    // This is an editable combo-box with user-entered text
    objV = Object(editedChoice->copy());
  } else {
    const int numSelected = getNumSelected();

    // Create /I array only if multiple selection is allowed (as per PDF spec)
    if (multiselect) {
      objI = Object(new Array(xref));
    }

    if (numSelected == 0) {
      // No options are selected
      objV = Object(new GooString(""));
    } else if (numSelected == 1) {
      // Only one option is selected
      for (int i = 0; i < numChoices; i++) {
        if (choices[i].selected) {
          if (multiselect) {
            objI.arrayAdd(Object(i));
          }

          if (choices[i].exportVal) {
            objV = Object(choices[i].exportVal->copy());
          } else if (choices[i].optionName) {
            objV = Object(choices[i].optionName->copy());
          }

          break; // We've just written the selected option. No need to keep on scanning
        }
      }
    } else {
      // More than one option is selected
      objV = Object(new Array(xref));
      for (int i = 0; i < numChoices; i++) {
        if (choices[i].selected) {
          if (multiselect) {
            objI.arrayAdd(Object(i));
          }

          if (choices[i].exportVal) {
            objV.arrayAdd(Object(choices[i].exportVal->copy()));
          } else if (choices[i].optionName) {
            objV.arrayAdd(Object(choices[i].optionName->copy()));
          }
        }
      }
    }
  }

  obj.getDict()->set("V", std::move(objV));
  obj.getDict()->set("I", std::move(objI));
  xref->setModifiedObject(&obj, ref);
  updateChildrenAppearance();
}

void FormFieldChoice::unselectAll ()
{
  for (int i = 0; i < numChoices; i++) {
    choices[i].selected = false;
  }
}

void FormFieldChoice::deselectAll () {
  delete editedChoice;
  editedChoice = nullptr;

  unselectAll();
  updateSelection();
}

void FormFieldChoice::toggle (int i)
{
  delete editedChoice;
  editedChoice = nullptr;

  choices[i].selected = !choices[i].selected;
  updateSelection();
}

void FormFieldChoice::select (int i)
{
  delete editedChoice;
  editedChoice = nullptr;

  if (!multiselect)
    unselectAll();

  choices[i].selected = true;
  updateSelection();
}

void FormFieldChoice::setEditChoice (const GooString* new_content)
{
  delete editedChoice;
  editedChoice = nullptr;

  unselectAll();

  if (new_content) {
    editedChoice = new_content->copy();

    //append the unicode marker <FE FF> if needed
    if (!editedChoice->hasUnicodeMarker()) {
      editedChoice->prependUnicodeMarker();
    }
  }
  updateSelection();
}

const GooString* FormFieldChoice::getEditChoice () const
{
  return editedChoice;
}

int FormFieldChoice::getNumSelected ()
{
  int cnt = 0;
  for(int i=0; i<numChoices; i++) {
    if (choices[i].selected)
      cnt++;
  }
  return cnt;
}

const GooString *FormFieldChoice::getSelectedChoice() const {
  if (edit && editedChoice)
    return editedChoice;

  for (int i = 0; i < numChoices; i++) {
    if (choices[i].optionName && choices[i].selected)
      return choices[i].optionName;
  }

  return nullptr;
}

//------------------------------------------------------------------------
// FormFieldSignature
//------------------------------------------------------------------------
FormFieldSignature::FormFieldSignature(PDFDoc *docA, Object &&dict, const Ref ref, FormField *parent, std::set<int> *usedParents)
  : FormField(docA, std::move(dict), ref, parent, usedParents, formSignature),
    signature_type(adbe_pkcs7_detached),
    signature(nullptr), signature_info(nullptr)
{
  signature = nullptr;

  signature_info = new SignatureInfo();
  parseInfo();
}

FormFieldSignature::~FormFieldSignature()
{
  delete signature_info;
  delete signature;
}

void FormFieldSignature::parseInfo()
{
  if (!obj.isDict())
    return;

  // retrieve PKCS#7
  Object sig_dict = obj.dictLookup("V");
  if (!sig_dict.isDict()) {
    return;
  }

  Object contents_obj = sig_dict.dictLookup("Contents");
  if (contents_obj.isString()) {
    signature = contents_obj.getString()->copy();
  }

  byte_range = sig_dict.dictLookup("ByteRange");

  const Object location_obj = sig_dict.dictLookup("Location");
  if (location_obj.isString()) {
    signature_info->setLocation(location_obj.getString()->c_str());
  }

  const Object reason_obj = sig_dict.dictLookup("Reason");
  if (reason_obj.isString()) {
    signature_info->setReason(reason_obj.getString()->c_str());
  }

  // retrieve SigningTime
  Object time_of_signing = sig_dict.dictLookup("M");
  if (time_of_signing.isString()) {
    const GooString *time_str = time_of_signing.getString();
    signature_info->setSigningTime(dateStringToTime(time_str)); // Put this information directly in SignatureInfo object
  }

  // check if subfilter is supported for signature validation, only detached signatures work for now
  Object subfilterName = sig_dict.dictLookup("SubFilter");
  if (subfilterName.isName("adbe.pkcs7.sha1")) {
    signature_type = adbe_pkcs7_sha1;
    signature_info->setSubFilterSupport(true);
  }
  else if (subfilterName.isName("adbe.pkcs7.detached")) {
    signature_type = adbe_pkcs7_detached;
    signature_info->setSubFilterSupport(true);
  }
  else if (subfilterName.isName("ETSI.CAdES.detached")) {
    signature_type = ETSI_CAdES_detached;
    signature_info->setSubFilterSupport(true);
  }
}

void FormFieldSignature::hashSignedDataBlock(SignatureHandler *handler, Goffset block_len)
{
#ifdef ENABLE_NSS3
  const int BLOCK_SIZE = 4096;
  unsigned char signed_data_buffer[BLOCK_SIZE];

  Goffset i = 0;
  while(i < block_len)
  {
    Goffset bytes_left = block_len - i;
    if (bytes_left < BLOCK_SIZE)
    {
      doc->getBaseStream()->doGetChars(bytes_left, signed_data_buffer);
      handler->updateHash(signed_data_buffer, bytes_left);
      i = block_len;
    }
    else
    {
      doc->getBaseStream()->doGetChars(BLOCK_SIZE, signed_data_buffer);
      handler->updateHash(signed_data_buffer, BLOCK_SIZE);
      i += BLOCK_SIZE;
    }
  }
#endif
}

FormSignatureType FormWidgetSignature::signatureType()
{
  return static_cast<FormFieldSignature*>(field)->signature_type;
}

SignatureInfo *FormFieldSignature::validateSignature(bool doVerifyCert, bool forceRevalidation, time_t validationTime)
{
#ifdef ENABLE_NSS3
  if (!signature_info->isSubfilterSupported()) {
    error(errUnimplemented, 0, "Unable to validate this type of signature");
    return signature_info;
  }

  if (signature_info->getSignatureValStatus() != SIGNATURE_NOT_VERIFIED && !forceRevalidation) {
    return signature_info;
  }

  if (signature == nullptr) {
    error(errSyntaxError, 0, "Invalid or missing Signature string");
    return signature_info;
  }

  if (!byte_range.isArray()) {
    error(errSyntaxError, 0, "Invalid or missing ByteRange array");
    return signature_info;
  }

  int arrayLen = byte_range.arrayGetLength();
  if (arrayLen < 2) {
    error(errSyntaxError, 0, "Too few elements in ByteRange array");
    return signature_info;
  }

  const int signature_len = signature->getLength();
  unsigned char *signatureuchar = (unsigned char *)gmalloc(signature_len);
  memcpy(signatureuchar, signature->c_str(), signature_len);
  SignatureHandler signature_handler(signatureuchar, signature_len);

  Goffset fileLength = doc->getBaseStream()->getLength();
  for (int i = 0; i < arrayLen/2; i++) {
    Object offsetObj = byte_range.arrayGet(i*2);
    Object lenObj = byte_range.arrayGet(i*2+1);

    if (!offsetObj.isIntOrInt64() || !lenObj.isIntOrInt64()) {
      error(errSyntaxError, 0, "Illegal values in ByteRange array");
      return signature_info;
    }

    Goffset offset = offsetObj.getIntOrInt64();
    Goffset len = lenObj.getIntOrInt64();

    if (offset < 0 || offset >= fileLength || len < 0 || len > fileLength || offset + len > fileLength) {
      error(errSyntaxError, 0, "Illegal values in ByteRange array");
      return signature_info;
    }

    doc->getBaseStream()->setPos(offset);
    hashSignedDataBlock(&signature_handler, len);
  }

  const SignatureValidationStatus sig_val_state = signature_handler.validateSignature();
  signature_info->setSignatureValStatus(sig_val_state);
  signature_info->setSignerName(signature_handler.getSignerName());
  signature_info->setSubjectDN(signature_handler.getSignerSubjectDN());
  signature_info->setHashAlgorithm(signature_handler.getHashAlgorithm());

  // verify if signature contains a 'signing time' attribute
  if (signature_handler.getSigningTime() != 0) {
    signature_info->setSigningTime(signature_handler.getSigningTime());
  }

  if (sig_val_state != SIGNATURE_VALID || !doVerifyCert) {
    return signature_info;
  }

  const CertificateValidationStatus cert_val_state = signature_handler.validateCertificate(validationTime);
  signature_info->setCertificateValStatus(cert_val_state);
  signature_info->setCertificateInfo(signature_handler.getCertificateInfo());

#endif
  return signature_info;
}

void FormFieldSignature::print(int indent)
{
  printf ("%*s- (%d %d): [signature] terminal: %s children: %d\n", indent, "", ref.num, ref.gen,
          terminal ? "Yes" : "No", numChildren);
}

//------------------------------------------------------------------------
// Form
//------------------------------------------------------------------------

Form::Form(PDFDoc *docA, Object* acroFormA)
{
  Object obj1;

  doc = docA;
  xref = doc->getXRef();
  acroForm = acroFormA;
  
  size = 0;
  numFields = 0;
  rootFields = nullptr;
  quadding = quaddingLeftJustified;
  defaultAppearance = nullptr;
  defaultResources = nullptr;

  obj1 = acroForm->dictLookup("NeedAppearances");
  needAppearances = (obj1.isBool() && obj1.getBool());

  obj1 = acroForm->dictLookup("DA");
  if (obj1.isString())
    defaultAppearance = obj1.getString()->copy();

  obj1 = acroForm->dictLookup("Q");
  if (obj1.isInt())
    quadding = static_cast<VariableTextQuadding>(obj1.getInt());

  resDict = acroForm->dictLookup("DR");
  if (resDict.isDict()) {
    // At a minimum, this dictionary shall contain a Font entry
    obj1 = resDict.dictLookup("Font");
    if (obj1.isDict())
      defaultResources = new GfxResources(xref, resDict.getDict(), nullptr);
  }
  if (!defaultResources) {
    resDict.setToNull();
  }

  obj1 = acroForm->dictLookup("Fields");
  if (obj1.isArray()) {
    Array *array = obj1.getArray();
    for(int i=0; i<array->getLength(); i++) {
      Object obj2 = array->get(i);
      const Object &oref = array->getNF(i);
      if (!oref.isRef()) {
        error(errSyntaxWarning, -1, "Direct object in rootFields");
        continue;
      }

      if (!obj2.isDict()) {
        error(errSyntaxWarning, -1, "Reference in Fields array to an invalid or non existent object");
	continue;
      }

      if (numFields >= size) {
        size += 16;
        rootFields = (FormField**)greallocn(rootFields,size,sizeof(FormField*));
      }

      std::set<int> usedParents;
      rootFields[numFields++] = createFieldFromDict (std::move(obj2), doc, oref.getRef(), nullptr, &usedParents);

    }
  } else {
    error(errSyntaxError, -1, "Can't get Fields array\n");
  }

  obj1 = acroForm->dictLookup("CO");
  if (obj1.isArray()) {
    Array *array = obj1.getArray();
    calculateOrder.reserve(array->getLength());
    for(int i=0; i<array->getLength(); i++) {
      const Object &oref = array->getNF(i);
      if (!oref.isRef()) {
        error(errSyntaxWarning, -1, "Direct object in CO");
        continue;
      }
      calculateOrder.push_back(oref.getRef());
    }
  }

//   for (int i = 0; i < numFields; i++)
//     rootFields[i]->printTree();
}

Form::~Form() {
  int i;
  for(i = 0; i < numFields; ++i)
    delete rootFields[i];
  gfree (rootFields);
  delete defaultAppearance;
  delete defaultResources;
}

// Look up an inheritable field dictionary entry.
static Object fieldLookup(Dict *field, const char *key, std::set<int> *usedParents) {
  Dict *dict = field;
  Object obj = dict->lookup(key);
  if (!obj.isNull()) {
    return obj;
  }
  const Object &parent = dict->lookupNF("Parent");
  if (parent.isRef()) {
    const Ref ref = parent.getRef();
    if (usedParents->find(ref.num) == usedParents->end()) {
      usedParents->insert(ref.num);

      Object obj2 = parent.fetch(dict->getXRef());
      if (obj2.isDict()) {
        return fieldLookup(obj2.getDict(), key, usedParents);
      }
    }
  } else if (parent.isDict()) {
    return fieldLookup(parent.getDict(), key, usedParents);
  }
  return Object(objNull);
}

Object Form::fieldLookup(Dict *field, const char *key) {
  std::set<int> usedParents;
  return ::fieldLookup(field, key, &usedParents);
}

FormField *Form::createFieldFromDict (Object &&obj, PDFDoc *docA, const Ref pref, FormField *parent, std::set<int> *usedParents)
{
    FormField *field;

    const Object obj2 = Form::fieldLookup(obj.getDict (), "FT");
    if (obj2.isName("Btn")) {
      field = new FormFieldButton(docA, std::move(obj), pref, parent, usedParents);
    } else if (obj2.isName("Tx")) {
      field = new FormFieldText(docA, std::move(obj), pref, parent, usedParents);
    } else if (obj2.isName("Ch")) {
      field = new FormFieldChoice(docA, std::move(obj), pref, parent, usedParents);
    } else if (obj2.isName("Sig")) {
      field = new FormFieldSignature(docA, std::move(obj), pref, parent, usedParents);
    } else { //we don't have an FT entry => non-terminal field
      field = new FormField(docA, std::move(obj), pref, parent, usedParents);
    }

    return field;
}

void Form::postWidgetsLoad()
{
  // We create the widget annotations associated to
  // every form widget here, because the AnnotWidget constructor
  // needs the form object that gets from the catalog. When constructing
  // a FormWidget the Catalog is still creating the form object
  for (int i = 0; i < numFields; i++) {
    rootFields[i]->fillChildrenSiblingsID();
    rootFields[i]->createWidgetAnnotations();
  }
}

FormWidget* Form::findWidgetByRef (Ref aref)
{
  for(int i=0; i<numFields; i++) {
    FormWidget *result = rootFields[i]->findWidgetByRef(aref);
    if(result) return result;
  }
  return nullptr;
}

//------------------------------------------------------------------------
// FormPageWidgets
//------------------------------------------------------------------------

FormPageWidgets::FormPageWidgets (Annots *annots, unsigned int page, Form *form)
{
  numWidgets = 0;
  widgets = nullptr;

  if (annots && annots->getNumAnnots() > 0 && form) {
    size = annots->getNumAnnots();
    widgets = (FormWidget**)greallocn(widgets, size, sizeof(FormWidget*));

    /* For each entry in the page 'Annots' dict, try to find
       a matching form field */
    for (int i = 0; i < size; ++i) {
      Annot *annot = annots->getAnnot(i);

      if (annot->getType() != Annot::typeWidget)
        continue;

      if (!annot->getHasRef()) {
        /* Since all entry in a form field's kid dict needs to be
           indirect references, if this annot isn't indirect, it isn't 
           related to a form field */
        continue;
      }

      Ref r = annot->getRef();

      /* Try to find a form field which either has this Annot in its Kids entry
          or  is merged with this Annot */
      FormWidget* tmp = form->findWidgetByRef(r);
      if (tmp) {
        // We've found a corresponding form field, link it
        tmp->setID(FormWidget::encodeID(page, numWidgets));
        widgets[numWidgets++] = tmp;
      }
    }
  }
}

FormPageWidgets::~FormPageWidgets()
{
  gfree (widgets);
}
