Skip to content

Commit

Permalink
Add signature field support
Browse files Browse the repository at this point in the history
  • Loading branch information
cmmcneill authored and modesty committed Apr 17, 2022
1 parent 25f8af6 commit 560efc4
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 4 deletions.
8 changes: 4 additions & 4 deletions base/shared/annotation.js
Original file line number Diff line number Diff line change
Expand Up @@ -372,10 +372,10 @@ var WidgetAnnotation = (function WidgetAnnotationClosure() {
var parent = Annotation.prototype;
Util.inherit(WidgetAnnotation, Annotation, {
isViewable: function WidgetAnnotation_isViewable() {
if (this.data.fieldType === 'Sig') {
TODO('unimplemented annotation type: Widget signature');
return false;
}
// if (this.data.fieldType === 'Sig') {
// TODO('unimplemented annotation type: Widget signature');
// return false;
// }

return parent.isViewable.call(this);
}
Expand Down
22 changes: 22 additions & 0 deletions lib/pdfanno.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,25 @@ function processFieldAttribute(jsFuncName, item) {
}
}

function setupSignature(annotation, item) {
//PDF Spec p.695: field value is signature dict if signed
let sig = annotation.get('V');
if (!sig) return;

//PDF Spec p.728: get signature information
item.Sig = {};
let name = sig.get('Name');
if (name) item.Sig.Name = name;
let time = sig.get('M');
if (time) item.Sig.M = time;
let location = sig.get('Location');
if (location) item.Sig.Location = location;
let reason = sig.get('Reason');
if (reason) item.Sig.Reason = reason;
let contactInfo = sig.get('ContactInfo');
if (contactInfo) item.Sig.ContactInfo = contactInfo;
}

//END - MQZ 9/19/2012. Helper functions to parse acroForm elements

class PDFAnno {
Expand All @@ -169,6 +188,9 @@ class PDFAnno {
else if (item.fieldType == 'Tx') {
setupFieldAttributes(annotation, item);
}
else if (item.fieldType === 'Sig') {
setupSignature(annotation, item);
}
else {
nodeUtil.p2jwarn("Unknown fieldType: ", item);
}
Expand Down
23 changes: 23 additions & 0 deletions lib/pdffield.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class PDFField {
retVal = true;
break;
case 'Ch': retVal = true; break; //drop down
case 'Sig': retVal = true; break; //signature
default:
nodeUtil.p2jwarn("Unsupported: field.fieldType of " + field.fieldType);
break;
Expand Down Expand Up @@ -222,6 +223,27 @@ class PDFField {
this.Fields.push(anData);
};

#addSignature(field) {
const anData = Object.assign({
style: 48,
T: {
Name: "signature",
TypeInfo: {}
}
}, this.#getFieldBaseData(field));

if (field.Sig) {
anData.Sig = {};
if (field.Sig.Name) anData.Sig.Name = field.Sig.Name;
if (field.Sig.M) anData.Sig.M = PDFUnit.dateToIso8601(field.Sig.M);
if (field.Sig.Location) anData.Sig.Location = field.Sig.Location;
if (field.Sig.Reason) anData.Sig.Reason = field.Sig.Reason;
if (field.Sig.ContactInfo) anData.Sig.ContactInfo = field.Sig.ContactInfo;
}

this.Fields.push(anData);
}

// public instance methods
processField() {
this.field.TI = PDFField.tabIndex++;
Expand All @@ -232,6 +254,7 @@ class PDFField {
case 'Rd': this.#addRadioButton(this.field);break;
case 'Btn':this.#addLinkButton(this.field); break;
case 'Ch': this.#addSelect(this.field); break;
case 'Sig': this.#addSignature(this.field); break;
}

this.clean();
Expand Down
23 changes: 23 additions & 0 deletions lib/pdfunit.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,29 @@ class PDFUnit {
//MQZ. 07/29/2013: if color is not in dictionary, just return -1. The caller (pdffont, pdffill) will set the actual color
return kColors.indexOf(color);
}

static dateToIso8601(date) {
// PDF spec p.160
if (date.slice(0, 2) === 'D:') { // D: prefix is optional
date = date.slice(2);
}
let tz = 'Z';
let idx = date.search(/[Z+-]/); // timezone is optional
if (idx >= 0) {
tz = date.slice(idx);
if (tz !== 'Z') { // timezone format OHH'mm'
tz = tz.slice(0, 3) + ':' + tz.slice(4, 6);
}
date = date.slice(0, idx);
}
let yr = date.slice(0, 4); // everything after year is optional
let mth = date.slice(4, 6) || '01';
let day = date.slice(6, 8) || '01';
let hr = date.slice(8, 10) || '00';
let min = date.slice(10, 12) || '00';
let sec = date.slice(12, 14) || '00';
return yr + '-' + mth + '-' + day + 'T' + hr + ':' + min + ':' + sec + tz;
}
}

module.exports = PDFUnit;
Expand Down
31 changes: 31 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,37 @@ Another supported field attributes is "required": when form author mark a field
h: 0.85
}
v2.X.X added support for the signature form element (Name: 'signature'). If the field has been signed, the 'Sig' property will be present, and will contain any of the following signature details if available:
- 'Name' - Signer's name
- 'M' - Time of signing in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format
- 'Location' - Location of signing
- 'Reason' - Reason for signing
- 'ContactInfo' - Signer's contact information
Signature example:
{
style: 48,
T: {
Name: "signature",
TypeInfo: {}
},
id: {
Id: "SignatureFormField_1",
EN: 0
},
TI: 0,
AM: 16,
x: 5.506,
y: 31.394,
w: 14.367,
h: 4.241,
Sig: {
Name: "Signer Name",
M: "2022-03-15T19:17:34-04:00"
}
}
## Text Input Field Formatter Types
v0.1.8 added text input field formatter types detection for
Expand Down

0 comments on commit 560efc4

Please sign in to comment.