CoolFace
Apppublic

TrinetraLabs/Placebo_AI

sourceHugging Faceupdated 2mo agoView on Hugging Face
0likes
zipEntries.js262 linesDownload Raw Back to lib
1"use strict";2var readerFor = require("./reader/readerFor");3var utils = require("./utils");4var sig = require("./signature");5var ZipEntry = require("./zipEntry");6var support = require("./support");7//  class ZipEntries {{{8/**9 * All the entries in the zip file.10 * @constructor11 * @param {Object} loadOptions Options for loading the stream.12 */13function ZipEntries(loadOptions) {14    this.files = [];15    this.loadOptions = loadOptions;16}17ZipEntries.prototype = {18    /**19     * Check that the reader is on the specified signature.20     * @param {string} expectedSignature the expected signature.21     * @throws {Error} if it is an other signature.22     */23    checkSignature: function(expectedSignature) {24        if (!this.reader.readAndCheckSignature(expectedSignature)) {25            this.reader.index -= 4;26            var signature = this.reader.readString(4);27            throw new Error("Corrupted zip or bug: unexpected signature " + "(" + utils.pretty(signature) + ", expected " + utils.pretty(expectedSignature) + ")");28        }29    },30    /**31     * Check if the given signature is at the given index.32     * @param {number} askedIndex the index to check.33     * @param {string} expectedSignature the signature to expect.34     * @return {boolean} true if the signature is here, false otherwise.35     */36    isSignature: function(askedIndex, expectedSignature) {37        var currentIndex = this.reader.index;38        this.reader.setIndex(askedIndex);39        var signature = this.reader.readString(4);40        var result = signature === expectedSignature;41        this.reader.setIndex(currentIndex);42        return result;43    },44    /**45     * Read the end of the central directory.46     */47    readBlockEndOfCentral: function() {48        this.diskNumber = this.reader.readInt(2);49        this.diskWithCentralDirStart = this.reader.readInt(2);50        this.centralDirRecordsOnThisDisk = this.reader.readInt(2);51        this.centralDirRecords = this.reader.readInt(2);52        this.centralDirSize = this.reader.readInt(4);53        this.centralDirOffset = this.reader.readInt(4);54 55        this.zipCommentLength = this.reader.readInt(2);56        // warning : the encoding depends of the system locale57        // On a linux machine with LANG=en_US.utf8, this field is utf8 encoded.58        // On a windows machine, this field is encoded with the localized windows code page.59        var zipComment = this.reader.readData(this.zipCommentLength);60        var decodeParamType = support.uint8array ? "uint8array" : "array";61        // To get consistent behavior with the generation part, we will assume that62        // this is utf8 encoded unless specified otherwise.63        var decodeContent = utils.transformTo(decodeParamType, zipComment);64        this.zipComment = this.loadOptions.decodeFileName(decodeContent);65    },66    /**67     * Read the end of the Zip 64 central directory.68     * Not merged with the method readEndOfCentral :69     * The end of central can coexist with its Zip64 brother,70     * I don't want to read the wrong number of bytes !71     */72    readBlockZip64EndOfCentral: function() {73        this.zip64EndOfCentralSize = this.reader.readInt(8);74        this.reader.skip(4);75        // this.versionMadeBy = this.reader.readString(2);76        // this.versionNeeded = this.reader.readInt(2);77        this.diskNumber = this.reader.readInt(4);78        this.diskWithCentralDirStart = this.reader.readInt(4);79        this.centralDirRecordsOnThisDisk = this.reader.readInt(8);80        this.centralDirRecords = this.reader.readInt(8);81        this.centralDirSize = this.reader.readInt(8);82        this.centralDirOffset = this.reader.readInt(8);83 84        this.zip64ExtensibleData = {};85        var extraDataSize = this.zip64EndOfCentralSize - 44,86            index = 0,87            extraFieldId,88            extraFieldLength,89            extraFieldValue;90        while (index < extraDataSize) {91            extraFieldId = this.reader.readInt(2);92            extraFieldLength = this.reader.readInt(4);93            extraFieldValue = this.reader.readData(extraFieldLength);94            this.zip64ExtensibleData[extraFieldId] = {95                id: extraFieldId,96                length: extraFieldLength,97                value: extraFieldValue98            };99        }100    },101    /**102     * Read the end of the Zip 64 central directory locator.103     */104    readBlockZip64EndOfCentralLocator: function() {105        this.diskWithZip64CentralDirStart = this.reader.readInt(4);106        this.relativeOffsetEndOfZip64CentralDir = this.reader.readInt(8);107        this.disksCount = this.reader.readInt(4);108        if (this.disksCount > 1) {109            throw new Error("Multi-volumes zip are not supported");110        }111    },112    /**113     * Read the local files, based on the offset read in the central part.114     */115    readLocalFiles: function() {116        var i, file;117        for (i = 0; i < this.files.length; i++) {118            file = this.files[i];119            this.reader.setIndex(file.localHeaderOffset);120            this.checkSignature(sig.LOCAL_FILE_HEADER);121            file.readLocalPart(this.reader);122            file.handleUTF8();123            file.processAttributes();124        }125    },126    /**127     * Read the central directory.128     */129    readCentralDir: function() {130        var file;131 132        this.reader.setIndex(this.centralDirOffset);133        while (this.reader.readAndCheckSignature(sig.CENTRAL_FILE_HEADER)) {134            file = new ZipEntry({135                zip64: this.zip64136            }, this.loadOptions);137            file.readCentralPart(this.reader);138            this.files.push(file);139        }140 141        if (this.centralDirRecords !== this.files.length) {142            if (this.centralDirRecords !== 0 && this.files.length === 0) {143                // We expected some records but couldn't find ANY.144                // This is really suspicious, as if something went wrong.145                throw new Error("Corrupted zip or bug: expected " + this.centralDirRecords + " records in central dir, got " + this.files.length);146            } else {147                // We found some records but not all.148                // Something is wrong but we got something for the user: no error here.149                // console.warn("expected", this.centralDirRecords, "records in central dir, got", this.files.length);150            }151        }152    },153    /**154     * Read the end of central directory.155     */156    readEndOfCentral: function() {157        var offset = this.reader.lastIndexOfSignature(sig.CENTRAL_DIRECTORY_END);158        if (offset < 0) {159            // Check if the content is a truncated zip or complete garbage.160            // A "LOCAL_FILE_HEADER" is not required at the beginning (auto161            // extractible zip for example) but it can give a good hint.162            // If an ajax request was used without responseType, we will also163            // get unreadable data.164            var isGarbage = !this.isSignature(0, sig.LOCAL_FILE_HEADER);165 166            if (isGarbage) {167                throw new Error("Can't find end of central directory : is this a zip file ? " +168                                "If it is, see https://stuk.github.io/jszip/documentation/howto/read_zip.html");169            } else {170                throw new Error("Corrupted zip: can't find end of central directory");171            }172 173        }174        this.reader.setIndex(offset);175        var endOfCentralDirOffset = offset;176        this.checkSignature(sig.CENTRAL_DIRECTORY_END);177        this.readBlockEndOfCentral();178 179 180        /* extract from the zip spec :181            4)  If one of the fields in the end of central directory182                record is too small to hold required data, the field183                should be set to -1 (0xFFFF or 0xFFFFFFFF) and the184                ZIP64 format record should be created.185            5)  The end of central directory record and the186                Zip64 end of central directory locator record must187                reside on the same disk when splitting or spanning188                an archive.189         */190        if (this.diskNumber === utils.MAX_VALUE_16BITS || this.diskWithCentralDirStart === utils.MAX_VALUE_16BITS || this.centralDirRecordsOnThisDisk === utils.MAX_VALUE_16BITS || this.centralDirRecords === utils.MAX_VALUE_16BITS || this.centralDirSize === utils.MAX_VALUE_32BITS || this.centralDirOffset === utils.MAX_VALUE_32BITS) {191            this.zip64 = true;192 193            /*194            Warning : the zip64 extension is supported, but ONLY if the 64bits integer read from195            the zip file can fit into a 32bits integer. This cannot be solved : JavaScript represents196            all numbers as 64-bit double precision IEEE 754 floating point numbers.197            So, we have 53bits for integers and bitwise operations treat everything as 32bits.198            see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Bitwise_Operators199            and http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf section 8.5200            */201 202            // should look for a zip64 EOCD locator203            offset = this.reader.lastIndexOfSignature(sig.ZIP64_CENTRAL_DIRECTORY_LOCATOR);204            if (offset < 0) {205                throw new Error("Corrupted zip: can't find the ZIP64 end of central directory locator");206            }207            this.reader.setIndex(offset);208            this.checkSignature(sig.ZIP64_CENTRAL_DIRECTORY_LOCATOR);209            this.readBlockZip64EndOfCentralLocator();210 211            // now the zip64 EOCD record212            if (!this.isSignature(this.relativeOffsetEndOfZip64CentralDir, sig.ZIP64_CENTRAL_DIRECTORY_END)) {213                // console.warn("ZIP64 end of central directory not where expected.");214                this.relativeOffsetEndOfZip64CentralDir = this.reader.lastIndexOfSignature(sig.ZIP64_CENTRAL_DIRECTORY_END);215                if (this.relativeOffsetEndOfZip64CentralDir < 0) {216                    throw new Error("Corrupted zip: can't find the ZIP64 end of central directory");217                }218            }219            this.reader.setIndex(this.relativeOffsetEndOfZip64CentralDir);220            this.checkSignature(sig.ZIP64_CENTRAL_DIRECTORY_END);221            this.readBlockZip64EndOfCentral();222        }223 224        var expectedEndOfCentralDirOffset = this.centralDirOffset + this.centralDirSize;225        if (this.zip64) {226            expectedEndOfCentralDirOffset += 20; // end of central dir 64 locator227            expectedEndOfCentralDirOffset += 12 /* should not include the leading 12 bytes */ + this.zip64EndOfCentralSize;228        }229 230        var extraBytes = endOfCentralDirOffset - expectedEndOfCentralDirOffset;231 232        if (extraBytes > 0) {233            // console.warn(extraBytes, "extra bytes at beginning or within zipfile");234            if (this.isSignature(endOfCentralDirOffset, sig.CENTRAL_FILE_HEADER)) {235                // The offsets seem wrong, but we have something at the specified offset.236                // So… we keep it.237            } else {238                // the offset is wrong, update the "zero" of the reader239                // this happens if data has been prepended (crx files for example)240                this.reader.zero = extraBytes;241            }242        } else if (extraBytes < 0) {243            throw new Error("Corrupted zip: missing " + Math.abs(extraBytes) + " bytes.");244        }245    },246    prepareReader: function(data) {247        this.reader = readerFor(data);248    },249    /**250     * Read a zip file and create ZipEntries.251     * @param {String|ArrayBuffer|Uint8Array|Buffer} data the binary string representing a zip file.252     */253    load: function(data) {254        this.prepareReader(data);255        this.readEndOfCentral();256        this.readCentralDir();257        this.readLocalFiles();258    }259};260// }}} end of ZipEntries261module.exports = ZipEntries;262