From 44628a8474ce28394a943578734eb08664d8a85a Mon Sep 17 00:00:00 2001 From: Luiz Carlos Date: Thu, 16 Nov 2023 14:43:37 -0300 Subject: [PATCH 1/6] Custom qpdf path types --- src/encrypt.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/encrypt.ts b/src/encrypt.ts index 4385e09..4c7b91d 100644 --- a/src/encrypt.ts +++ b/src/encrypt.ts @@ -7,6 +7,8 @@ const EncryptDefaults = { }; export interface EncryptOptions { + /** Optional - Path to custom qpdf binary */ + qpdfPath?: string /** The location of the unencrypted pdf file */ input: string; /** From 1743b1a4c0f650e104e04e92cda5307ae3dd9d6c Mon Sep 17 00:00:00 2001 From: Luiz Carlos Date: Thu, 16 Nov 2023 14:50:33 -0300 Subject: [PATCH 2/6] allow custom qpdf binary --- src/decrypt.ts | 4 +++- src/encrypt.ts | 2 +- src/info.ts | 4 +++- src/spawn.ts | 6 ++++-- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/decrypt.ts b/src/decrypt.ts index e1dabec..6a39136 100644 --- a/src/decrypt.ts +++ b/src/decrypt.ts @@ -2,6 +2,8 @@ import execute from "./spawn.js"; import { fileExists } from "./utils.js"; export interface DecryptSettings { + /** Optional - Path to custom qpdf binary */ + qpdfPath?: string /** The path for the encrypted pdf */ input: string; /** The path for the decrypted pdf */ @@ -36,5 +38,5 @@ export const decrypt = async (payload: DecryptSettings): Promise => { callArguments.push("-"); } - return execute(callArguments); + return execute(callArguments, payload.qpdfPath); }; diff --git a/src/encrypt.ts b/src/encrypt.ts index 4c7b91d..d748408 100644 --- a/src/encrypt.ts +++ b/src/encrypt.ts @@ -138,5 +138,5 @@ export const encrypt = async (userPayload: EncryptOptions): Promise => { callArguments.push("-"); } // Execute command and return stdout for pipe - return execute(callArguments); + return execute(callArguments, payload.qpdfPath); }; diff --git a/src/info.ts b/src/info.ts index 2006573..38dc5f8 100644 --- a/src/info.ts +++ b/src/info.ts @@ -2,6 +2,8 @@ import execute from "./spawn.js"; import { fileExists } from "./utils.js"; export interface InfoSettings { + /** Optional - Path to custom qpdf binary */ + qpdfPath?: string /** The path for the encrypted pdf */ input: string; /** The password for the encrypted pdf */ @@ -27,7 +29,7 @@ export const info = async (payload: InfoSettings): Promise => { // Input file path callArguments.push(payload.input); - const result = await execute(callArguments); + const result = await execute(callArguments, payload.qpdfPath); return result.toLocaleString().trim(); }; diff --git a/src/spawn.ts b/src/spawn.ts index a85b1ef..a6aff4c 100644 --- a/src/spawn.ts +++ b/src/spawn.ts @@ -3,9 +3,11 @@ import { spawn } from "node:child_process"; -export default (callArguments: string[]): Promise => +export default (callArguments: string[], qpdfPath?:string): Promise => new Promise((resolve, reject) => { - const process = spawn("qpdf", callArguments); + const process = spawn(qpdfPath? "./qpdf" :"qpdf", callArguments, { + cwd: qpdfPath + }); const stdout: string[] = []; const stderr: string[] = []; process.stdout.on("data", (data) => { From 69b2e15074a360ecbd81e3f8cea5849b223ef7d5 Mon Sep 17 00:00:00 2001 From: Luiz Carlos Date: Fri, 17 Nov 2023 09:23:22 -0300 Subject: [PATCH 3/6] google cloud functions example --- README.md | 108 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 66 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index ece32e3..5593168 100644 --- a/README.md +++ b/README.md @@ -7,103 +7,127 @@ [![npm](https://img.shields.io/npm/dm/node-qpdf)](https://www.npmjs.com/package/node-qpdf2) [![qpdf 11+](https://img.shields.io/badge/dependencies-qpdf-green)](https://github.com/qpdf/qpdf) -A very simple wrapper for [qpdf](https://github.com/qpdf/qpdf) which is performs content-preserving transformations on PDF files. It includes encrypting and decrypting PDF files with AES 256, AES 128, RC4 (128 & 40) encryption algorithms. This is a fork of [nrhirani/node-qpdf](https://github.com/nrhirani/node-qpdf), adding Promises and Types, and is kept mostly up to date with `qpdf`. +A very simple wrapper for [qpdf](https://github.com/qpdf/qpdf) which performs content-preserving transformations on PDF files. It includes encrypting and decrypting PDF files with AES 256, AES 128, RC4 (128 & 40) encryption algorithms. This is a fork of [nrhirani/node-qpdf](https://github.com/nrhirani/node-qpdf), adding `Promises` and `Types``, and is kept mostly up to date with `qpdf`. ## Dependencies -- [qpdf](https://github.com/qpdf/qpdf) - - Version 11 is the minimum version for node-qpdf2 4.0+ +- [qpdf](https://github.com/qpdf/qpdf) v11.0+ ## Installation -1. Install qpdf: - - Download [qpdf](https://github.com/qpdf/qpdf/releases) -2. Install node-qpdf: - ``` - npm install node-qpdf2 - ``` +1. Install [qpdf](https://github.com/qpdf/qpdf/releases): +2. Install `node-qpdf2`: -## Serverless? +```bash + npm install node-qpdf2 + # or + yarn add node-qpdf2 +``` -This package can be uses on serverless platforms by using your vendor's layers functionality. Use the zip release from `qpdf` as the layer. For example, `qpdf-11.1.0-bin-linux-x86_64.zip` can be directly uploaded as a layer, and has been tested using Amazon Lambda. +## Serverless? -## Encryption +This package can be used on serverless platforms and has been tested on `Amazon Lambda` and `Google Cloud Functions`. -You can encrypt your PDF by following: +### Amazon Lambda +Download latest `qpdf-XX.X.X-bin-linux-x86_64.zip` release from `qpdf` then directly upload it as a [layer](https://docs.aws.amazon.com/lambda/latest/dg/chapter-layers.html). -``` -import { encrypt } from "node-qpdf2"; +### Google Cloud Functions +Download latest `qpdf-XX.X.X-bin-linux-x86_64.zip` release then extract it's content where functions entry point (generally `index.js`) is: -const pdf = { - input: "./test/example.pdf", - output: "/tmp/encrypted.pdf", - password: "1234", +```bash +# package.json +{ + ... + # entry point + "main": "build/index.js", + ... } -await encrypt(pdf); +# directory structure +/root_dir + /build + # entry point + /index.js + /other files... + # you can rename qpdf folder to whatever you want + /qpdf_dir + # zip content + /bin + /lib + /src + /index.ts + /other files... ``` -### Options for Encryption +Then provide a `qpdfPath` pointing to `bin` folder inside `qpdf` directory: +```bash +import path from "path"; -Please see [src/encrypt.ts](https://github.com/Sparticuz/node-qpdf2/blob/master/src/encrypt.ts#L9) for the latest options, as well as [QPDF's documentation](https://qpdf.readthedocs.io/en/stable/cli.html#encryption) for information on what each restriction does. +const pdf = { + qpdfPath: path.join( process.cwd(), 'qpdf_dir/bin' ), + ... other props +} +``` -### Examples +## Encryption -#### Render and Save: +You can encrypt your PDF by following: -``` +```bash import { encrypt } from "node-qpdf2"; const options = { - input: "./test/example.pdf", - keyLength: 128, - output: "/tmp/encrypted.pdf", - password: 'YOUR_PASSWORD_TO_ENCRYPT', - restrictions: { - print: 'low', - useAes: 'y' - } + input: "./test/example.pdf", + output: "/tmp/encrypted.pdf", + password: 'ENCRYPTION_PASSWORD', + restrictions: { + print: 'low', + useAes: 'y' + } } await encrypt(options); ``` +### Encryption options + +Please see [src/encrypt.ts](https://github.com/Sparticuz/node-qpdf2/blob/master/src/encrypt.ts#L9) for the all available options, as well as [qpdf's documentation](https://qpdf.readthedocs.io/en/stable/cli.html#encryption) for informations about each restriction prop. + ## Decryption You can decrypt your PDF by following: -``` +```bash import { decrypt } from "node-qpdf2"; const options = { input: "/tmp/encrypted.pdf", output: "/tmp/decrypted.pdf", - password: "YOUR_PASSWORD_TO_DECRYPT_PDF", + password: "ENCRYPTION_PASSWORD", } await decrypt(options); ``` -## PDF Encryption info +## Encryption info -You can retrieve encryption information using the info function. This function will return a Promise. See [here](https://qpdf.readthedocs.io/en/stable/cli.html#option-show-encryption) for more information. +You can retrieve encryption information using the info function. This function will return a `Promise`. See [here](https://qpdf.readthedocs.io/en/stable/cli.html#option-show-encryption) for more information. -``` +```bash import { info } from "node-qpdf2"; const options = { input: "/tmp/encrypted.pdf", - password: "FILE_PASSWORD", + password: "ENCRYPTION_PASSWORD", } console.log(await info(options)); ``` - -If the file is not encrypted, the result will be "File is not encrypted". +If file is not encrypted, the result will be `File is not encrypted`. ## Coverage -| File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s | +| File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Lines | | ---------- | ------- | -------- | ------- | ------- | ----------------- | | All files | 100 | 100 | 100 | 100 | | decrypt.ts | 100 | 100 | 100 | 100 | From e5e0d9c3d31e15ce0382e1e7b812f4d795a26413 Mon Sep 17 00:00:00 2001 From: Luiz Carlos Date: Fri, 17 Nov 2023 14:41:49 -0300 Subject: [PATCH 4/6] --allow-weak-crypto required on 128 keyLenght --- src/encrypt.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/encrypt.ts b/src/encrypt.ts index d748408..5ba6be3 100644 --- a/src/encrypt.ts +++ b/src/encrypt.ts @@ -78,9 +78,9 @@ export const encrypt = async (userPayload: EncryptOptions): Promise => { const callArguments = []; - // If the keyLength is 40, `--allow-weak-crypto` needs to be specified before `--encrypt`. + // If the keyLength is not 256, `--allow-weak-crypto` needs to be specified before `--encrypt`. // This is required for qpdf 11+. - if (payload.keyLength === 40) callArguments.push("--allow-weak-crypto"); + if (payload.keyLength !== 256) callArguments.push("--allow-weak-crypto"); callArguments.push("--encrypt"); From 39398c9dc39bacf292b4f5f6d076a3360d466f2a Mon Sep 17 00:00:00 2001 From: Luiz Carlos Date: Wed, 6 Dec 2023 13:30:48 -0300 Subject: [PATCH 5/6] fix double backtick --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5593168..b2faf05 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ [![npm](https://img.shields.io/npm/dm/node-qpdf)](https://www.npmjs.com/package/node-qpdf2) [![qpdf 11+](https://img.shields.io/badge/dependencies-qpdf-green)](https://github.com/qpdf/qpdf) -A very simple wrapper for [qpdf](https://github.com/qpdf/qpdf) which performs content-preserving transformations on PDF files. It includes encrypting and decrypting PDF files with AES 256, AES 128, RC4 (128 & 40) encryption algorithms. This is a fork of [nrhirani/node-qpdf](https://github.com/nrhirani/node-qpdf), adding `Promises` and `Types``, and is kept mostly up to date with `qpdf`. +A very simple wrapper for [qpdf](https://github.com/qpdf/qpdf) which performs content-preserving transformations on PDF files. It includes encrypting and decrypting PDF files with AES 256, AES 128, RC4 (128 & 40) encryption algorithms. This is a fork of [nrhirani/node-qpdf](https://github.com/nrhirani/node-qpdf), adding `Promises` and `Types`, and is kept mostly up to date with `qpdf`. ## Dependencies From fddb1352ebe312c63d4536cf2c8bb95abd35acb5 Mon Sep 17 00:00:00 2001 From: Luiz Carlos Date: Wed, 6 Dec 2023 13:31:06 -0300 Subject: [PATCH 6/6] revert qpdf version --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b2faf05..814b9e1 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,8 @@ A very simple wrapper for [qpdf](https://github.com/qpdf/qpdf) which performs co ## Dependencies -- [qpdf](https://github.com/qpdf/qpdf) v11.0+ +- [qpdf](https://github.com/qpdf/qpdf) + - Version 11 is the minimum version for node-qpdf2 4.0+ ## Installation