Skip to content

Commit c36601c

Browse files
committed
Adjustments to support signing existing signature fields, and to support adding a signature appearance without an actual digital signature.
1 parent 5eacdaf commit c36601c

9 files changed

Lines changed: 158 additions & 55 deletions

File tree

PdfSharpCore/Drawing/IXGraphicsRenderer.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,12 @@ public interface IXGraphicsRenderer
4949
void DrawLines(XPen pen, XPoint[] points);
5050

5151
/// <summary>
52-
/// Draws a Bézier spline.
52+
/// Draws a B�zier spline.
5353
/// </summary>
5454
void DrawBezier(XPen pen, double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4);
5555

5656
/// <summary>
57-
/// Draws a series of Bézier splines.
57+
/// Draws a series of B�zier splines.
5858
/// </summary>
5959
void DrawBeziers(XPen pen, XPoint[] points);
6060

PdfSharpCore/Drawing/XForm.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
using PdfSharpCore.Drawing.Pdf;
3333
using PdfSharpCore.Pdf;
3434
using PdfSharpCore.Pdf.Advanced;
35+
using PdfSharpCore.Pdf.Filters;
3536

3637
namespace PdfSharpCore.Drawing
3738
{
@@ -177,6 +178,28 @@ protected override void Dispose(bool disposing)
177178
/// </summary>
178179
internal virtual void Finish()
179180
{
181+
if (_formState == FormState.NotATemplate || _formState == FormState.Finished)
182+
return;
183+
184+
//Debug.Assert(_formState == FormState.Created || _formState == FormState.UnderConstruction);
185+
_formState = FormState.Finished;
186+
Gfx.Dispose();
187+
Gfx = null;
188+
189+
if (PdfRenderer != null)
190+
{
191+
//pdfForm.CreateStream(PdfEncoders.RawEncoding.GetBytes(PdfRenderer.GetContent()));
192+
PdfRenderer.Close();
193+
Debug.Assert(PdfRenderer == null);
194+
195+
if (_document.Options.CompressContentStreams)
196+
{
197+
_pdfForm.Stream.Value = Filtering.FlateDecode.Encode(_pdfForm.Stream.Value, _document.Options.FlateEncodeMode);
198+
_pdfForm.Elements["/Filter"] = new PdfName("/FlateDecode");
199+
}
200+
int length = _pdfForm.Stream.Length;
201+
_pdfForm.Elements.SetInteger("/Length", length);
202+
}
180203
}
181204

182205
/// <summary>

PdfSharpCore/Drawing/XGraphics.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
// ReSharper disable RedundantNameQualifier
3838
// ReSharper disable UseNameofExpression
3939

40-
namespace PdfSharpCore.Drawing // #??? aufräumen
40+
namespace PdfSharpCore.Drawing // #??? aufr�umen
4141
{
4242
/// <summary>
4343
/// Holds information about the current state of the XGraphics object.
@@ -532,15 +532,15 @@ public void DrawLines(XPen pen, double x, double y, params double[] value)
532532

533533
// ----- DrawBezier ---------------------------------------------------------------------------
534534
/// <summary>
535-
/// Draws a Bézier spline defined by four points.
535+
/// Draws a B�zier spline defined by four points.
536536
/// </summary>
537537
public void DrawBezier(XPen pen, XPoint pt1, XPoint pt2, XPoint pt3, XPoint pt4)
538538
{
539539
DrawBezier(pen, pt1.X, pt1.Y, pt2.X, pt2.Y, pt3.X, pt3.Y, pt4.X, pt4.Y);
540540
}
541541

542542
/// <summary>
543-
/// Draws a Bézier spline defined by four points.
543+
/// Draws a B�zier spline defined by four points.
544544
/// </summary>
545545
public void DrawBezier(XPen pen, double x1, double y1, double x2, double y2,
546546
double x3, double y3, double x4, double y4)
@@ -556,7 +556,7 @@ public void DrawBezier(XPen pen, double x1, double y1, double x2, double y2,
556556
// ----- DrawBeziers --------------------------------------------------------------------------
557557

558558
/// <summary>
559-
/// Draws a series of Bézier splines from an array of points.
559+
/// Draws a series of B�zier splines from an array of points.
560560
/// </summary>
561561
public void DrawBeziers(XPen pen, XPoint[] points)
562562
{

PdfSharpCore/Pdf.AcroForms/PdfSignatureField.cs

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@ namespace PdfSharpCore.Pdf.AcroForms
3939
/// </summary>
4040
public sealed class PdfSignatureField : PdfAcroField
4141
{
42-
private bool visible;
43-
4442
public string Reason
4543
{
4644
get
@@ -69,10 +67,23 @@ public PdfItem Contents
6967
{
7068
get
7169
{
72-
return Elements.GetDictionary(Keys.V).Elements[Keys.Contents];
70+
return Elements.GetDictionary(Keys.V)?.Elements[Keys.Contents];
7371
}
7472
set
7573
{
74+
if (!Elements.ContainsKey(Keys.V))
75+
{
76+
PdfDictionary sign = new PdfDictionary(_document);
77+
sign.Elements.Add(Keys.Type, new PdfName("/Sig"));
78+
sign.Elements.Add(Keys.Filter, new PdfName("/Adobe.PPKLite"));
79+
sign.Elements.Add(Keys.SubFilter, new PdfName("/adbe.pkcs7.detached"));
80+
sign.Elements.Add(Keys.M, new PdfDate(DateTime.Now));
81+
82+
_document._irefTable.Add(sign);
83+
84+
Elements.Add(Keys.V, sign);
85+
}
86+
7687
Elements.GetDictionary(Keys.V).Elements.Add(Keys.Contents, value);
7788
}
7889
}
@@ -95,16 +106,16 @@ public PdfRectangle Rectangle
95106
{
96107
get
97108
{
98-
return (PdfRectangle)Elements[Keys.Rect];
109+
return Elements.GetRectangle(Keys.Rect);
99110
}
100111
set
101-
{
102-
Elements.Add(Keys.Rect, value);
103-
this.visible = !(value.X1 + value.X2 + value.Y1 + value.Y2 == 0);
104-
112+
{
113+
Elements[Keys.Rect] = value;
105114
}
106115
}
107116

117+
private bool IsVisible => Rectangle.X1 + Rectangle.X2 + Rectangle.Y1 + Rectangle.Y2 != 0;
118+
108119

109120
public ISignatureAppearanceHandler AppearanceHandler { get; internal set; }
110121

@@ -144,7 +155,7 @@ internal PdfSignatureField(PdfDictionary dict)
144155

145156
internal override void PrepareForSave()
146157
{
147-
if (!this.visible)
158+
if (!this.IsVisible)
148159
return;
149160

150161
if (this.AppearanceHandler == null)
@@ -181,7 +192,7 @@ internal override void PrepareForSave()
181192

182193
/// <summary>
183194
/// (Required; inheritable) The name of the signature handler to be used for
184-
/// authenticating the fields contents, such as Adobe.PPKLite, Entrust.PPKEF,
195+
/// authenticating the fields contents, such as Adobe.PPKLite, Entrust.PPKEF,
185196
/// CICI.SignIt, or VeriSign.PPKVS.
186197
/// </summary>
187198
[KeyInfo(KeyType.Name | KeyType.Required)]
@@ -229,7 +240,7 @@ internal override void PrepareForSave()
229240
public const string Location = "/Location";
230241

231242
/// <summary>
232-
/// (Optional) The reason for the signing, such as (I agree).
243+
/// (Optional) The reason for the signing, such as (I agree).
233244
/// </summary>
234245
[KeyInfo(KeyType.TextString | KeyType.Optional)]
235246
public const string Reason = "/Reason";

PdfSharpCore/Pdf.Signatures/PdfSignatureHandler.cs

Lines changed: 54 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
1-
using PdfSharpCore.Pdf;
1+
using PdfSharpCore.Drawing;
2+
using PdfSharpCore.Pdf;
23
using PdfSharpCore.Pdf.AcroForms;
34
using PdfSharpCore.Pdf.Advanced;
45
using PdfSharpCore.Pdf.Annotations;
56
using PdfSharpCore.Pdf.Signatures;
67
using System;
78
using System.Collections.Generic;
89
using System.IO;
10+
using System.Net.Security;
911
using System.Security.Cryptography.Pkcs;
1012
using System.Security.Cryptography.X509Certificates;
1113
using System.Text;
14+
using System.Xml.Linq;
1215
using static PdfSharpCore.Pdf.AcroForms.PdfAcroField;
1316

1417
namespace PdfSharpCore.Pdf.Signatures
@@ -38,24 +41,25 @@ public void AttachToDocument(PdfDocument documentToSign)
3841
this.Document.BeforeSave += AddSignatureComponents;
3942
this.Document.AfterSave += ComputeSignatureAndRange;
4043

41-
if (!maximumSignatureLength.HasValue)
44+
if (signer != null && !maximumSignatureLength.HasValue)
4245
{
4346
maximumSignatureLength = signer.GetSignedCms(new MemoryStream(new byte[] { 0})).Length;
4447
SignatureSizeComputed(this, new IntEventArgs() { Value = maximumSignatureLength.Value });
4548
}
4649
}
4750

48-
public PdfSignatureHandler(ISigner signer, int? signatureMaximumLength, PdfSignatureOptions options)
51+
public PdfSignatureHandler(ISigner signer, PdfSignatureOptions options, int? signatureMaximumLength = null)
4952
{
5053
this.signer = signer;
51-
5254

5355
this.maximumSignatureLength = signatureMaximumLength;
5456
this.Options = options;
5557
}
5658

5759
private void ComputeSignatureAndRange(object sender, PdfDocumentEventArgs e)
5860
{
61+
if (signer == null) return;
62+
5963
var writer = e.Writer;
6064
writer.Stream.Position = rangeTracker.Start;
6165
var rangeArray = new PdfArray(new PdfInteger(0),
@@ -94,7 +98,7 @@ private RangedStream GetRangeToSign(Stream stream)
9498
new RangedStream.Range(contentsTraker.End, stream.Length - contentsTraker.End)
9599
});
96100

97-
}
101+
}
98102

99103
private void AddSignatureComponents(object sender, EventArgs e)
100104
{
@@ -103,36 +107,62 @@ private void AddSignatureComponents(object sender, EventArgs e)
103107
if (catalog.AcroForm == null)
104108
catalog.AcroForm = new PdfAcroForm(Document);
105109

106-
catalog.AcroForm.Elements.Add(PdfAcroForm.Keys.SigFlags, new PdfInteger(3));
110+
if (signer != null)
111+
{
112+
if (catalog.AcroForm.Elements.ContainsKey(PdfAcroForm.Keys.SigFlags))
113+
{
114+
catalog.AcroForm.Elements.Remove(PdfAcroForm.Keys.SigFlags);
115+
}
116+
catalog.AcroForm.Elements.Add(PdfAcroForm.Keys.SigFlags, new PdfInteger(3));
117+
}
107118

108-
var signature = new PdfSignatureField(Document);
119+
PdfSignatureField signature = Options.FieldName == null ? null : catalog.AcroForm.Fields[Options.FieldName] as PdfSignatureField;
120+
bool isNew = signature == null;
109121

110-
var paddedContents = new PdfString("", PdfStringFlags.HexLiteral, maximumSignatureLength.Value);
111-
var paddedRange = new PdfArray(Document, byteRangePaddingLength, new PdfInteger(0), new PdfInteger(0), new PdfInteger(0), new PdfInteger(0));
122+
if (isNew)
123+
{
124+
signature = new PdfSignatureField(Document);
125+
signature.Elements[Keys.T] = new PdfString(Options.FieldName ?? "Signature1");
126+
}
112127

113-
signature.Contents = paddedContents;
114-
signature.ByteRange = paddedRange;
115-
signature.Reason = Options.Reason;
116-
signature.Location = Options.Location;
117-
signature.Rectangle = new PdfRectangle(Options.Rectangle);
128+
if (isNew || (Options.Rectangle != XRect.Empty && Options.Rectangle != default))
129+
{
130+
signature.Rectangle = new PdfRectangle(Options.Rectangle);
131+
}
132+
if (signer != null)
133+
{
134+
var paddedContents = new PdfString("", PdfStringFlags.HexLiteral, maximumSignatureLength.Value);
135+
var paddedRange = new PdfArray(Document, byteRangePaddingLength, new PdfInteger(0), new PdfInteger(0), new PdfInteger(0), new PdfInteger(0));
136+
137+
this.contentsTraker = new PositionTracker(paddedContents);
138+
this.rangeTracker = new PositionTracker(paddedRange);
139+
140+
signature.Contents = paddedContents;
141+
signature.ByteRange = paddedRange;
142+
signature.Reason = Options.Reason;
143+
signature.Location = Options.Location;
144+
}
145+
else
146+
{
147+
signature.Elements.Remove(Keys.V);
148+
}
118149
signature.AppearanceHandler = Options.AppearanceHandler ?? new DefaultAppearanceHandler()
119150
{
120151
Location = Options.Location,
121152
Reason = Options.Reason,
122-
Signer = signer.GetName()
153+
Signer = signer?.GetName()
123154
};
124-
signature.PrepareForSave();
155+
signature.PrepareForSave();
125156

126-
this.contentsTraker = new PositionTracker(paddedContents);
127-
this.rangeTracker = new PositionTracker(paddedRange);
128-
129-
if (!Document.Pages[0].Elements.ContainsKey(PdfPage.Keys.Annots))
130-
Document.Pages[0].Elements.Add(PdfPage.Keys.Annots, new PdfArray(Document));
157+
if (isNew)
158+
{
159+
if (!Document.Pages[0].Elements.ContainsKey(PdfPage.Keys.Annots))
160+
Document.Pages[0].Elements.Add(PdfPage.Keys.Annots, new PdfArray(Document));
131161

132-
(Document.Pages[0].Elements[PdfPage.Keys.Annots] as PdfArray).Elements.Add(signature);
133-
134-
catalog.AcroForm.Fields.Elements.Add(signature);
162+
(Document.Pages[0].Elements[PdfPage.Keys.Annots] as PdfArray).Elements.Add(signature);
135163

164+
catalog.AcroForm.Fields.Elements.Add(signature);
165+
}
136166
}
137167
}
138168
}

PdfSharpCore/Pdf.Signatures/PdfSignatureOptions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ namespace PdfSharpCore.Pdf.Signatures
77
{
88
public class PdfSignatureOptions
99
{
10+
public string FieldName { get; set; }
1011
public ISignatureAppearanceHandler AppearanceHandler { get; set; }
1112
public string ContactInfo { get; set; }
1213
public string Location { get; set; }

0 commit comments

Comments
 (0)