| 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 tableconst 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 functionsfunction 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 functionsUtils.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 folderUtils.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 bufferUtils.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 systemUtils.crcTable = crcTable;
 |