mirror of
https://github.com/OpenSignLabs/OpenSign.git
synced 2026-08-21 15:12:34 +02:00
v2.12.0
feat: create duplicate template functionality feat: add support of csv and xlsx for bulk contacts import feat: add info text for forms and dashboard button feat: implement functionality to delete a PDF page while editing the document feat: show completed documents in which signers included but not owner in completed reports feat: add delete folder button in opensign drive feat: introduce Bcc email support for sending completed documents feat: allow merging multiple pdf while drafting document and template feat: add 'My Initials' tab for auto-signing in request-sign flow feat: add support for redirect URL to navigate after document completion feat: introduce privacy policy and digital signature terms before signing documents. feat: add feature to allow adding new pages to existing document feat: add save signature, initials, stamp functionality in sign pad for logged in user feat: add preferences menu feat: add save custom email template, notifyonsignature, set timezone, allow signature types in preferences feat: secure local url feat: implement Italian language translation feat: implement German language translation feat: update menu name from report to documents and shift contactbook in main menu feat: provide edit contact functionality fix: unable to delete folder when all its documents are deleted fix: fields.push is not function fix: document loading issue in opensign drive fix: adjust the guest signature flow to display the document in full screen, eliminating any blank space which is displayed below the place holder in mobile view fix: resolve issue of instance of pdfdict or pdfstream but got undefined build(deps): update dependencies refactor: change note text from add contact form
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
import {
|
||||
DEFAULT_SIGNATURE_LENGTH,
|
||||
DEFAULT_BYTE_RANGE_PLACEHOLDER,
|
||||
SUBFILTER_ADOBE_PKCS7_DETACHED,
|
||||
ANNOTATION_FLAGS,
|
||||
SIG_FLAGS,
|
||||
SignPdfError,
|
||||
} from '@signpdf/utils';
|
||||
import {
|
||||
PDFArray,
|
||||
PDFNumber,
|
||||
PDFName,
|
||||
PDFHexString,
|
||||
PDFString,
|
||||
PDFInvalidObject,
|
||||
PDFDict,
|
||||
} from 'pdf-lib';
|
||||
|
||||
export const Placeholder = ({
|
||||
pdfDoc,
|
||||
pdfPage,
|
||||
reason,
|
||||
contactInfo,
|
||||
name,
|
||||
location,
|
||||
signingTime = new Date(),
|
||||
signatureLength = DEFAULT_SIGNATURE_LENGTH,
|
||||
byteRangePlaceholder = DEFAULT_BYTE_RANGE_PLACEHOLDER,
|
||||
subFilter = SUBFILTER_ADOBE_PKCS7_DETACHED,
|
||||
widgetRect = [0, 0, 0, 0],
|
||||
appName,
|
||||
}) => {
|
||||
if (!pdfDoc && !pdfPage) {
|
||||
throw new SignPdfError('PDFDoc or PDFPage must be set.', SignPdfError.TYPE_INPUT);
|
||||
}
|
||||
|
||||
const doc = pdfDoc || pdfPage.doc;
|
||||
const page = pdfPage || doc.getPages()[0];
|
||||
|
||||
const byteRange = PDFArray.withContext(doc.context);
|
||||
byteRange.push(PDFNumber.of(0));
|
||||
byteRange.push(PDFName.of(byteRangePlaceholder));
|
||||
byteRange.push(PDFName.of(byteRangePlaceholder));
|
||||
byteRange.push(PDFName.of(byteRangePlaceholder));
|
||||
|
||||
const placeholder = PDFHexString.of(String.fromCharCode(0).repeat(signatureLength));
|
||||
|
||||
const appBuild = appName ? { App: { Name: appName } } : {};
|
||||
const signatureDict = doc.context.obj({
|
||||
Type: 'Sig',
|
||||
Filter: 'Adobe.PPKLite',
|
||||
SubFilter: subFilter,
|
||||
ByteRange: byteRange,
|
||||
Contents: placeholder,
|
||||
Reason: PDFString.of(reason),
|
||||
M: PDFString.fromDate(signingTime),
|
||||
ContactInfo: PDFString.of(contactInfo),
|
||||
Name: PDFString.of(name),
|
||||
Location: PDFString.of(location),
|
||||
Prop_Build: {
|
||||
Filter: { Name: 'Adobe.PPKLite' },
|
||||
...appBuild,
|
||||
},
|
||||
});
|
||||
|
||||
const signatureBuffer = new Uint8Array(signatureDict.sizeInBytes());
|
||||
signatureDict.copyBytesInto(signatureBuffer, 0);
|
||||
const signatureObj = PDFInvalidObject.of(signatureBuffer);
|
||||
const signatureDictRef = doc.context.register(signatureObj);
|
||||
|
||||
const rect = PDFArray.withContext(doc.context);
|
||||
widgetRect.forEach(c => rect.push(PDFNumber.of(c)));
|
||||
const apStream = doc.context.formXObject([], {
|
||||
BBox: widgetRect,
|
||||
Resources: {},
|
||||
});
|
||||
|
||||
const widgetDict = doc.context.obj({
|
||||
Type: 'Annot',
|
||||
Subtype: 'Widget',
|
||||
FT: 'Sig',
|
||||
Rect: rect,
|
||||
V: signatureDictRef,
|
||||
T: PDFString.of('Signature1'),
|
||||
F: ANNOTATION_FLAGS.PRINT,
|
||||
P: page.ref,
|
||||
AP: { N: doc.context.register(apStream) },
|
||||
});
|
||||
|
||||
const widgetDictRef = doc.context.register(widgetDict);
|
||||
|
||||
let annotations = page.node.lookupMaybe(PDFName.of('Annots'), PDFArray);
|
||||
if (!annotations) {
|
||||
annotations = doc.context.obj([]);
|
||||
}
|
||||
annotations.push(widgetDictRef);
|
||||
page.node.set(PDFName.of('Annots'), annotations);
|
||||
|
||||
let acroForm = doc.catalog.lookupMaybe(PDFName.of('AcroForm'), PDFDict);
|
||||
if (!acroForm) {
|
||||
acroForm = doc.context.obj({ Fields: [] });
|
||||
const acroFormRef = doc.context.register(acroForm);
|
||||
doc.catalog.set(PDFName.of('AcroForm'), acroFormRef);
|
||||
}
|
||||
|
||||
let sigFlags = acroForm.has(PDFName.of('SigFlags'))
|
||||
? acroForm.get(PDFName.of('SigFlags'))
|
||||
: PDFNumber.of(0);
|
||||
|
||||
const updatedFlags = PDFNumber.of(
|
||||
sigFlags.asNumber() | SIG_FLAGS.SIGNATURES_EXIST | SIG_FLAGS.APPEND_ONLY
|
||||
);
|
||||
acroForm.set(PDFName.of('SigFlags'), updatedFlags);
|
||||
|
||||
let fields = acroForm.get(PDFName.of('Fields'));
|
||||
if (fields instanceof PDFArray) {
|
||||
fields.push(widgetDictRef);
|
||||
}
|
||||
// else if (fields) {
|
||||
// const newFields = PDFArray.withContext(doc.context);
|
||||
// fields.asArray().forEach(field => newFields.push(field));
|
||||
// newFields.push(widgetDictRef);
|
||||
// acroForm.set(PDFName.of('Fields'), newFields);
|
||||
// }
|
||||
else {
|
||||
const newFields = PDFArray.withContext(doc.context);
|
||||
newFields.push(widgetDictRef);
|
||||
acroForm.set(PDFName.of('Fields'), newFields);
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user