xml-fiesta
Version:
Electronic signed document XML Protocol for Node & Browser
184 lines • 7.08 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
var Promise = require('promise');
var xmlCrypto = require('xml-crypto');
var select = require('xpath.js');
var Dom = require('xmldom').DOMParser;
var xml2js_1 = require("xml2js");
var common_1 = require("./common");
var ExclusiveCanonicalization = xmlCrypto.
SignedXml.
CanonicalizationAlgorithms['http://www.w3.org/2001/10/xml-exc-c14n#'];
var XML = (function () {
function XML() {
}
XML.parse = function (string) {
var xml = new XML();
return xml.parse(string);
};
XML.toXML = function (eDocument, file) {
var edoc = JSON.parse(JSON.stringify(eDocument));
this.removeEncrypedData(edoc);
edoc.file[0]._ = file;
var builder = new xml2js_1.Builder({
rootName: "electronicDocument",
renderOpts: {
pretty: false,
},
});
return builder.buildObject(edoc);
};
XML.removeEncrypedData = function (xmljs) {
if (xmljs.file && xmljs.file[0]) {
delete xmljs.file[0].$.encrypted;
xmljs.file[0].$.name = xmljs.file[0].$.name.replace(".enc", "");
}
xmljs.signers[0].signer.forEach(function (signer) {
delete signer.ePass;
});
};
XML.removeGeolocation = function (xmljs) {
xmljs.signers[0].signer.forEach(function (signer) {
if (signer.auditTrail) {
signer.auditTrail[0].event.forEach(function (event, index) {
if (event.$.name === "geolocation") {
delete signer.auditTrail[0].event[index];
}
});
}
});
};
XML.removeBlockchain = function (xmljs) {
delete xmljs.blockchain;
};
XML.removeTransfer = function (xmljs) {
delete xmljs.transfers;
};
XML.prototype.parse = function (xml) {
var el = this;
return new Promise(function (resolve, reject) {
return xml2js_1.parseString(xml, function (err, result) {
var _a;
var isTransfer = false;
if (result.electronicDocument.transfers) {
var lastNodeTransfer = result.electronicDocument.transfers[result.electronicDocument.transfers.length - 1];
if ((_a = lastNodeTransfer) === null || _a === void 0 ? void 0 : _a.electronicDocument) {
isTransfer = true;
result.originalElectronicDocument = result.electronicDocument;
result.electronicDocument =
lastNodeTransfer.electronicDocument[lastNodeTransfer.electronicDocument.length - 1];
el.originalElectronicDocument = result.originalElectronicDocument;
}
}
if (err) {
return reject(err);
}
el.eDocument = result.electronicDocument;
var eDocumentAttrs = el.eDocument.$;
el.version = eDocumentAttrs.version;
el.signed = eDocumentAttrs.signed;
var v = el.version.split(/\./).map(function (v) { return parseInt(v); });
el.version_int = v[0] * 100 + v[1] * 10 + v[2];
if (el.version_int < 100) {
el.fileElementName = "pdf";
}
else {
el.fileElementName = "file";
}
var pdfAttrs = el.eDocument[el.fileElementName][0].$;
el.encrypted = pdfAttrs.encrypted;
el.name = pdfAttrs.name;
el.contentType = pdfAttrs.contentType;
el.originalHash = pdfAttrs.originalHash;
el.isTransfer = isTransfer;
return resolve(el);
});
});
};
XML.prototype.canonical = function () {
var edoc = JSON.parse(JSON.stringify(this.eDocument));
if (this.isTransfer && this.originalElectronicDocument) {
Object.entries(this.originalElectronicDocument.$).map(function (_a) {
var key = _a[0], value = _a[1];
if (key.includes('xmlns')) {
edoc.$[key] = value;
}
});
}
delete edoc.conservancyRecord;
XML.removeEncrypedData(edoc);
XML.removeGeolocation(edoc);
XML.removeBlockchain(edoc);
XML.removeTransfer(edoc);
if (this.version_int >= 100) {
edoc[this.fileElementName][0]._ = "";
}
var builder = new xml2js_1.Builder({
rootName: "electronicDocument",
renderOpts: {
pretty: false,
},
});
var originalXml = builder.buildObject(edoc);
var doc = new Dom().parseFromString(originalXml);
var elem = select(doc, "//*")[0];
var can = new ExclusiveCanonicalization();
var canonicalString = can.process(elem).toString();
return canonicalString.replace(/
/g, "");
};
XML.prototype.getCanonicalBuffer = function () {
return Buffer.from(this.canonical(), "utf-8");
};
XML.prototype.file = function () {
return this.eDocument[this.fileElementName][0]._;
};
XML.prototype.pdf = function () {
return this.file();
};
XML.prototype.xmlSigners = function () {
var parsedSigners = [];
this.eDocument.signers[0].signer.forEach(function (signer) {
var attrs = signer.$;
var xmlSigner = {
email: attrs.email,
cer: common_1.b64toHex(signer.certificate[0]._),
signature: common_1.b64toHex(signer.signature[0]._),
signedAt: signer.signature[0].$.signedAt,
};
if (signer.ePass) {
xmlSigner.ePass = {
content: common_1.b64toHex(signer.ePass[0]._),
algorithm: signer.ePass[0].$.algorithm,
iterations: signer.ePass[0].$.iterations,
keySize: signer.ePass[0].$.keySize,
};
}
return parsedSigners.push(xmlSigner);
});
return parsedSigners;
};
XML.prototype.getConservancyRecord = function () {
var crVersion, userCertificate;
if (!this.eDocument.conservancyRecord) {
return null;
}
var cr = this.eDocument.conservancyRecord[0];
if (!cr.$.version) {
userCertificate = cr.userCertificate[0]._;
}
else {
crVersion = cr.$.version;
}
return {
caCert: cr.caCertificate[0]._,
userCert: userCertificate,
record: cr.record[0],
timestamp: cr.$.timestamp,
originalXmlHash: common_1.sha256(this.canonical()),
version: crVersion,
};
};
return XML;
}());
exports.default = XML;
//# sourceMappingURL=xml.js.map