Skip to content

Commit

Permalink
Added support for typescript development.
Browse files Browse the repository at this point in the history
  • Loading branch information
zboris12 committed Aug 17, 2024
1 parent e1ed49d commit 1f92ca6
Show file tree
Hide file tree
Showing 8 changed files with 323 additions and 2 deletions.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,18 @@ pdfkit.loadZga(globalThis);
```
npm install zgapdfsigner
```
If using [typescript](https://www.typescriptlang.org/) for development, installation of [definitely typed for node-forge](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node-forge) is necessary.
```
npm install --save-dev @types/node-forge
```
2. Import
```js
// CommonJS Mode
const Zga = require("zgapdfsigner");
// ES Module Mode
import { default as Zga } from "zgapdfsigner";
// Typescript
import * as Zga from "zgapdfsigner";
```

## Let's sign
Expand Down
111 changes: 111 additions & 0 deletions lib/zganode.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import * as forge from "node-forge";
import * as PDFLib from "pdf-lib";
export * as forge from "node-forge";
export * as PDFLib from "pdf-lib";

export declare function u8arrToRaw(uarr: Uint8Array): string;
export declare function rawToU8arr(raw: string): Uint8Array;
export declare namespace Crypto {
enum Mode {
RC4_40,
RC4_128,
AES_128,
AES_256,
}
}
export type DSSInfo = {
certs?: Array<forge.pki.Certificate>;
ocsps?: Array<Uint8Array>;
crls?: Array<Uint8Array>;
};
export type EncryptOption = {
mode: Crypto.Mode;
permissions?: Array<string>;
userpwd?: string;
ownerpwd?: string;
pubkeys?: Array<PubKeyInfo>;
};
export type PubKeyInfo = {
c?: Array<number> | Uint8Array | ArrayBuffer | string | forge.pki.Certificate;
p?: Array<string>;
};
export type SignAreaInfo = {
x: number;
y: number;
w?: number;
h?: number;
};
export type SignTextInfo = {
text: string,
fontData?: Array<number> | Uint8Array | ArrayBuffer | string;
color?: string;
opacity?: number;
blendMode?: string;
lineHeight?: number;
size: number,
xOffset?: number;
yOffset?: number;
wMax?: number;
align?: number;
noBreaks?: string;
};
export type SignImageInfo = {
imgData: Array<number> | Uint8Array | ArrayBuffer | string;
imgType: string;
opacity?: number;
blendMode?: string;
};
export type SignDrawInfo = {
area: SignAreaInfo;
pageidx?: number | string;
/** @deprecated use imgInfo instead */
imgData?: Array<number> | Uint8Array | ArrayBuffer | string;
/** @deprecated use imgInfo instead */
imgType?: string;
imgInfo?: SignImageInfo;
textInfo?: SignTextInfo;
};
export type SignOption = {
p12cert?: Array<number> | Uint8Array | ArrayBuffer | string;
pwd?: string;
permission?: number;
reason?: string;
location?: string;
contact?: string;
signdate?: Date | TsaServiceInfo | string;
signame?: string;
drawinf?: SignDrawInfo;
ltv?: number;
debug?: boolean;
};
export type TsaServiceInfo = {
url: string;
len?: number;
headers?: Record<string, any>;
};

export declare class CertsChain {
constructor(certs?: Array<forge.pki.Certificate | forge.asn1.Asn1 | string>);
buildChain(cert: forge.pki.Certificate): Promise<boolean>;
getAllCerts(): Array<forge.pki.Certificate>;
getSignCert(): forge.pki.Certificate;
isSelfSignedCert(): boolean;
prepareDSSInf(crlOnly?: boolean): Promise<DSSInfo>;
}
export declare class PdfCryptor {
constructor(encopt: EncryptOption);
encryptPdf(pdf: PDFLib.PDFDocument | Array<number> | Uint8Array | ArrayBuffer | string, ref?: PDFLib.PDFRef): Promise<PDFLib.PDFDocument>;
encryptObject(num: number, val: PDFLib.PDFObject): void;
}
export declare class PdfSigner {
constructor(signopt: SignOption);
sign(pdf: PDFLib.PDFDocument | Array<number> | Uint8Array | ArrayBuffer | string, cypopt?: EncryptOption): Promise<Uint8Array>;
}
export declare class TsaFetcher {
constructor(inf: TsaServiceInfo);
url: string;
len: number;
getCertsChain(): CertsChain;
getToken(forP7?: boolean): forge.asn1.Asn1;
queryTsa(data?: string): Promise<string>;
}
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "zgapdfsigner",
"version": "2.6.0",
"version": "2.7.0",
"author": "zboris12",
"description": "A javascript tool to sign a pdf or set protection to a pdf in web browser, Google Apps Script and nodejs.",
"homepage": "https://github.com/zboris12/zgapdfsigner",
Expand All @@ -16,6 +16,7 @@
"main": "lib/zganode.js",
"files": [
"dist/*.min.js",
"lib/*.d.ts",
"lib/*.js"
],
"keywords": [
Expand All @@ -30,7 +31,7 @@
],
"scripts": {
"build": "./build.sh",
"test": "node test4node.js"
"test": "node test4node.js ${pfxpwd}"
},
"dependencies": {
"@pdf-lib/fontkit": "^1.1.1",
Expand Down
5 changes: 5 additions & 0 deletions test-ts/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"editor.tabSize": 2,
"editor.formatOnSave": true,
"files.eol": "\n"
}
20 changes: 20 additions & 0 deletions test-ts/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "zgapdfsigner-test-ts",
"version": "1.0.0",
"author": "zboris12",
"description": "A typescript program to test zgapdfsigner.",
"private": false,
"license": "MIT",
"main": "index.js",
"scripts": {
"build": "tsc",
"test": "node test/index.js ${pfxpwd}"
},
"dependencies": {
"zgapdfsigner": "^2.7.0"
},
"devDependencies": {
"@types/node-forge": "^1.3.11",
"typescript": "~4.9"
}
}
144 changes: 144 additions & 0 deletions test-ts/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
import * as m_fs from "node:fs";
import * as m_path from "node:path";
import * as Zga from "zgapdfsigner";

const workpath = "./";

async function sign_protect(pdfPath: string, pfxPath: string, ps: string, perm: number, imgPath?: string, txt?: string, fontPath?: string): Promise<string> {
let pdf: Buffer = m_fs.readFileSync(pdfPath);
let pfx: Buffer = m_fs.readFileSync(pfxPath);
let img: Buffer | undefined = undefined;
let imgType: string = "";
let font: Buffer | undefined = undefined;

if (perm == 1) {
console.log("\nTest signing pdf with full protection. (permission 1 and password encryption)");
} else {
console.log("\nTest signing pdf with permission " + perm);
}

if (imgPath) {
img = m_fs.readFileSync(imgPath);
imgType = m_path.extname(imgPath).slice(1);
}
if (fontPath) {
font = m_fs.readFileSync(fontPath);
}
let sopt: Zga.SignOption = {
p12cert: pfx,
pwd: ps,
permission: perm,
signdate: "1",
reason: "I have a test reason " + perm + ".",
location: "I am on the earth " + perm + ".",
contact: "zga" + perm + "@zga.com",
ltv: 1,
debug: true,
};
if (img || txt) {
sopt.drawinf = {
area: {
x: 25, // left
y: 50, // top
w: txt ? undefined : 60,
h: txt ? undefined : 100,
},
pageidx: "-",
imgInfo: img ? {
imgData: img,
imgType: imgType,
} : undefined,
textInfo: txt ? {
text: txt,
fontData: font,
color: "00f0f1",
lineHeight: 20,
size: 16,
align: 1,
wMax: 80,
yOffset: 10,
xOffset: 20,
noBreaks: "[あいうえおA-Za-z0-9]",
} : undefined,
};
}

let eopt: Zga.EncryptOption | undefined = undefined;
if (perm == 1) {
eopt = {
mode: Zga.Crypto.Mode.AES_256,
permissions: ["copy", "copy-extract", "print-high"],
userpwd: "123",
};
}

let ser: Zga.PdfSigner = new Zga.PdfSigner(sopt);
let u8dat: Uint8Array = await ser.sign(pdf, eopt);
let outPath: string = "";
if (u8dat) {
outPath = m_path.join(__dirname, workpath + "test_perm" + perm + m_path.basename(pdfPath));
m_fs.writeFileSync(outPath, u8dat);
console.log("Output file: " + outPath);
}
return outPath;
}

async function addtsa(pdfPath: string): Promise<string> {
console.log("\nTest signing pdf by a timestamp.");

let pdf: Buffer = m_fs.readFileSync(pdfPath);
let sopt: Zga.SignOption = {
signdate: "2",
reason: "I have a test reason tsa.",
location: "I am on the earth tsa.",
contact: "[email protected]",
ltv: 1,
debug: true,
};
let ser: Zga.PdfSigner = new Zga.PdfSigner(sopt);
let u8dat: Uint8Array = await ser.sign(pdf);
let outPath: string = m_path.join(__dirname, workpath + "tsa_" + m_path.basename(pdfPath));
m_fs.writeFileSync(outPath, u8dat);
console.log("Output file: " + outPath);
return outPath;
}

async function main1(angle: number): Promise<void> {
let pdfPath: string = m_path.join(__dirname, workpath + "_test" + (angle ? "_" + angle : "") + ".pdf");
let pfxPath: string = m_path.join(__dirname, workpath + "_test.pfx");
let ps: string = "";
let imgPath: string = m_path.join(__dirname, workpath + "_test.png");
let fontPath: string = m_path.join(__dirname, workpath + "_test.ttf");

if (process.argv.length > 3) {
pfxPath = process.argv[2];
ps = process.argv[3];
} else if (process.argv[2]) {
ps = process.argv[2];
}

if (!ps) {
// throw new Error("The passphrase is not specified.");
pfxPath = "";
}

if (pfxPath) {
await sign_protect(pdfPath, pfxPath, ps, 1, imgPath, "あいうえおあいうえおか\r\n\nThis is a test of text!\n", fontPath);
pdfPath = await sign_protect(pdfPath, pfxPath, ps, 2, undefined, "ありがとうご\r\n\nThis is an another test of text!\n", fontPath);
await addtsa(pdfPath);
} else {
await addtsa(pdfPath);
}

console.log("Done");
}

async function main(): Promise<void> {
let arr: Array<number> = [0, 90, 180, 270];
for (let i = 0; i < arr.length; i++) {
await main1(arr[i]);
// break;
}
}

main();
24 changes: 24 additions & 0 deletions test-ts/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"compilerOptions": {
"target": "es2015",
"module": "commonjs",
"newLine": "LF",
"declaration": true,
"sourceMap": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitThis": true,
"rootDir": "./src",
"outDir": "./test",
"typeRoots": [
"node_modules/@types"
]
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules"
]
}
7 changes: 7 additions & 0 deletions test4node.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
// ES Module Mode
// import * as m_fs from "node:fs";
// import * as m_path from "node:path";
// import { fileURLToPath } from "node:url";
// import { default as Zga } from "./lib/zganode.js";
// const __dirname = m_path.dirname(fileURLToPath(import.meta.url));

const m_fs = require("fs");
const m_path = require("path");
const Zga = require("./lib/zganode.js");
Expand Down

0 comments on commit 1f92ca6

Please sign in to comment.