123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336 |
- const fsystem = require("fs");
- const pth = require("path");
- const Constants = require("./constants");
- const Errors = require("./errors");
- const isWin = typeof process === "object" && "win32" === process.platform;
- const is_Obj = (obj) => typeof obj === "object" && obj !== null;
- // generate CRC32 lookup table
- const crcTable = new Uint32Array(256).map((t, c) => {
- for (let k = 0; k < 8; k++) {
- if ((c & 1) !== 0) {
- c = 0xedb88320 ^ (c >>> 1);
- } else {
- c >>>= 1;
- }
- }
- return c >>> 0;
- });
- // UTILS functions
- function Utils(opts) {
- this.sep = pth.sep;
- this.fs = fsystem;
- if (is_Obj(opts)) {
- // custom filesystem
- if (is_Obj(opts.fs) && typeof opts.fs.statSync === "function") {
- this.fs = opts.fs;
- }
- }
- }
- module.exports = Utils;
- // INSTANTIABLE functions
- Utils.prototype.makeDir = function (/*String*/ folder) {
- const self = this;
- // Sync - make directories tree
- function mkdirSync(/*String*/ fpath) {
- let resolvedPath = fpath.split(self.sep)[0];
- fpath.split(self.sep).forEach(function (name) {
- if (!name || name.substr(-1, 1) === ":") return;
- resolvedPath += self.sep + name;
- var stat;
- try {
- stat = self.fs.statSync(resolvedPath);
- } catch (e) {
- self.fs.mkdirSync(resolvedPath);
- }
- if (stat && stat.isFile()) throw Errors.FILE_IN_THE_WAY(`"${resolvedPath}"`);
- });
- }
- mkdirSync(folder);
- };
- Utils.prototype.writeFileTo = function (/*String*/ path, /*Buffer*/ content, /*Boolean*/ overwrite, /*Number*/ attr) {
- const self = this;
- if (self.fs.existsSync(path)) {
- if (!overwrite) return false; // cannot overwrite
- var stat = self.fs.statSync(path);
- if (stat.isDirectory()) {
- return false;
- }
- }
- var folder = pth.dirname(path);
- if (!self.fs.existsSync(folder)) {
- self.makeDir(folder);
- }
- var fd;
- try {
- fd = self.fs.openSync(path, "w", 0o666); // 0666
- } catch (e) {
- self.fs.chmodSync(path, 0o666);
- fd = self.fs.openSync(path, "w", 0o666);
- }
- if (fd) {
- try {
- self.fs.writeSync(fd, content, 0, content.length, 0);
- } finally {
- self.fs.closeSync(fd);
- }
- }
- self.fs.chmodSync(path, attr || 0o666);
- return true;
- };
- Utils.prototype.writeFileToAsync = function (/*String*/ path, /*Buffer*/ content, /*Boolean*/ overwrite, /*Number*/ attr, /*Function*/ callback) {
- if (typeof attr === "function") {
- callback = attr;
- attr = undefined;
- }
- const self = this;
- self.fs.exists(path, function (exist) {
- if (exist && !overwrite) return callback(false);
- self.fs.stat(path, function (err, stat) {
- if (exist && stat.isDirectory()) {
- return callback(false);
- }
- var folder = pth.dirname(path);
- self.fs.exists(folder, function (exists) {
- if (!exists) self.makeDir(folder);
- self.fs.open(path, "w", 0o666, function (err, fd) {
- if (err) {
- self.fs.chmod(path, 0o666, function () {
- self.fs.open(path, "w", 0o666, function (err, fd) {
- self.fs.write(fd, content, 0, content.length, 0, function () {
- self.fs.close(fd, function () {
- self.fs.chmod(path, attr || 0o666, function () {
- callback(true);
- });
- });
- });
- });
- });
- } else if (fd) {
- self.fs.write(fd, content, 0, content.length, 0, function () {
- self.fs.close(fd, function () {
- self.fs.chmod(path, attr || 0o666, function () {
- callback(true);
- });
- });
- });
- } else {
- self.fs.chmod(path, attr || 0o666, function () {
- callback(true);
- });
- }
- });
- });
- });
- });
- };
- Utils.prototype.findFiles = function (/*String*/ path) {
- const self = this;
- function findSync(/*String*/ dir, /*RegExp*/ pattern, /*Boolean*/ recursive) {
- if (typeof pattern === "boolean") {
- recursive = pattern;
- pattern = undefined;
- }
- let files = [];
- self.fs.readdirSync(dir).forEach(function (file) {
- const path = pth.join(dir, file);
- const stat = self.fs.statSync(path);
- if (!pattern || pattern.test(path)) {
- files.push(pth.normalize(path) + (stat.isDirectory() ? self.sep : ""));
- }
- if (stat.isDirectory() && recursive) files = files.concat(findSync(path, pattern, recursive));
- });
- return files;
- }
- return findSync(path, undefined, true);
- };
- /**
- * Callback for showing if everything was done.
- *
- * @callback filelistCallback
- * @param {Error} err - Error object
- * @param {string[]} list - was request fully completed
- */
- /**
- *
- * @param {string} dir
- * @param {filelistCallback} cb
- */
- Utils.prototype.findFilesAsync = function (dir, cb) {
- const self = this;
- let results = [];
- self.fs.readdir(dir, function (err, list) {
- if (err) return cb(err);
- let list_length = list.length;
- if (!list_length) return cb(null, results);
- list.forEach(function (file) {
- file = pth.join(dir, file);
- self.fs.stat(file, function (err, stat) {
- if (err) return cb(err);
- if (stat) {
- results.push(pth.normalize(file) + (stat.isDirectory() ? self.sep : ""));
- if (stat.isDirectory()) {
- self.findFilesAsync(file, function (err, res) {
- if (err) return cb(err);
- results = results.concat(res);
- if (!--list_length) cb(null, results);
- });
- } else {
- if (!--list_length) cb(null, results);
- }
- }
- });
- });
- });
- };
- Utils.prototype.getAttributes = function () {};
- Utils.prototype.setAttributes = function () {};
- // STATIC functions
- // crc32 single update (it is part of crc32)
- Utils.crc32update = function (crc, byte) {
- return crcTable[(crc ^ byte) & 0xff] ^ (crc >>> 8);
- };
- Utils.crc32 = function (buf) {
- if (typeof buf === "string") {
- buf = Buffer.from(buf, "utf8");
- }
- let len = buf.length;
- let crc = ~0;
- for (let off = 0; off < len; ) crc = Utils.crc32update(crc, buf[off++]);
- // xor and cast as uint32 number
- return ~crc >>> 0;
- };
- Utils.methodToString = function (/*Number*/ method) {
- switch (method) {
- case Constants.STORED:
- return "STORED (" + method + ")";
- case Constants.DEFLATED:
- return "DEFLATED (" + method + ")";
- default:
- return "UNSUPPORTED (" + method + ")";
- }
- };
- /**
- * removes ".." style path elements
- * @param {string} path - fixable path
- * @returns string - fixed filepath
- */
- Utils.canonical = function (/*string*/ path) {
- if (!path) return "";
- // trick normalize think path is absolute
- const safeSuffix = pth.posix.normalize("/" + path.split("\\").join("/"));
- return pth.join(".", safeSuffix);
- };
- /**
- * fix file names in achive
- * @param {string} path - fixable path
- * @returns string - fixed filepath
- */
- Utils.zipnamefix = function (path) {
- if (!path) return "";
- // trick normalize think path is absolute
- const safeSuffix = pth.posix.normalize("/" + path.split("\\").join("/"));
- return pth.posix.join(".", safeSuffix);
- };
- /**
- *
- * @param {Array} arr
- * @param {function} callback
- * @returns
- */
- Utils.findLast = function (arr, callback) {
- if (!Array.isArray(arr)) throw new TypeError("arr is not array");
- const len = arr.length >>> 0;
- for (let i = len - 1; i >= 0; i--) {
- if (callback(arr[i], i, arr)) {
- return arr[i];
- }
- }
- return void 0;
- };
- // make abolute paths taking prefix as root folder
- Utils.sanitize = function (/*string*/ prefix, /*string*/ name) {
- prefix = pth.resolve(pth.normalize(prefix));
- var parts = name.split("/");
- for (var i = 0, l = parts.length; i < l; i++) {
- var path = pth.normalize(pth.join(prefix, parts.slice(i, l).join(pth.sep)));
- if (path.indexOf(prefix) === 0) {
- return path;
- }
- }
- return pth.normalize(pth.join(prefix, pth.basename(name)));
- };
- // converts buffer, Uint8Array, string types to buffer
- Utils.toBuffer = function toBuffer(/*buffer, Uint8Array, string*/ input, /* function */ encoder) {
- if (Buffer.isBuffer(input)) {
- return input;
- } else if (input instanceof Uint8Array) {
- return Buffer.from(input);
- } else {
- // expect string all other values are invalid and return empty buffer
- return typeof input === "string" ? encoder(input) : Buffer.alloc(0);
- }
- };
- Utils.readBigUInt64LE = function (/*Buffer*/ buffer, /*int*/ index) {
- var slice = Buffer.from(buffer.slice(index, index + 8));
- slice.swap64();
- return parseInt(`0x${slice.toString("hex")}`);
- };
- Utils.fromDOS2Date = function (val) {
- return new Date(((val >> 25) & 0x7f) + 1980, Math.max(((val >> 21) & 0x0f) - 1, 0), Math.max((val >> 16) & 0x1f, 1), (val >> 11) & 0x1f, (val >> 5) & 0x3f, (val & 0x1f) << 1);
- };
- Utils.fromDate2DOS = function (val) {
- let date = 0;
- let time = 0;
- if (val.getFullYear() > 1979) {
- date = (((val.getFullYear() - 1980) & 0x7f) << 9) | ((val.getMonth() + 1) << 5) | val.getDate();
- time = (val.getHours() << 11) | (val.getMinutes() << 5) | (val.getSeconds() >> 1);
- }
- return (date << 16) | time;
- };
- Utils.isWin = isWin; // Do we have windows system
- Utils.crcTable = crcTable;
|