예제 #1
0
        /// <summary>Sets the XFA key from a byte array.</summary>
        /// <remarks>Sets the XFA key from a byte array. The old XFA is erased.</remarks>
        /// <param name="form">the data</param>
        /// <param name="acroForm">an AcroForm instance</param>
        /// <exception cref="System.IO.IOException">on IO error</exception>
        public static void SetXfaForm(iText.Forms.Xfa.XfaForm form, PdfAcroForm acroForm)
        {
            if (form == null || acroForm == null || acroForm.GetPdfDocument() == null)
            {
                throw new ArgumentException("XfaForm, PdfAcroForm and PdfAcroForm's document shall not be null");
            }
            PdfDocument document = acroForm.GetPdfDocument();
            PdfObject   xfa      = GetXfaObject(acroForm);

            if (xfa != null && xfa.IsArray())
            {
                PdfArray ar = (PdfArray)xfa;
                int      t  = -1;
                int      d  = -1;
                for (int k = 0; k < ar.Size(); k += 2)
                {
                    PdfString s = ar.GetAsString(k);
                    if ("template".Equals(s.ToString()))
                    {
                        t = k + 1;
                    }
                    if ("datasets".Equals(s.ToString()))
                    {
                        d = k + 1;
                    }
                }
                if (t > -1 && d > -1)
                {
                    //reader.killXref(ar.getAsIndirectObject(t));
                    //reader.killXref(ar.getAsIndirectObject(d));
                    PdfStream tStream = new PdfStream(SerializeDocument(form.templateNode));
                    tStream.SetCompressionLevel(document.GetWriter().GetCompressionLevel());
                    ar.Set(t, tStream);
                    PdfStream dStream = new PdfStream(SerializeDocument(form.datasetsNode));
                    dStream.SetCompressionLevel(document.GetWriter().GetCompressionLevel());
                    ar.Set(d, dStream);
                    ar.SetModified();
                    ar.Flush();
                    acroForm.Put(PdfName.XFA, new PdfArray(ar));
                    acroForm.SetModified();
                    if (!acroForm.GetPdfObject().IsIndirect())
                    {
                        document.GetCatalog().SetModified();
                    }
                    return;
                }
            }
            //reader.killXref(af.get(PdfName.XFA));
            PdfStream stream = new PdfStream(SerializeDocument(form.domDocument));

            stream.SetCompressionLevel(document.GetWriter().GetCompressionLevel());
            stream.Flush();
            acroForm.Put(PdfName.XFA, stream);
            acroForm.SetModified();
            if (!acroForm.GetPdfObject().IsIndirect())
            {
                document.GetCatalog().SetModified();
            }
        }
예제 #2
0
        public virtual void SetDefaultJustificationTest()
        {
            PdfDocument outputDoc = CreateDocument();
            PdfAcroForm acroForm  = PdfAcroForm.GetAcroForm(outputDoc, true);

            acroForm.SetDefaultJustification(14);
            bool      isModified           = acroForm.GetPdfObject().IsModified();
            bool      isReleaseForbidden   = acroForm.GetPdfObject().IsReleaseForbidden();
            PdfObject defaultJustification = acroForm.GetPdfObject().Get(PdfName.Q);

            outputDoc.Close();
            NUnit.Framework.Assert.AreEqual(new PdfNumber(14), defaultJustification);
            NUnit.Framework.Assert.IsTrue(isModified);
            NUnit.Framework.Assert.IsTrue(isReleaseForbidden);
        }
예제 #3
0
        public virtual void SetSignatureFlagsTest()
        {
            PdfDocument outputDoc = CreateDocument();
            PdfAcroForm acroForm  = PdfAcroForm.GetAcroForm(outputDoc, true);

            acroForm.SetSignatureFlags(65);
            bool      isModified         = acroForm.GetPdfObject().IsModified();
            bool      isReleaseForbidden = acroForm.GetPdfObject().IsReleaseForbidden();
            PdfObject sigFlags           = acroForm.GetPdfObject().Get(PdfName.SigFlags);

            outputDoc.Close();
            NUnit.Framework.Assert.AreEqual(new PdfNumber(65), sigFlags);
            NUnit.Framework.Assert.IsTrue(isModified);
            NUnit.Framework.Assert.IsTrue(isReleaseForbidden);
        }
예제 #4
0
        public virtual void SetDefaultAppearanceTest()
        {
            PdfDocument outputDoc = CreateDocument();
            PdfAcroForm acroForm  = PdfAcroForm.GetAcroForm(outputDoc, true);

            acroForm.SetDefaultAppearance("default appearance");
            bool      isModified         = acroForm.GetPdfObject().IsModified();
            bool      isReleaseForbidden = acroForm.GetPdfObject().IsReleaseForbidden();
            PdfObject calculationOrder   = acroForm.GetPdfObject().Get(PdfName.DA);

            outputDoc.Close();
            NUnit.Framework.Assert.AreEqual(new PdfString("default appearance"), calculationOrder);
            NUnit.Framework.Assert.IsTrue(isModified);
            NUnit.Framework.Assert.IsTrue(isReleaseForbidden);
        }
예제 #5
0
        public virtual void SetNeedAppearancesTest()
        {
            PdfDocument outputDoc = CreateDocument();
            PdfAcroForm acroForm  = PdfAcroForm.GetAcroForm(outputDoc, true);

            acroForm.SetNeedAppearances(false);
            bool      isModified         = acroForm.GetPdfObject().IsModified();
            bool      isReleaseForbidden = acroForm.GetPdfObject().IsReleaseForbidden();
            PdfObject needAppearance     = acroForm.GetPdfObject().Get(PdfName.NeedAppearances);

            outputDoc.Close();
            NUnit.Framework.Assert.AreEqual(new PdfBoolean(false), needAppearance);
            NUnit.Framework.Assert.IsTrue(isModified);
            NUnit.Framework.Assert.IsTrue(isReleaseForbidden);
        }
예제 #6
0
        public virtual void SetCalculationOrderTest()
        {
            PdfDocument outputDoc             = CreateDocument();
            PdfAcroForm acroForm              = PdfAcroForm.GetAcroForm(outputDoc, true);
            PdfArray    calculationOrderArray = new PdfArray(new int[] { 1, 0 });

            acroForm.SetCalculationOrder(calculationOrderArray);
            bool      isModified         = acroForm.GetPdfObject().IsModified();
            bool      isReleaseForbidden = acroForm.GetPdfObject().IsReleaseForbidden();
            PdfObject calculationOrder   = acroForm.GetPdfObject().Get(PdfName.CO);

            outputDoc.Close();
            NUnit.Framework.Assert.AreEqual(calculationOrderArray, calculationOrder);
            NUnit.Framework.Assert.IsTrue(isModified);
            NUnit.Framework.Assert.IsTrue(isReleaseForbidden);
        }
예제 #7
0
        public virtual void SetXFAResourcePdfStreamTest()
        {
            PdfDocument outputDoc = CreateDocument();
            PdfAcroForm acroForm  = PdfAcroForm.GetAcroForm(outputDoc, true);
            PdfStream   stream    = new PdfStream();

            acroForm.SetXFAResource(stream);
            bool      isModified         = acroForm.GetPdfObject().IsModified();
            bool      isReleaseForbidden = acroForm.GetPdfObject().IsReleaseForbidden();
            PdfObject xfaObject          = acroForm.GetPdfObject().Get(PdfName.XFA);

            outputDoc.Close();
            NUnit.Framework.Assert.AreEqual(stream, xfaObject);
            NUnit.Framework.Assert.IsTrue(isModified);
            NUnit.Framework.Assert.IsTrue(isReleaseForbidden);
        }
예제 #8
0
        public virtual void SetDefaultResourcesTest()
        {
            PdfDocument   outputDoc  = CreateDocument();
            PdfAcroForm   acroForm   = PdfAcroForm.GetAcroForm(outputDoc, true);
            PdfDictionary dictionary = new PdfDictionary();

            PdfAcroForm.GetAcroForm(outputDoc, true).SetDefaultResources(dictionary);
            bool      isModified           = acroForm.GetPdfObject().IsModified();
            bool      isReleaseForbidden   = acroForm.GetPdfObject().IsReleaseForbidden();
            PdfObject defaultResourcesDict = acroForm.GetPdfObject().Get(PdfName.DR);

            outputDoc.Close();
            NUnit.Framework.Assert.AreEqual(dictionary, defaultResourcesDict);
            NUnit.Framework.Assert.IsTrue(isModified);
            NUnit.Framework.Assert.IsTrue(isReleaseForbidden);
        }
예제 #9
0
        public virtual void SetNeedAppearancesInPdf2Test()
        {
            PdfDocument outputDoc = new PdfDocument(new PdfWriter(new ByteArrayOutputStream(), new WriterProperties().
                                                                  SetPdfVersion(PdfVersion.PDF_2_0)));

            outputDoc.AddNewPage();
            PdfAcroForm acroForm = PdfAcroForm.GetAcroForm(outputDoc, true);

            acroForm.SetNeedAppearances(false);
            bool      isModified         = acroForm.GetPdfObject().IsModified();
            bool      isReleaseForbidden = acroForm.GetPdfObject().IsReleaseForbidden();
            PdfObject needAppearance     = acroForm.GetPdfObject().Get(PdfName.NeedAppearances);

            outputDoc.Close();
            NUnit.Framework.Assert.IsNull(needAppearance);
            NUnit.Framework.Assert.IsTrue(isModified);
            NUnit.Framework.Assert.IsTrue(isReleaseForbidden);
        }
        public virtual void Copy(PdfPage fromPage, PdfPage toPage)
        {
            if (documentFrom != fromPage.GetDocument())
            {
                documentFrom = fromPage.GetDocument();
                formFrom     = PdfAcroForm.GetAcroForm(documentFrom, false);
            }
            if (documentTo != toPage.GetDocument())
            {
                documentTo = toPage.GetDocument();
                formTo     = PdfAcroForm.GetAcroForm(documentTo, true);
            }
            if (formFrom == null)
            {
                return;
            }
            //duplicate AcroForm dictionary
            IList <PdfName> excludedKeys = new List <PdfName>();

            excludedKeys.Add(PdfName.Fields);
            excludedKeys.Add(PdfName.DR);
            PdfDictionary dict = formFrom.GetPdfObject().CopyTo(documentTo, excludedKeys, false);

            formTo.GetPdfObject().MergeDifferent(dict);
            IDictionary <String, PdfFormField> fieldsFrom = formFrom.GetFormFields();

            if (fieldsFrom.Count <= 0)
            {
                return;
            }
            IDictionary <String, PdfFormField> fieldsTo = formTo.GetFormFields();
            IList <PdfAnnotation> annots = toPage.GetAnnotations();

            foreach (PdfAnnotation annot in annots)
            {
                if (!annot.GetSubtype().Equals(PdfName.Widget))
                {
                    continue;
                }
                CopyField(toPage, fieldsFrom, fieldsTo, annot);
            }
        }
예제 #11
0
 /// <summary>Return the XFA Object, could be an array, could be a Stream.</summary>
 /// <remarks>
 /// Return the XFA Object, could be an array, could be a Stream.
 /// Returns null if no XFA Object is present.
 /// </remarks>
 /// <param name="acroForm">a PdfAcroForm instance</param>
 /// <returns>the XFA object</returns>
 private static PdfObject GetXfaObject(PdfAcroForm acroForm)
 {
     return(acroForm == null || acroForm.GetPdfObject() == null ? null : acroForm.GetPdfObject().Get(PdfName.XFA));
 }
예제 #12
0
        /// <summary>This is the first method to be called when using external signatures.</summary>
        /// <remarks>
        /// This is the first method to be called when using external signatures. The general sequence is:
        /// preClose(), getDocumentBytes() and close().
        /// <p>
        /// <CODE>exclusionSizes</CODE> must contain at least
        /// the <CODE>PdfName.CONTENTS</CODE> key with the size that it will take in the
        /// document. Note that due to the hex string coding this size should be byte_size*2+2.
        /// </remarks>
        /// <param name="exclusionSizes">
        /// Map with names and sizes to be excluded in the signature
        /// calculation. The key is a PdfName and the value an Integer. At least the /Contents must be present
        /// </param>
        /// <exception cref="System.IO.IOException">on error</exception>
        protected internal virtual void PreClose(IDictionary <PdfName, int?> exclusionSizes)
        {
            if (preClosed)
            {
                throw new PdfException(PdfException.DocumentAlreadyPreClosed);
            }
            // TODO: add mergeVerification functionality
            preClosed = true;
            PdfAcroForm   acroForm   = PdfAcroForm.GetAcroForm(document, true);
            SignatureUtil sgnUtil    = new SignatureUtil(document);
            String        name       = GetFieldName();
            bool          fieldExist = sgnUtil.DoesSignatureFieldExist(name);

            acroForm.SetSignatureFlags(PdfAcroForm.SIGNATURE_EXIST | PdfAcroForm.APPEND_ONLY);
            PdfSigFieldLockDictionary fieldLock = null;

            if (cryptoDictionary == null)
            {
                throw new PdfException(PdfException.NoCryptoDictionaryDefined);
            }
            cryptoDictionary.GetPdfObject().MakeIndirect(document);
            if (fieldExist)
            {
                PdfSignatureFormField sigField = (PdfSignatureFormField)acroForm.GetField(fieldName);
                sigField.Put(PdfName.V, cryptoDictionary.GetPdfObject());
                fieldLock = sigField.GetSigFieldLockDictionary();
                if (fieldLock == null && this.fieldLock != null)
                {
                    this.fieldLock.GetPdfObject().MakeIndirect(document);
                    sigField.Put(PdfName.Lock, this.fieldLock.GetPdfObject());
                    fieldLock = this.fieldLock;
                }
                sigField.Put(PdfName.P, document.GetPage(appearance.GetPageNumber()).GetPdfObject());
                sigField.Put(PdfName.V, cryptoDictionary.GetPdfObject());
                PdfObject obj   = sigField.GetPdfObject().Get(PdfName.F);
                int       flags = 0;
                if (obj != null && obj.IsNumber())
                {
                    flags = ((PdfNumber)obj).IntValue();
                }
                flags |= PdfAnnotation.LOCKED;
                sigField.Put(PdfName.F, new PdfNumber(flags));
                PdfDictionary ap = new PdfDictionary();
                ap.Put(PdfName.N, appearance.GetAppearance().GetPdfObject());
                sigField.Put(PdfName.AP, ap);
                sigField.SetModified();
            }
            else
            {
                PdfWidgetAnnotation widget = new PdfWidgetAnnotation(appearance.GetPageRect());
                widget.SetFlags(PdfAnnotation.PRINT | PdfAnnotation.LOCKED);
                PdfSignatureFormField sigField = PdfFormField.CreateSignature(document);
                sigField.SetFieldName(name);
                sigField.Put(PdfName.V, cryptoDictionary.GetPdfObject());
                sigField.AddKid(widget);
                if (this.fieldLock != null)
                {
                    this.fieldLock.GetPdfObject().MakeIndirect(document);
                    sigField.Put(PdfName.Lock, this.fieldLock.GetPdfObject());
                    fieldLock = this.fieldLock;
                }
                int pagen = appearance.GetPageNumber();
                widget.SetPage(document.GetPage(pagen));
                PdfDictionary ap = widget.GetAppearanceDictionary();
                if (ap == null)
                {
                    ap = new PdfDictionary();
                    widget.Put(PdfName.AP, ap);
                }
                ap.Put(PdfName.N, appearance.GetAppearance().GetPdfObject());
                acroForm.AddField(sigField, document.GetPage(pagen));
                if (acroForm.GetPdfObject().IsIndirect())
                {
                    acroForm.SetModified();
                }
                else
                {
                    //Acroform dictionary is a Direct dictionary,
                    //for proper flushing, catalog needs to be marked as modified
                    document.GetCatalog().SetModified();
                }
            }
            exclusionLocations = new Dictionary <PdfName, PdfLiteral>();
            PdfLiteral lit = new PdfLiteral(80);

            exclusionLocations[PdfName.ByteRange] = lit;
            cryptoDictionary.Put(PdfName.ByteRange, lit);
            foreach (KeyValuePair <PdfName, int?> entry in exclusionSizes)
            {
                PdfName key = entry.Key;
                lit = new PdfLiteral((int)entry.Value);
                exclusionLocations[key] = lit;
                cryptoDictionary.Put(key, lit);
            }
            if (certificationLevel > 0)
            {
                AddDocMDP(cryptoDictionary);
            }
            if (fieldLock != null)
            {
                AddFieldMDP(cryptoDictionary, fieldLock);
            }
            if (signatureEvent != null)
            {
                signatureEvent.GetSignatureDictionary(cryptoDictionary);
            }
            if (certificationLevel > 0)
            {
                // add DocMDP entry to root
                PdfDictionary docmdp = new PdfDictionary();
                docmdp.Put(PdfName.DocMDP, cryptoDictionary.GetPdfObject());
                document.GetCatalog().Put(PdfName.Perms, docmdp);
                document.GetCatalog().SetModified();
            }
            cryptoDictionary.GetPdfObject().Flush(false);
            document.Close();
            range = new long[exclusionLocations.Count * 2];
            long byteRangePosition = exclusionLocations.Get(PdfName.ByteRange).GetPosition();

            exclusionLocations.JRemove(PdfName.ByteRange);
            int idx = 1;

            foreach (PdfLiteral lit1 in exclusionLocations.Values)
            {
                long n = lit1.GetPosition();
                range[idx++] = n;
                range[idx++] = lit1.GetBytesCount() + n;
            }
            iText.IO.Util.JavaUtil.Sort(range, 1, range.Length - 1);
            for (int k = 3; k < range.Length - 2; k += 2)
            {
                range[k] -= range[k - 1];
            }
            if (tempFile == null)
            {
                bout = temporaryOS.ToArray();
                range[range.Length - 1] = bout.Length - range[range.Length - 2];
                MemoryStream    bos = new MemoryStream();
                PdfOutputStream os  = new PdfOutputStream(bos);
                os.Write('[');
                for (int k_1 = 0; k_1 < range.Length; ++k_1)
                {
                    os.WriteLong(range[k_1]).Write(' ');
                }
                os.Write(']');
                System.Array.Copy(bos.ToArray(), 0, bout, (int)byteRangePosition, bos.Length);
            }
            else
            {
                try {
                    raf = FileUtil.GetRandomAccessFile(tempFile);
                    long len = raf.Length;
                    range[range.Length - 1] = len - range[range.Length - 2];
                    MemoryStream    bos = new MemoryStream();
                    PdfOutputStream os  = new PdfOutputStream(bos);
                    os.Write('[');
                    for (int k_1 = 0; k_1 < range.Length; ++k_1)
                    {
                        os.WriteLong(range[k_1]).Write(' ');
                    }
                    os.Write(']');
                    raf.Seek(byteRangePosition);
                    raf.Write(bos.ToArray(), 0, (int)bos.Length);
                }
                catch (System.IO.IOException e) {
                    try {
                        raf.Close();
                    }
                    catch (Exception) {
                    }
                    try {
                        tempFile.Delete();
                    }
                    catch (Exception) {
                    }
                    throw;
                }
            }
        }
예제 #13
0
 public virtual void Copy(PdfPage fromPage, PdfPage toPage)
 {
     if (documentFrom != fromPage.GetDocument())
     {
         documentFrom = fromPage.GetDocument();
         formFrom     = PdfAcroForm.GetAcroForm(documentFrom, false);
     }
     if (documentTo != toPage.GetDocument())
     {
         documentTo = toPage.GetDocument();
         formTo     = PdfAcroForm.GetAcroForm(documentTo, true);
     }
     if (formFrom != null)
     {
         //duplicate AcroForm dictionary
         IList <PdfName> excludedKeys = new List <PdfName>();
         excludedKeys.Add(PdfName.Fields);
         excludedKeys.Add(PdfName.DR);
         PdfDictionary dict = formFrom.GetPdfObject().CopyTo(documentTo, excludedKeys, false);
         formTo.GetPdfObject().MergeDifferent(dict);
     }
     if (formFrom != null)
     {
         IDictionary <String, PdfFormField> fieldsFrom = formFrom.GetFormFields();
         if (fieldsFrom.Count > 0)
         {
             IDictionary <String, PdfFormField> fieldsTo = formTo.GetFormFields();
             IList <PdfAnnotation> annots = toPage.GetAnnotations();
             foreach (PdfAnnotation annot in annots)
             {
                 if (annot.GetSubtype().Equals(PdfName.Widget))
                 {
                     PdfDictionary parent = annot.GetPdfObject().GetAsDictionary(PdfName.Parent);
                     if (parent != null)
                     {
                         PdfFormField parentField = GetParentField(parent, documentTo);
                         PdfString    parentName  = parentField.GetFieldName();
                         if (parentName == null)
                         {
                             continue;
                         }
                         if (!fieldsTo.ContainsKey(parentName.ToUnicodeString()))
                         {
                             PdfFormField field = CreateParentFieldCopy(annot.GetPdfObject(), documentTo);
                             PdfArray     kids  = field.GetKids();
                             field.GetPdfObject().Remove(PdfName.Kids);
                             formTo.AddField(field, toPage);
                             field.GetPdfObject().Put(PdfName.Kids, kids);
                         }
                         else
                         {
                             PdfFormField field     = PdfFormField.MakeFormField(annot.GetPdfObject(), documentTo);
                             PdfString    fieldName = field.GetFieldName();
                             if (fieldName != null)
                             {
                                 PdfFormField existingField = fieldsTo.Get(fieldName.ToUnicodeString());
                                 if (existingField != null)
                                 {
                                     PdfFormField clonedField = PdfFormField.MakeFormField(field.GetPdfObject().Clone().MakeIndirect(documentTo
                                                                                                                                     ), documentTo);
                                     toPage.GetPdfObject().GetAsArray(PdfName.Annots).Add(clonedField.GetPdfObject());
                                     toPage.RemoveAnnotation(annot);
                                     MergeFieldsWithTheSameName(clonedField);
                                 }
                                 else
                                 {
                                     HashSet <String> existingFields = new HashSet <String>();
                                     GetAllFieldNames(formTo.GetFields(), existingFields);
                                     AddChildToExistingParent(annot.GetPdfObject(), existingFields);
                                 }
                             }
                             else
                             {
                                 if (!parentField.GetKids().Contains(field.GetPdfObject()))
                                 {
                                     HashSet <String> existingFields = new HashSet <String>();
                                     GetAllFieldNames(formTo.GetFields(), existingFields);
                                     AddChildToExistingParent(annot.GetPdfObject(), existingFields);
                                 }
                             }
                         }
                     }
                     else
                     {
                         PdfString annotName       = annot.GetPdfObject().GetAsString(PdfName.T);
                         String    annotNameString = null;
                         if (annotName != null)
                         {
                             annotNameString = annotName.ToUnicodeString();
                         }
                         if (annotNameString != null && fieldsFrom.ContainsKey(annotNameString))
                         {
                             PdfFormField field = fieldsTo.Get(annotNameString);
                             if (field != null)
                             {
                                 PdfDictionary clonedAnnot = (PdfDictionary)annot.GetPdfObject().Clone().MakeIndirect(documentTo);
                                 toPage.GetPdfObject().GetAsArray(PdfName.Annots).Add(clonedAnnot);
                                 toPage.RemoveAnnotation(annot);
                                 field = MergeFieldsWithTheSameName(PdfFormField.MakeFormField(clonedAnnot, toPage.GetDocument()));
                                 logger.Warn(MessageFormatUtil.Format(iText.IO.LogMessageConstant.DOCUMENT_ALREADY_HAS_FIELD, annotNameString
                                                                      ));
                                 PdfArray kids = field.GetKids();
                                 if (kids != null)
                                 {
                                     field.GetPdfObject().Remove(PdfName.Kids);
                                     formTo.AddField(field, toPage);
                                     field.GetPdfObject().Put(PdfName.Kids, kids);
                                 }
                                 else
                                 {
                                     formTo.AddField(field, toPage);
                                 }
                             }
                             else
                             {
                                 formTo.AddField(PdfFormField.MakeFormField(annot.GetPdfObject(), documentTo), null);
                             }
                         }
                     }
                 }
             }
         }
     }
 }
예제 #14
0
        public virtual void Copy(PdfPage fromPage, PdfPage toPage)
        {
            if (documentFrom != fromPage.GetDocument())
            {
                documentFrom = fromPage.GetDocument();
                formFrom     = PdfAcroForm.GetAcroForm(documentFrom, false);
            }
            if (documentTo != toPage.GetDocument())
            {
                documentTo = toPage.GetDocument();
                formTo     = PdfAcroForm.GetAcroForm(documentTo, true);
                if (formFrom != null)
                {
                    //duplicate AcroForm dictionary
                    IList <PdfName> excludedKeys = new List <PdfName>();
                    excludedKeys.Add(PdfName.Fields);
                    excludedKeys.Add(PdfName.DR);
                    PdfDictionary dict = formFrom.GetPdfObject().CopyTo(documentTo, excludedKeys, false);
                    formTo.GetPdfObject().MergeDifferent(dict);
                }
            }
            IList <PdfDictionary> usedParents = new List <PdfDictionary>();

            if (formFrom != null)
            {
                IDictionary <String, PdfFormField> fieldsFrom = formFrom.GetFormFields();
                if (fieldsFrom.Count > 0)
                {
                    IDictionary <String, PdfFormField> fieldsTo = formTo.GetFormFields();
                    IList <PdfAnnotation> annots = toPage.GetAnnotations();
                    foreach (PdfAnnotation annot in annots)
                    {
                        if (annot.GetSubtype().Equals(PdfName.Widget))
                        {
                            PdfDictionary parent = annot.GetPdfObject().GetAsDictionary(PdfName.Parent);
                            if (parent != null)
                            {
                                PdfString parentName = parent.GetAsString(PdfName.T);
                                if (parentName == null)
                                {
                                    continue;
                                }
                                if (!usedParents.Contains(parent))
                                {
                                    PdfFormField field = PdfFormField.MakeFormField(parent, toPage.GetDocument());
                                    field.GetKids().Clear();
                                    formTo.AddField(field, toPage);
                                    usedParents.Add(parent);
                                    field.AddKid((PdfWidgetAnnotation)annot);
                                }
                                else
                                {
                                    parent.GetAsArray(PdfName.Kids).Add(annot.GetPdfObject());
                                }
                            }
                            else
                            {
                                PdfString annotName       = annot.GetPdfObject().GetAsString(PdfName.T);
                                String    annotNameString = null;
                                if (annotName != null)
                                {
                                    annotNameString = annotName.ToUnicodeString();
                                }
                                if (annotNameString != null && fieldsFrom.ContainsKey(annotNameString))
                                {
                                    PdfFormField field = PdfFormField.MakeFormField(annot.GetPdfObject(), toPage.GetDocument());
                                    if (fieldsTo.ContainsKey(annotNameString))
                                    {
                                        field = MergeFieldsWithTheSameName(field, fieldsTo.Get(annotNameString));
                                        ILogger logger = LoggerFactory.GetLogger(typeof(PdfPageFormCopier));
                                        logger.Warn(String.Format(LogMessageConstant.DOCUMENT_ALREADY_HAS_FIELD, annotNameString));
                                    }
                                    formTo.AddField(field, null);
                                }
                            }
                        }
                    }
                }
            }
        }