// import { PDFName, PDFPage, PDFString, PDFDocument, PDFImage } from "pdf-lib"; import { nopodofo as npdf, NPDFImageFormat } from "nopodofo"; import { PdfData } from "pdfdataextract"; import { config } from "./config"; import { IGetMetaResponse } from "./types"; import { verifyPDF } from "./lib"; import { formatPdfTime } from "./lib/timeUtils"; import { AppError, GeneralError } from "./lib/errors"; import { isPDF } from "./lib/generalUtils"; import { getSignatureField, pdf, sign, TimestampAndEnableLTV, write, } from "./utils"; import axios from "axios"; import { createWriterToModify, PDFPageModifier, PDFRStreamForBuffer, PDFWStreamForBuffer, } from "hummus"; import Stream from "pdf-lib/cjs/core/streams/Stream"; import { asPDFName, degrees, drawImage, drawRectangle, drawText, PDFContentStream, PDFDocument, PDFName, PDFOperator, PDFOperatorNames, PDFPage, PDFString, popGraphicsState, pushGraphicsState, rgb, rotateDegrees, translate, } from "pdf-lib"; const { Readable } = require("stream"); const streams = require("memory-streams"); import signer from "node-signpdf"; import fs from "fs"; import { PDFNet } from "@pdftron/pdfnet-node"; // const { PDFNet } = require("@pdftron/pdfnet-node"); type SealCoords = { [key: string]: { x: string; y: string }; }; class PDFparser { readonly document; readonly config; constructor(document: Buffer) { this.document = document; this.config = config; } getPDFMeta = async (): Promise<IGetMetaResponse> => { if (!(this.document instanceof Buffer)) { throw new AppError("Document is not Buffer"); } if (!isPDF(this.document)) { throw new AppError("Only pdf file type is supported"); } try { const signaturesMeta = await verifyPDF(this.document); const pdfMeta = await PdfData.extract(this.document, config); const result = { pages: pdfMeta.pages, title: pdfMeta.info.Title || "Unknown", author: pdfMeta.info.Author || "Unknown", creation_date: formatPdfTime(pdfMeta.info.CreationDate), mod_date: formatPdfTime(pdfMeta.info.ModDate), }; if (signaturesMeta) { result["signatures"] = signaturesMeta.signatures; result["expired"] = signaturesMeta.expired; } return result; } catch (error) { throw new GeneralError(error); } }; insertQrCode = async ( imgBytes: ArrayBuffer, url: string, coords: SealCoords, scaleFactor: number ): Promise<ArrayBuffer> => { // tron pdf library start // PDFNet.initialize(licenseKey); await PDFNet.initialize( "demo:1652778685773:7b893c000300000000b9c455b21b7b47780dc82f9ef63ddc54ce5c282b" ); const input_path = `${__dirname}`; // try { // const doc = await PDFNet.PDFDoc.createFromBuffer(this.document); // doc.initSecurityHandler(); // const approval_signature_field = await doc.createDigitalSignatureField( // "PDFTronApprovalSig" // ); // const widgetAnnotApproval = // await PDFNet.SignatureWidget.createWithDigitalSignatureField( // doc, // new PDFNet.Rect(300, 287, 376, 306), // approval_signature_field // ); // const page1 = await doc.getPage(1); // await page1.annotPushBack(widgetAnnotApproval); // await doc.save( // output_path + "abc.pdf", // PDFNet.SDFDoc.SaveOptions.e_remove_unused // ); // } catch (err) { // console.log(err); // } const buf = await TimestampAndEnableLTV( this.document, `${__dirname}/GlobalSignRootForTST.cer`, imgBytes ); return buf; // try { // if ( // !(await TimestampAndEnableLTV( // this.document, // input_path + "GlobalSignRootForTST.cer", // input_path + "qrcode.png", // output_path + "abc_LTV.pdf" // )) // ) { // console.log("fail"); // } // } catch (error) { // console.log(error); // } // tron pdf library end // lib-pdf signature start // const pdfDoc = await PDFDocument.load(this.document); // const pdfLibSigImg = await pdfDoc.embedPng(imgBytes); // const pdfLibSigImgName = "PDF_LIB_SIG_IMG"; // const form = pdfDoc.getForm(); // const sig = form.getSignature("Signature1"); // sig.acroField.getWidgets().forEach((widget) => { // const { context } = widget.dict; // const { width, height } = widget.getRectangle(); // const appearance = [ // ...drawRectangle({ // x: 100, // y: 0, // width, // height, // borderWidth: 1, // color: rgb(1, 0, 0), // borderColor: rgb(1, 0.5, 0.75), // rotate: degrees(0), // xSkew: degrees(0), // ySkew: degrees(0), // }), // ...drawImage(pdfLibSigImgName, { // x: 100, // y: 5, // width: width - 10, // height: height - 10, // rotate: degrees(0), // xSkew: degrees(0), // ySkew: degrees(0), // }), // ]; // const stream = context.formXObject(appearance, { // Resources: { XObject: { [pdfLibSigImgName]: pdfLibSigImg.ref } }, // BBox: context.obj([0, 0, width, height]), // Matrix: context.obj([1, 0, 0, 1, 0, 0]), // }); // const streamRef = context.register(stream); // widget.setNormalAppearance(streamRef); // }); // const pdfBytes = await pdfDoc.save(); // const signatureAppearanceStreamRef = this.imageAppearanceStream(); // pdfDoc.context.obj({ // Type: "Annot", // Subtype: "Widget", // FT: "Sig", // Rect: [image.width, image.height, 0, 0], // V: signatureDictRef, // T: PDFString.of("Signature1"), // F: 4, // P: pages[pages.length - 1].ref, //lastPage // AP: pdfDoc.context.obj({ N: signatureAppearanceStreamRef }), // }); // for (let index = 0; index < pages.length; index++) { // const page = pages[index]; // const x = // typeof coords[index + 1] !== "undefined" // ? parseFloat(coords[index + 1].x) // : null; // const y = // typeof coords[index + 1] !== "undefined" // ? parseFloat(coords[index + 1].y) // : null; // if (x && y) { // page.drawImage(img, { // x, // y, // width: scaled.width, // height: scaled.height, // }); // const link = this.createPageLinkAnnotation(page, url, { // imgXPos: x, // imgYPos: y, // imgWidth: scaled.width, // imagHeight: scaled.height, // }); // page.node.set(PDFName.of("Annots"), pdfDoc.context.obj([link])); // } // } // const pdfBytes = await pdfDoc.save(); //lib-pdf end //HUMMUS lib start // const result = new PDFWStreamForBuffer(); // const pdfWriter = createWriterToModify( // new PDFRStreamForBuffer(Buffer.from(this.document)), // result // ); // const imageOptions = { // transformation: [0.5, 0, 0, 0.5, 0, 0], // index: 1000, // }; // const pageModifier = new PDFPageModifier(pdfWriter, 0); // pageModifier // .startContext() // .getContext() // .drawImage(0, 100, __dirname + "/qrcode.png", imageOptions); // pageModifier.endContext().writePage(); // pdfWriter.end(); //HUMMUS lib end //qrcode as a signature nopodofo pdf lib start // const pdfDoc = await pdf(this.document); // const field = getSignatureField(pdfDoc); // const signer = new npdf.Signer(pdfDoc); // signer.signatureField = field; // const result = await sign(signer); //qrcode as a signature nopodofo pdf lib end // return result; // return pdfBytes; // return result; //node signer //node signer }; private createPageLinkAnnotation = ( page: PDFPage, uri: string, { imgXPos, imgYPos, imgWidth, imagHeight } ) => page.doc.context.register( page.doc.context.obj({ Type: "Annot", Subtype: "Link", Rect: [imgXPos, imgYPos, imgXPos + imgWidth, imgYPos + imagHeight], A: { Type: "Action", S: "URI", URI: PDFString.of(uri), }, }) ); // imageAppearanceStream(image, rotation, width, height) { // const dict = image.doc.context.obj({ // Type: "XObject", // Subtype: "Form", // FormType: 1, // BBox: [0, 0, width, height], // Resources: { XObject: { Image: image.ref } }, // }); // const operators = [ // rotateDegrees(rotation), // translate(0, rotation % 90 === 0 ? -width : 0), // ...drawImage("Image", { // x: 0, // y: width, //y = 0 is width for me // width: width, // height: height, // rotate: degrees(0), // xSkew: degrees(0), // ySkew: degrees(0), // }), // ]; // const stream = PDFContentStream.of(dict, operators, false); // return image.doc.context.register(stream); // } } export default PDFparser;