CoolFace
Apppublic

TrinetraLabs/Placebo_AI

sourceHugging Faceupdated 2mo agoView on Hugging Face
0likes
zipEntry.js294 linesDownload Raw Back to lib
1"use strict";2var readerFor = require("./reader/readerFor");3var utils = require("./utils");4var CompressedObject = require("./compressedObject");5var crc32fn = require("./crc32");6var utf8 = require("./utf8");7var compressions = require("./compressions");8var support = require("./support");9 10var MADE_BY_DOS = 0x00;11var MADE_BY_UNIX = 0x03;12 13/**14 * Find a compression registered in JSZip.15 * @param {string} compressionMethod the method magic to find.16 * @return {Object|null} the JSZip compression object, null if none found.17 */18var findCompression = function(compressionMethod) {19    for (var method in compressions) {20        if (!Object.prototype.hasOwnProperty.call(compressions, method)) {21            continue;22        }23        if (compressions[method].magic === compressionMethod) {24            return compressions[method];25        }26    }27    return null;28};29 30// class ZipEntry {{{31/**32 * An entry in the zip file.33 * @constructor34 * @param {Object} options Options of the current file.35 * @param {Object} loadOptions Options for loading the stream.36 */37function ZipEntry(options, loadOptions) {38    this.options = options;39    this.loadOptions = loadOptions;40}41ZipEntry.prototype = {42    /**43     * say if the file is encrypted.44     * @return {boolean} true if the file is encrypted, false otherwise.45     */46    isEncrypted: function() {47        // bit 1 is set48        return (this.bitFlag & 0x0001) === 0x0001;49    },50    /**51     * say if the file has utf-8 filename/comment.52     * @return {boolean} true if the filename/comment is in utf-8, false otherwise.53     */54    useUTF8: function() {55        // bit 11 is set56        return (this.bitFlag & 0x0800) === 0x0800;57    },58    /**59     * Read the local part of a zip file and add the info in this object.60     * @param {DataReader} reader the reader to use.61     */62    readLocalPart: function(reader) {63        var compression, localExtraFieldsLength;64 65        // we already know everything from the central dir !66        // If the central dir data are false, we are doomed.67        // On the bright side, the local part is scary  : zip64, data descriptors, both, etc.68        // The less data we get here, the more reliable this should be.69        // Let's skip the whole header and dash to the data !70        reader.skip(22);71        // in some zip created on windows, the filename stored in the central dir contains \ instead of /.72        // Strangely, the filename here is OK.73        // I would love to treat these zip files as corrupted (see http://www.info-zip.org/FAQ.html#backslashes74        // or APPNOTE#4.4.17.1, "All slashes MUST be forward slashes '/'") but there are a lot of bad zip generators...75        // Search "unzip mismatching "local" filename continuing with "central" filename version" on76        // the internet.77        //78        // I think I see the logic here : the central directory is used to display79        // content and the local directory is used to extract the files. Mixing / and \80        // may be used to display \ to windows users and use / when extracting the files.81        // Unfortunately, this lead also to some issues : http://seclists.org/fulldisclosure/2009/Sep/39482        this.fileNameLength = reader.readInt(2);83        localExtraFieldsLength = reader.readInt(2); // can't be sure this will be the same as the central dir84        // the fileName is stored as binary data, the handleUTF8 method will take care of the encoding.85        this.fileName = reader.readData(this.fileNameLength);86        reader.skip(localExtraFieldsLength);87 88        if (this.compressedSize === -1 || this.uncompressedSize === -1) {89            throw new Error("Bug or corrupted zip : didn't get enough information from the central directory " + "(compressedSize === -1 || uncompressedSize === -1)");90        }91 92        compression = findCompression(this.compressionMethod);93        if (compression === null) { // no compression found94            throw new Error("Corrupted zip : compression " + utils.pretty(this.compressionMethod) + " unknown (inner file : " + utils.transformTo("string", this.fileName) + ")");95        }96        this.decompressed = new CompressedObject(this.compressedSize, this.uncompressedSize, this.crc32, compression, reader.readData(this.compressedSize));97    },98 99    /**100     * Read the central part of a zip file and add the info in this object.101     * @param {DataReader} reader the reader to use.102     */103    readCentralPart: function(reader) {104        this.versionMadeBy = reader.readInt(2);105        reader.skip(2);106        // this.versionNeeded = reader.readInt(2);107        this.bitFlag = reader.readInt(2);108        this.compressionMethod = reader.readString(2);109        this.date = reader.readDate();110        this.crc32 = reader.readInt(4);111        this.compressedSize = reader.readInt(4);112        this.uncompressedSize = reader.readInt(4);113        var fileNameLength = reader.readInt(2);114        this.extraFieldsLength = reader.readInt(2);115        this.fileCommentLength = reader.readInt(2);116        this.diskNumberStart = reader.readInt(2);117        this.internalFileAttributes = reader.readInt(2);118        this.externalFileAttributes = reader.readInt(4);119        this.localHeaderOffset = reader.readInt(4);120 121        if (this.isEncrypted()) {122            throw new Error("Encrypted zip are not supported");123        }124 125        // will be read in the local part, see the comments there126        reader.skip(fileNameLength);127        this.readExtraFields(reader);128        this.parseZIP64ExtraField(reader);129        this.fileComment = reader.readData(this.fileCommentLength);130    },131 132    /**133     * Parse the external file attributes and get the unix/dos permissions.134     */135    processAttributes: function () {136        this.unixPermissions = null;137        this.dosPermissions = null;138        var madeBy = this.versionMadeBy >> 8;139 140        // Check if we have the DOS directory flag set.141        // We look for it in the DOS and UNIX permissions142        // but some unknown platform could set it as a compatibility flag.143        this.dir = this.externalFileAttributes & 0x0010 ? true : false;144 145        if(madeBy === MADE_BY_DOS) {146            // first 6 bits (0 to 5)147            this.dosPermissions = this.externalFileAttributes & 0x3F;148        }149 150        if(madeBy === MADE_BY_UNIX) {151            this.unixPermissions = (this.externalFileAttributes >> 16) & 0xFFFF;152            // the octal permissions are in (this.unixPermissions & 0x01FF).toString(8);153        }154 155        // fail safe : if the name ends with a / it probably means a folder156        if (!this.dir && this.fileNameStr.slice(-1) === "/") {157            this.dir = true;158        }159    },160 161    /**162     * Parse the ZIP64 extra field and merge the info in the current ZipEntry.163     * @param {DataReader} reader the reader to use.164     */165    parseZIP64ExtraField: function() {166        if (!this.extraFields[0x0001]) {167            return;168        }169 170        // should be something, preparing the extra reader171        var extraReader = readerFor(this.extraFields[0x0001].value);172 173        // I really hope that these 64bits integer can fit in 32 bits integer, because js174        // won't let us have more.175        if (this.uncompressedSize === utils.MAX_VALUE_32BITS) {176            this.uncompressedSize = extraReader.readInt(8);177        }178        if (this.compressedSize === utils.MAX_VALUE_32BITS) {179            this.compressedSize = extraReader.readInt(8);180        }181        if (this.localHeaderOffset === utils.MAX_VALUE_32BITS) {182            this.localHeaderOffset = extraReader.readInt(8);183        }184        if (this.diskNumberStart === utils.MAX_VALUE_32BITS) {185            this.diskNumberStart = extraReader.readInt(4);186        }187    },188    /**189     * Read the central part of a zip file and add the info in this object.190     * @param {DataReader} reader the reader to use.191     */192    readExtraFields: function(reader) {193        var end = reader.index + this.extraFieldsLength,194            extraFieldId,195            extraFieldLength,196            extraFieldValue;197 198        if (!this.extraFields) {199            this.extraFields = {};200        }201 202        while (reader.index + 4 < end) {203            extraFieldId = reader.readInt(2);204            extraFieldLength = reader.readInt(2);205            extraFieldValue = reader.readData(extraFieldLength);206 207            this.extraFields[extraFieldId] = {208                id: extraFieldId,209                length: extraFieldLength,210                value: extraFieldValue211            };212        }213 214        reader.setIndex(end);215    },216    /**217     * Apply an UTF8 transformation if needed.218     */219    handleUTF8: function() {220        var decodeParamType = support.uint8array ? "uint8array" : "array";221        if (this.useUTF8()) {222            this.fileNameStr = utf8.utf8decode(this.fileName);223            this.fileCommentStr = utf8.utf8decode(this.fileComment);224        } else {225            var upath = this.findExtraFieldUnicodePath();226            if (upath !== null) {227                this.fileNameStr = upath;228            } else {229                // ASCII text or unsupported code page230                var fileNameByteArray =  utils.transformTo(decodeParamType, this.fileName);231                this.fileNameStr = this.loadOptions.decodeFileName(fileNameByteArray);232            }233 234            var ucomment = this.findExtraFieldUnicodeComment();235            if (ucomment !== null) {236                this.fileCommentStr = ucomment;237            } else {238                // ASCII text or unsupported code page239                var commentByteArray =  utils.transformTo(decodeParamType, this.fileComment);240                this.fileCommentStr = this.loadOptions.decodeFileName(commentByteArray);241            }242        }243    },244 245    /**246     * Find the unicode path declared in the extra field, if any.247     * @return {String} the unicode path, null otherwise.248     */249    findExtraFieldUnicodePath: function() {250        var upathField = this.extraFields[0x7075];251        if (upathField) {252            var extraReader = readerFor(upathField.value);253 254            // wrong version255            if (extraReader.readInt(1) !== 1) {256                return null;257            }258 259            // the crc of the filename changed, this field is out of date.260            if (crc32fn(this.fileName) !== extraReader.readInt(4)) {261                return null;262            }263 264            return utf8.utf8decode(extraReader.readData(upathField.length - 5));265        }266        return null;267    },268 269    /**270     * Find the unicode comment declared in the extra field, if any.271     * @return {String} the unicode comment, null otherwise.272     */273    findExtraFieldUnicodeComment: function() {274        var ucommentField = this.extraFields[0x6375];275        if (ucommentField) {276            var extraReader = readerFor(ucommentField.value);277 278            // wrong version279            if (extraReader.readInt(1) !== 1) {280                return null;281            }282 283            // the crc of the comment changed, this field is out of date.284            if (crc32fn(this.fileComment) !== extraReader.readInt(4)) {285                return null;286            }287 288            return utf8.utf8decode(extraReader.readData(ucommentField.length - 5));289        }290        return null;291    }292};293module.exports = ZipEntry;294