Skip to content

Commit

Permalink
Working on LTV, Completeness is 90%.
Browse files Browse the repository at this point in the history
  • Loading branch information
zboris12 committed Nov 14, 2022
1 parent 3f0dd0a commit dd52e4e
Show file tree
Hide file tree
Showing 11 changed files with 479 additions and 208 deletions.
2 changes: 2 additions & 0 deletions .env.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
java="C:\java8\jre\bin\java.exe"
closure="C:\closure-compiler\closure-compiler-v20220104.jar"
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
<div align="center"><img src="logo.png" title="zgapdfsigner"></div>

# ZgaPdfSigner
A javascript tool to sign a pdf or set protection of a pdf in web browser.
And it also can be used in Google Apps Script and nodejs.
Expand Down
180 changes: 180 additions & 0 deletions closure.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
const m_fs = require("fs");
const m_path = require("path");
const m_cp = require("child_process");

/** @const {string} */
const m_libpath = "lib/";
/** @const {string} */
const m_distpath = "dist/_";
/** @const {Array<string>} */
const m_targets = ["zgacertsutil.js", "zgapdfcryptor.js", "zgapdfsigner.js", "zgaindex.js"];
/** @const {Array<string>} */
const m_dists = [];

/**
* @param {string} raw
* @return {Uint8Array}
*/
function rawToU8arr(raw){
/** @type {Uint8Array} */
var arr = new Uint8Array(raw.length);
for(var i=0; i<raw.length; i++){
arr[i] = raw.charCodeAt(i);
}
return arr;
}
/** @const {number} */
const m_repcode = "*".charCodeAt(0);
/** @const {Uint8Array} */
const m_cprbufst = rawToU8arr("//Only for nodejs Start");
/** @const {number} */
const m_repidxst = 1;
/** @const {Uint8Array} */
const m_cprbufed = rawToU8arr("Only for nodejs End//");
/** @const {number} */
const m_repidxed = 19;

/** @type {boolean} */
var m_debug = false;

/**
* @param {Uint8Array} tgtbuf
* @param {number} idx
* @param {Uint8Array} cprbuf
* @return {boolean}
*/
function sameBuffer(tgtbuf, idx, cprbuf){
for(var i=0; i<cprbuf.length; i++,idx++){
if(idx >= tgtbuf.length){
return false;
}else if(tgtbuf[idx] != cprbuf[i]){
return false;
}
}
return true;
}

/**
* @param {string} js
*/
function fixjs(js){
/** @type {string} */
var jspath = m_path.join(__dirname, m_libpath + js);
/** @type {Buffer} */
var jsbuf = m_fs.readFileSync(jspath);
for(var i=0; i<jsbuf.length; i++){
if(sameBuffer(jsbuf, i, m_cprbufst)){
jsbuf[i + m_repidxst] = m_repcode;
}else if(sameBuffer(jsbuf, i, m_cprbufed)){
jsbuf[i + m_repidxed] = m_repcode;
}
}

jspath = m_distpath + js;
m_dists.push(jspath);

jspath = m_path.join(__dirname, jspath);
m_fs.writeFileSync(jspath, jsbuf);
if(m_debug){
console.log("Output file: " + jspath);
}
}
/**
* @param {string} js
*/
function deltmpjs(js){
/** @type {string} */
var jspath = m_path.join(__dirname, js);
m_fs.rmSync(jspath);
if(m_debug){
console.log("Deleted file: " + jspath);
}
}

/**
* @param {envfil}
* @return {Object<string, string>}
*/
function loadEnv(envfil){
/** @type {Object<string, string>} */
var retobj = {};
/** @type {string} */
var envpath = m_path.join(__dirname, envfil);
/** @type {Array<string>} */
var envs = m_fs.readFileSync(envpath, "utf8").split("\n");
envs.forEach(function(/** @type {string} */a_env){
a_env = a_env.trimStart();
if(a_env.charAt(0) != "#"){
var a_idx = a_env.indexOf("=");
if(a_idx > 0){
retobj[a_env.substring(0, a_idx)] = a_env.substring(a_idx + 1);
}
}
});
if(m_debug){
console.log("Environment:");
console.log(retobj);
}
return retobj;
}

function main(){
if(process.argv.indexOf("-debug") > 0){
m_debug = true;
}

/** @type {Object<string, string>} */
var env = loadEnv(".env");

/** @type {boolean} */
var flg = true;
if(!env.java){
console.error("Can't find java's execution path in .env file.");
flg = false;
}
if(!env.closure){
console.error("Can't find closure complier's path in .env file.");
flg = false;
}
if(!flg){
return;
}

m_targets.forEach(fixjs);

/** @type {Array<string>} */
var cmd = [env.java];
cmd.push("-jar " + env.closure);
cmd.push("--charset UTF-8");
cmd.push("--compilation_level SIMPLE_OPTIMIZATIONS");
cmd.push("--warning_level VERBOSE");
cmd.push("--externs closure/google-ext.js");
cmd.push("--externs closure/forge-ext.js");
cmd.push("--externs closure/pdflib-ext.js");
cmd.push("--externs closure/zb-externs.js");
m_dists.forEach(function(a_js){
cmd.push("--js " + a_js);
});
cmd.push("--js_output_file dist/zgapdfsigner.min.js");
if(m_debug){
console.log(cmd.join(" "));
}

console.log("Excuting google closure compiler...\n");
m_cp.exec(cmd.join(" "), function(a_err, a_stdout, a_stderr){
const a_rex = new RegExp("^" + m_distpath, "g");
// if(a_err){
// console.log(a_err);
// }
if(a_stdout){
console.log(a_stdout.replaceAll(a_rex, m_libpath));
}
if(a_stderr){
console.log(a_stderr.replaceAll(a_rex, m_libpath));
}
m_dists.forEach(deltmpjs);
console.log("Done");
});
}

main();
9 changes: 9 additions & 0 deletions closure/zb-externs.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,11 @@ Zga.PdfCryptor = function(encopt){};
* @return {Promise<PDFLib.PDFDocument>}
*/
Zga.PdfCryptor.prototype.encryptPdf = function(pdf, ref){};
/**
* @param {number} num
* @param {PDFLib.PDFObject} val
*/
Zga.PdfCryptor.prototype.encryptObject = function(num, val){};
/**
* @constructor
* @param {Array<forge_cert|forge.asn1|string>=} certs
Expand Down Expand Up @@ -198,6 +203,10 @@ Zga.CertsChain.prototype.prepareDSSInf = function(crlOnly){};
* @param {TsaServiceInfo} inf
*/
Zga.TsaFetcher = function(inf){};
/** @type {string} */
Zga.TsaFetcher.prototype.url;
/** @type {number} */
Zga.TsaFetcher.prototype.len;
/**
* @param {string=} data
* @return {Promise<string>}
Expand Down
6 changes: 4 additions & 2 deletions lib/zgacertsutil.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use strict';

/**
* @param {Object<string, *>} z
*/
Expand Down Expand Up @@ -877,9 +879,9 @@ z.TsaFetcher = class{
this.asnc = forge.asn1.Class;
/** @private @lends {forge.asn1.Type} */
this.asnt = forge.asn1.Type;
/** @private @type {string} */
/** @public @type {string} */
this.url = inf.url;
/** @private @type {number} */
/** @public @type {number} */
this.len = inf.len ? inf.len : 0;
/** @private @type {Object<string, *>|undefined} */
this.headers = inf.headers;
Expand Down
18 changes: 13 additions & 5 deletions lib/zgaindex.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use strict';

/**
* @return {Object<string, *>}
*/
Expand Down Expand Up @@ -59,11 +61,17 @@ function genZga(){
return z;
}

//Only for nodejs Start//
if(typeof exports === "object" && typeof module !== "undefined"){
module.exports = genZga();
}else if(!globalThis.Zga){
globalThis.Zga = genZga();
supplyZgaCertsChain(globalThis.Zga);
supplyZgaCryptor(globalThis.Zga);
supplyZgaSigner(globalThis.Zga);
}else{
//Only for nodejs End//
if(!globalThis.Zga){
globalThis.Zga = genZga();
supplyZgaCertsChain(globalThis.Zga);
supplyZgaCryptor(globalThis.Zga);
supplyZgaSigner(globalThis.Zga);
}
//Only for nodejs Start//
}
//Only for nodejs End//
82 changes: 45 additions & 37 deletions lib/zgapdfcryptor.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use strict';

// This module was migrated from [TCPDF](http://www.tcpdf.org)
/**
* @param {Object<string, *>} z
Expand Down Expand Up @@ -428,6 +430,8 @@ z.PdfCryptor = class{
* @return {Promise<PDFLib.PDFDocument>}
*/
async encryptPdf(pdf, ref){
/** @const {z.PdfCryptor} */
const _this = this;
/** @type {PDFLib.PDFDocument} */
var pdfdoc = await z.loadPdf(pdf);
if(pdfdoc === pdf && !ref){
Expand All @@ -437,45 +441,10 @@ z.PdfCryptor = class{
/** @type {PDFLib.PDFContext} */
var pdfcont = pdfdoc.context;
/** @type {PDFLib.PDFObject} */
var trobj = this.prepareEncrypt(pdfcont);
var trobj = _this.prepareEncrypt(pdfcont);

/**
* @param {number} a_num
* @param {PDFLib.PDFObject} a_val
*/
var func = function(a_num, a_val){
if(a_val instanceof PDFLib.PDFContentStream){
/** @type {Uint8Array} */
var a_dat = a_val.contentsCache.access();
if(a_dat){
a_val.contentsCache.value = this.encryptU8arr(a_num, a_dat);
}
}else if(a_val instanceof PDFLib.PDFStream){
if(a_val.contents){
a_val.contents = this.encryptU8arr(a_num, a_val.contents);
}
}else if(a_val instanceof PDFLib.PDFHexString){
if(a_val.value){
a_val.value = this.encryptHexstr(a_num, a_val.value);
}
}else if(a_val instanceof PDFLib.PDFString){
if(a_val.value){
a_val.value = z.Crypto._escape(this._encrypt_data(a_num, a_val.value));
}
}
if(a_val.dict instanceof Map){
/** @type {Iterator} */
var a_es = a_val.dict.entries();
/** @type {IIterableResult<PdfObjEntry>} */
var a_res = a_es.next();
while(!a_res.done){
func(a_num, a_res.value[1]);
a_res = a_es.next();
}
}
}.bind(this);
pdfcont.enumerateIndirectObjects().forEach(function(/** @type {PdfObjEntry} */a_arr){
func(a_arr[0].objectNumber, a_arr[1]);
_this.encryptObject(a_arr[0].objectNumber, a_arr[1]);
});

if(ref){
Expand All @@ -488,6 +457,43 @@ z.PdfCryptor = class{
return pdfdoc;
}

/**
* @public
* @param {number} num
* @param {PDFLib.PDFObject} val
*/
encryptObject(num, val){
if(val instanceof PDFLib.PDFContentStream){
/** @type {Uint8Array} */
var dat = val.contentsCache.access();
if(dat){
val.contentsCache.value = this.encryptU8arr(num, dat);
}
}else if(val instanceof PDFLib.PDFStream){
if(val.contents){
val.contents = this.encryptU8arr(num, val.contents);
}
}else if(val instanceof PDFLib.PDFHexString){
if(val.value){
val.value = this.encryptHexstr(num, val.value);
}
}else if(val instanceof PDFLib.PDFString){
if(val.value){
val.value = z.Crypto._escape(this._encrypt_data(num, val.value));
}
}
if(val.dict instanceof Map){
/** @type {Iterator} */
var es = val.dict.entries();
/** @type {IIterableResult<PdfObjEntry>} */
var res = es.next();
while(!res.done){
this.encryptObject(num, res.value[1]);
res = es.next();
}
}
}

/**
* Prepare for encryption and create the object for saving in trailer.
*
Expand Down Expand Up @@ -955,6 +961,8 @@ z.PdfCryptor = class{

}

//Only for nodejs Start//
if(typeof exports === "object" && typeof module !== "undefined"){
module.exports = supplyZgaCryptor;
}
//Only for nodejs End//
Loading

0 comments on commit dd52e4e

Please sign in to comment.