Skip to content

Commit 9f6b238

Browse files
Eugene BochiloiText-CI
authored andcommitted
Refactor preClose method in PdfSigner
DEVSIX-5219 Autoported commit. Original commit hash: [2057d951f]
1 parent e7ca435 commit 9f6b238

File tree

3 files changed

+213
-50
lines changed

3 files changed

+213
-50
lines changed
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
using System.IO;
2+
using iText.Forms;
3+
using iText.Forms.Fields;
4+
using iText.IO.Source;
5+
using iText.Kernel.Geom;
6+
using iText.Kernel.Pdf;
7+
using iText.Kernel.Pdf.Annot;
8+
using iText.Test;
9+
10+
namespace iText.Signatures {
11+
public class PdfSignerUnitTest : ExtendedITextTest {
12+
[NUnit.Framework.Test]
13+
public virtual void CreateNewSignatureFormFieldInvisibleAnnotationTest() {
14+
PdfSigner signer = new PdfSigner(new PdfReader(new MemoryStream(CreateDocumentWithoutWidgetAnnotation()),
15+
new ReaderProperties().SetPassword("owner".GetBytes())), new ByteArrayOutputStream(), new StampingProperties
16+
());
17+
signer.cryptoDictionary = new PdfSignature();
18+
signer.appearance.SetPageRect(new Rectangle(100, 100, 0, 0));
19+
PdfAcroForm acroForm = PdfAcroForm.GetAcroForm(signer.document, true);
20+
signer.CreateNewSignatureFormField(acroForm, signer.fieldName);
21+
PdfFormField formField = acroForm.GetField(signer.fieldName);
22+
PdfDictionary formFieldDictionary = formField.GetPdfObject();
23+
NUnit.Framework.Assert.IsNotNull(formFieldDictionary);
24+
NUnit.Framework.Assert.IsFalse(formFieldDictionary.ContainsKey(PdfName.AP));
25+
}
26+
27+
[NUnit.Framework.Test]
28+
public virtual void CreateNewSignatureFormFieldNotInvisibleAnnotationTest() {
29+
PdfSigner signer = new PdfSigner(new PdfReader(new MemoryStream(CreateDocumentWithoutWidgetAnnotation()),
30+
new ReaderProperties().SetPassword("owner".GetBytes())), new ByteArrayOutputStream(), new StampingProperties
31+
());
32+
signer.cryptoDictionary = new PdfSignature();
33+
signer.appearance.SetPageRect(new Rectangle(100, 100, 10, 10));
34+
PdfSigFieldLock fieldLock = new PdfSigFieldLock();
35+
signer.fieldLock = fieldLock;
36+
PdfAcroForm acroForm = PdfAcroForm.GetAcroForm(signer.document, true);
37+
NUnit.Framework.Assert.AreEqual(fieldLock, signer.CreateNewSignatureFormField(acroForm, signer.fieldName));
38+
PdfFormField formField = acroForm.GetField(signer.fieldName);
39+
PdfDictionary formFieldDictionary = formField.GetPdfObject();
40+
NUnit.Framework.Assert.IsNotNull(formFieldDictionary);
41+
NUnit.Framework.Assert.IsTrue(formFieldDictionary.ContainsKey(PdfName.AP));
42+
}
43+
44+
[NUnit.Framework.Test]
45+
public virtual void PopulateExistingSignatureFormFieldInvisibleAnnotationTest() {
46+
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
47+
PdfDocument document = new PdfDocument(new PdfWriter(outputStream, new WriterProperties().SetStandardEncryption
48+
("user".GetBytes(), "owner".GetBytes(), 0, EncryptionConstants.STANDARD_ENCRYPTION_128)));
49+
document.AddNewPage();
50+
PdfWidgetAnnotation widgetAnnotation = new PdfWidgetAnnotation(new Rectangle(100, 100, 0, 0));
51+
document.GetPage(1).AddAnnotation(widgetAnnotation);
52+
document.Close();
53+
PdfSigner signer = new PdfSigner(new PdfReader(new MemoryStream(outputStream.ToArray()), new ReaderProperties
54+
().SetPassword("owner".GetBytes())), new ByteArrayOutputStream(), new StampingProperties());
55+
signer.cryptoDictionary = new PdfSignature();
56+
signer.appearance.SetPageRect(new Rectangle(100, 100, 0, 0));
57+
widgetAnnotation = (PdfWidgetAnnotation)signer.document.GetPage(1).GetAnnotations()[0];
58+
PdfAcroForm acroForm = PdfAcroForm.GetAcroForm(signer.document, true);
59+
PdfFormField formField = new PdfSignerUnitTest.ExtendedPdfSignatureFormField(widgetAnnotation, signer.document
60+
);
61+
formField.SetFieldName(signer.fieldName);
62+
acroForm.AddField(formField);
63+
signer.PopulateExistingSignatureFormField(acroForm);
64+
formField = acroForm.GetField(signer.fieldName);
65+
PdfDictionary formFieldDictionary = formField.GetPdfObject();
66+
NUnit.Framework.Assert.IsNotNull(formFieldDictionary);
67+
NUnit.Framework.Assert.IsFalse(formFieldDictionary.ContainsKey(PdfName.AP));
68+
}
69+
70+
[NUnit.Framework.Test]
71+
public virtual void PopulateExistingSignatureFormFieldNotInvisibleAnnotationTest() {
72+
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
73+
PdfDocument document = new PdfDocument(new PdfWriter(outputStream, new WriterProperties().SetStandardEncryption
74+
("user".GetBytes(), "owner".GetBytes(), 0, EncryptionConstants.STANDARD_ENCRYPTION_128)));
75+
document.AddNewPage();
76+
PdfWidgetAnnotation widgetAnnotation = new PdfWidgetAnnotation(new Rectangle(100, 100, 0, 0));
77+
document.GetPage(1).AddAnnotation(widgetAnnotation);
78+
document.Close();
79+
PdfSigner signer = new PdfSigner(new PdfReader(new MemoryStream(outputStream.ToArray()), new ReaderProperties
80+
().SetPassword("owner".GetBytes())), new ByteArrayOutputStream(), new StampingProperties());
81+
signer.cryptoDictionary = new PdfSignature();
82+
PdfSigFieldLock fieldLock = new PdfSigFieldLock();
83+
signer.fieldLock = fieldLock;
84+
signer.appearance.SetPageRect(new Rectangle(100, 100, 10, 10));
85+
widgetAnnotation = (PdfWidgetAnnotation)signer.document.GetPage(1).GetAnnotations()[0];
86+
PdfAcroForm acroForm = PdfAcroForm.GetAcroForm(signer.document, true);
87+
PdfFormField formField = new PdfSignerUnitTest.ExtendedPdfSignatureFormField(widgetAnnotation, signer.document
88+
);
89+
formField.SetFieldName(signer.fieldName);
90+
acroForm.AddField(formField);
91+
NUnit.Framework.Assert.AreEqual(signer.PopulateExistingSignatureFormField(acroForm), fieldLock);
92+
formField = acroForm.GetField(signer.fieldName);
93+
PdfDictionary formFieldDictionary = formField.GetPdfObject();
94+
NUnit.Framework.Assert.IsNotNull(formFieldDictionary);
95+
NUnit.Framework.Assert.IsTrue(formFieldDictionary.ContainsKey(PdfName.AP));
96+
}
97+
98+
private static byte[] CreateDocumentWithoutWidgetAnnotation() {
99+
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
100+
PdfDocument document = new PdfDocument(new PdfWriter(outputStream, new WriterProperties().SetStandardEncryption
101+
("user".GetBytes(), "owner".GetBytes(), 0, EncryptionConstants.STANDARD_ENCRYPTION_128)));
102+
document.AddNewPage();
103+
document.Close();
104+
return outputStream.ToArray();
105+
}
106+
107+
internal class ExtendedPdfSignatureFormField : PdfSignatureFormField {
108+
public ExtendedPdfSignatureFormField(PdfWidgetAnnotation widgetAnnotation, PdfDocument document)
109+
: base(widgetAnnotation, document) {
110+
}
111+
}
112+
}
113+
}

itext/itext.sign/itext/signatures/PdfSigner.cs

Lines changed: 99 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -763,57 +763,10 @@ protected internal virtual void PreClose(IDictionary<PdfName, int?> exclusionSiz
763763
}
764764
cryptoDictionary.GetPdfObject().MakeIndirect(document);
765765
if (fieldExist) {
766-
PdfSignatureFormField sigField = (PdfSignatureFormField)acroForm.GetField(fieldName);
767-
sigField.Put(PdfName.V, cryptoDictionary.GetPdfObject());
768-
fieldLock = sigField.GetSigFieldLockDictionary();
769-
if (fieldLock == null && this.fieldLock != null) {
770-
this.fieldLock.GetPdfObject().MakeIndirect(document);
771-
sigField.Put(PdfName.Lock, this.fieldLock.GetPdfObject());
772-
fieldLock = this.fieldLock;
773-
}
774-
sigField.Put(PdfName.P, document.GetPage(appearance.GetPageNumber()).GetPdfObject());
775-
sigField.Put(PdfName.V, cryptoDictionary.GetPdfObject());
776-
PdfObject obj = sigField.GetPdfObject().Get(PdfName.F);
777-
int flags = 0;
778-
if (obj != null && obj.IsNumber()) {
779-
flags = ((PdfNumber)obj).IntValue();
780-
}
781-
flags |= PdfAnnotation.LOCKED;
782-
sigField.Put(PdfName.F, new PdfNumber(flags));
783-
PdfDictionary ap = new PdfDictionary();
784-
ap.Put(PdfName.N, appearance.GetAppearance().GetPdfObject());
785-
sigField.Put(PdfName.AP, ap);
786-
sigField.SetModified();
766+
fieldLock = PopulateExistingSignatureFormField(acroForm);
787767
}
788768
else {
789-
PdfWidgetAnnotation widget = new PdfWidgetAnnotation(appearance.GetPageRect());
790-
widget.SetFlags(PdfAnnotation.PRINT | PdfAnnotation.LOCKED);
791-
PdfSignatureFormField sigField = PdfFormField.CreateSignature(document);
792-
sigField.SetFieldName(name);
793-
sigField.Put(PdfName.V, cryptoDictionary.GetPdfObject());
794-
sigField.AddKid(widget);
795-
if (this.fieldLock != null) {
796-
this.fieldLock.GetPdfObject().MakeIndirect(document);
797-
sigField.Put(PdfName.Lock, this.fieldLock.GetPdfObject());
798-
fieldLock = this.fieldLock;
799-
}
800-
int pagen = appearance.GetPageNumber();
801-
widget.SetPage(document.GetPage(pagen));
802-
PdfDictionary ap = widget.GetAppearanceDictionary();
803-
if (ap == null) {
804-
ap = new PdfDictionary();
805-
widget.Put(PdfName.AP, ap);
806-
}
807-
ap.Put(PdfName.N, appearance.GetAppearance().GetPdfObject());
808-
acroForm.AddField(sigField, document.GetPage(pagen));
809-
if (acroForm.GetPdfObject().IsIndirect()) {
810-
acroForm.SetModified();
811-
}
812-
else {
813-
//Acroform dictionary is a Direct dictionary,
814-
//for proper flushing, catalog needs to be marked as modified
815-
document.GetCatalog().SetModified();
816-
}
769+
fieldLock = CreateNewSignatureFormField(acroForm, name);
817770
}
818771
exclusionLocations = new Dictionary<PdfName, PdfLiteral>();
819772
PdfLiteral lit = new PdfLiteral(80);
@@ -899,6 +852,103 @@ protected internal virtual void PreClose(IDictionary<PdfName, int?> exclusionSiz
899852
}
900853
}
901854

855+
/// <summary>Populates already existing signature form field in the acroForm object.</summary>
856+
/// <remarks>
857+
/// Populates already existing signature form field in the acroForm object.
858+
/// This method is called during the
859+
/// <see cref="PreClose(System.Collections.Generic.IDictionary{K, V})"/>
860+
/// method if the signature field already exists.
861+
/// </remarks>
862+
/// <param name="acroForm">
863+
///
864+
/// <see cref="iText.Forms.PdfAcroForm"/>
865+
/// object in which the signature field will be populated
866+
/// </param>
867+
/// <returns>signature field lock dictionary</returns>
868+
protected internal virtual PdfSigFieldLock PopulateExistingSignatureFormField(PdfAcroForm acroForm) {
869+
PdfSignatureFormField sigField = (PdfSignatureFormField)acroForm.GetField(fieldName);
870+
sigField.Put(PdfName.V, cryptoDictionary.GetPdfObject());
871+
PdfSigFieldLock sigFieldLock = sigField.GetSigFieldLockDictionary();
872+
if (sigFieldLock == null && this.fieldLock != null) {
873+
this.fieldLock.GetPdfObject().MakeIndirect(document);
874+
sigField.Put(PdfName.Lock, this.fieldLock.GetPdfObject());
875+
sigFieldLock = this.fieldLock;
876+
}
877+
sigField.Put(PdfName.P, document.GetPage(appearance.GetPageNumber()).GetPdfObject());
878+
sigField.Put(PdfName.V, cryptoDictionary.GetPdfObject());
879+
PdfObject obj = sigField.GetPdfObject().Get(PdfName.F);
880+
int flags = 0;
881+
if (obj != null && obj.IsNumber()) {
882+
flags = ((PdfNumber)obj).IntValue();
883+
}
884+
flags |= PdfAnnotation.LOCKED;
885+
sigField.Put(PdfName.F, new PdfNumber(flags));
886+
if (appearance.IsInvisible()) {
887+
// According to the spec, appearance stream is not required if the width and height of the rectangle are 0
888+
sigField.Remove(PdfName.AP);
889+
}
890+
else {
891+
PdfDictionary ap = new PdfDictionary();
892+
ap.Put(PdfName.N, appearance.GetAppearance().GetPdfObject());
893+
sigField.Put(PdfName.AP, ap);
894+
}
895+
sigField.SetModified();
896+
return sigFieldLock;
897+
}
898+
899+
/// <summary>Creates new signature form field and adds it to the acroForm object.</summary>
900+
/// <remarks>
901+
/// Creates new signature form field and adds it to the acroForm object.
902+
/// This method is called during the
903+
/// <see cref="PreClose(System.Collections.Generic.IDictionary{K, V})"/>
904+
/// method if the signature field doesn't exist.
905+
/// </remarks>
906+
/// <param name="acroForm">
907+
///
908+
/// <see cref="iText.Forms.PdfAcroForm"/>
909+
/// object in which new signature field will be added
910+
/// </param>
911+
/// <param name="name">the name of the field</param>
912+
/// <returns>signature field lock dictionary</returns>
913+
protected internal virtual PdfSigFieldLock CreateNewSignatureFormField(PdfAcroForm acroForm, String name) {
914+
PdfWidgetAnnotation widget = new PdfWidgetAnnotation(appearance.GetPageRect());
915+
widget.SetFlags(PdfAnnotation.PRINT | PdfAnnotation.LOCKED);
916+
PdfSignatureFormField sigField = PdfFormField.CreateSignature(document);
917+
sigField.SetFieldName(name);
918+
sigField.Put(PdfName.V, cryptoDictionary.GetPdfObject());
919+
sigField.AddKid(widget);
920+
PdfSigFieldLock sigFieldLock = sigField.GetSigFieldLockDictionary();
921+
if (this.fieldLock != null) {
922+
this.fieldLock.GetPdfObject().MakeIndirect(document);
923+
sigField.Put(PdfName.Lock, this.fieldLock.GetPdfObject());
924+
sigFieldLock = this.fieldLock;
925+
}
926+
int pagen = appearance.GetPageNumber();
927+
widget.SetPage(document.GetPage(pagen));
928+
if (appearance.IsInvisible()) {
929+
// According to the spec, appearance stream is not required if the width and height of the rectangle are 0
930+
widget.Remove(PdfName.AP);
931+
}
932+
else {
933+
PdfDictionary ap = widget.GetAppearanceDictionary();
934+
if (ap == null) {
935+
ap = new PdfDictionary();
936+
widget.Put(PdfName.AP, ap);
937+
}
938+
ap.Put(PdfName.N, appearance.GetAppearance().GetPdfObject());
939+
}
940+
acroForm.AddField(sigField, document.GetPage(pagen));
941+
if (acroForm.GetPdfObject().IsIndirect()) {
942+
acroForm.SetModified();
943+
}
944+
else {
945+
//Acroform dictionary is a Direct dictionary,
946+
//for proper flushing, catalog needs to be marked as modified
947+
document.GetCatalog().SetModified();
948+
}
949+
return sigFieldLock;
950+
}
951+
902952
/// <summary>Gets the document bytes that are hashable when using external signatures.</summary>
903953
/// <remarks>
904954
/// Gets the document bytes that are hashable when using external signatures.

port-hash

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
31060776b57cde331fa8a0e0b01145bad3c812a7
1+
2057d951fca6af05b48ea8dbc93e75330e8183e3

0 commit comments

Comments
 (0)