/** * node-compress-commons * * Copyright (c) 2014 Chris Talkington, contributors. * Licensed under the MIT license. * https://github.com/archiverjs/node-compress-commons/blob/master/LICENSE-MIT */ var inherits = require('util').inherits; var normalizePath = require('normalize-path'); var ArchiveEntry = require('../archive-entry'); var GeneralPurposeBit = require('./general-purpose-bit'); var UnixStat = require('./unix-stat'); var constants = require('./constants'); var zipUtil = require('./util'); var ZipArchiveEntry = module.exports = function(name) { if (!(this instanceof ZipArchiveEntry)) { return new ZipArchiveEntry(name); } ArchiveEntry.call(this); this.platform = constants.PLATFORM_FAT; this.method = -1; this.name = null; this.size = 0; this.csize = 0; this.gpb = new GeneralPurposeBit(); this.crc = 0; this.time = -1; this.minver = constants.MIN_VERSION_INITIAL; this.mode = -1; this.extra = null; this.exattr = 0; this.inattr = 0; this.comment = null; if (name) { this.setName(name); } }; inherits(ZipArchiveEntry, ArchiveEntry); /** * Returns the extra fields related to the entry. * * @returns {Buffer} */ ZipArchiveEntry.prototype.getCentralDirectoryExtra = function() { return this.getExtra(); }; /** * Returns the comment set for the entry. * * @returns {string} */ ZipArchiveEntry.prototype.getComment = function() { return this.comment !== null ? this.comment : ''; }; /** * Returns the compressed size of the entry. * * @returns {number} */ ZipArchiveEntry.prototype.getCompressedSize = function() { return this.csize; }; /** * Returns the CRC32 digest for the entry. * * @returns {number} */ ZipArchiveEntry.prototype.getCrc = function() { return this.crc; }; /** * Returns the external file attributes for the entry. * * @returns {number} */ ZipArchiveEntry.prototype.getExternalAttributes = function() { return this.exattr; }; /** * Returns the extra fields related to the entry. * * @returns {Buffer} */ ZipArchiveEntry.prototype.getExtra = function() { return this.extra !== null ? this.extra : constants.EMPTY; }; /** * Returns the general purpose bits related to the entry. * * @returns {GeneralPurposeBit} */ ZipArchiveEntry.prototype.getGeneralPurposeBit = function() { return this.gpb; }; /** * Returns the internal file attributes for the entry. * * @returns {number} */ ZipArchiveEntry.prototype.getInternalAttributes = function() { return this.inattr; }; /** * Returns the last modified date of the entry. * * @returns {number} */ ZipArchiveEntry.prototype.getLastModifiedDate = function() { return this.getTime(); }; /** * Returns the extra fields related to the entry. * * @returns {Buffer} */ ZipArchiveEntry.prototype.getLocalFileDataExtra = function() { return this.getExtra(); }; /** * Returns the compression method used on the entry. * * @returns {number} */ ZipArchiveEntry.prototype.getMethod = function() { return this.method; }; /** * Returns the filename of the entry. * * @returns {string} */ ZipArchiveEntry.prototype.getName = function() { return this.name; }; /** * Returns the platform on which the entry was made. * * @returns {number} */ ZipArchiveEntry.prototype.getPlatform = function() { return this.platform; }; /** * Returns the size of the entry. * * @returns {number} */ ZipArchiveEntry.prototype.getSize = function() { return this.size; }; /** * Returns a date object representing the last modified date of the entry. * * @returns {number|Date} */ ZipArchiveEntry.prototype.getTime = function() { return this.time !== -1 ? zipUtil.dosToDate(this.time) : -1; }; /** * Returns the DOS timestamp for the entry. * * @returns {number} */ ZipArchiveEntry.prototype.getTimeDos = function() { return this.time !== -1 ? this.time : 0; }; /** * Returns the UNIX file permissions for the entry. * * @returns {number} */ ZipArchiveEntry.prototype.getUnixMode = function() { return this.platform !== constants.PLATFORM_UNIX ? 0 : ((this.getExternalAttributes() >> constants.SHORT_SHIFT) & constants.SHORT_MASK); }; /** * Returns the version of ZIP needed to extract the entry. * * @returns {number} */ ZipArchiveEntry.prototype.getVersionNeededToExtract = function() { return this.minver; }; /** * Sets the comment of the entry. * * @param comment */ ZipArchiveEntry.prototype.setComment = function(comment) { if (Buffer.byteLength(comment) !== comment.length) { this.getGeneralPurposeBit().useUTF8ForNames(true); } this.comment = comment; }; /** * Sets the compressed size of the entry. * * @param size */ ZipArchiveEntry.prototype.setCompressedSize = function(size) { if (size < 0) { throw new Error('invalid entry compressed size'); } this.csize = size; }; /** * Sets the checksum of the entry. * * @param crc */ ZipArchiveEntry.prototype.setCrc = function(crc) { if (crc < 0) { throw new Error('invalid entry crc32'); } this.crc = crc; }; /** * Sets the external file attributes of the entry. * * @param attr */ ZipArchiveEntry.prototype.setExternalAttributes = function(attr) { this.exattr = attr >>> 0; }; /** * Sets the extra fields related to the entry. * * @param extra */ ZipArchiveEntry.prototype.setExtra = function(extra) { this.extra = extra; }; /** * Sets the general purpose bits related to the entry. * * @param gpb */ ZipArchiveEntry.prototype.setGeneralPurposeBit = function(gpb) { if (!(gpb instanceof GeneralPurposeBit)) { throw new Error('invalid entry GeneralPurposeBit'); } this.gpb = gpb; }; /** * Sets the internal file attributes of the entry. * * @param attr */ ZipArchiveEntry.prototype.setInternalAttributes = function(attr) { this.inattr = attr; }; /** * Sets the compression method of the entry. * * @param method */ ZipArchiveEntry.prototype.setMethod = function(method) { if (method < 0) { throw new Error('invalid entry compression method'); } this.method = method; }; /** * Sets the name of the entry. * * @param name * @param prependSlash */ ZipArchiveEntry.prototype.setName = function(name, prependSlash = false) { name = normalizePath(name, false) .replace(/^\w+:/, '') .replace(/^(\.\.\/|\/)+/, ''); if (prependSlash) { name = `/${name}`; } if (Buffer.byteLength(name) !== name.length) { this.getGeneralPurposeBit().useUTF8ForNames(true); } this.name = name; }; /** * Sets the platform on which the entry was made. * * @param platform */ ZipArchiveEntry.prototype.setPlatform = function(platform) { this.platform = platform; }; /** * Sets the size of the entry. * * @param size */ ZipArchiveEntry.prototype.setSize = function(size) { if (size < 0) { throw new Error('invalid entry size'); } this.size = size; }; /** * Sets the time of the entry. * * @param time * @param forceLocalTime */ ZipArchiveEntry.prototype.setTime = function(time, forceLocalTime) { if (!(time instanceof Date)) { throw new Error('invalid entry time'); } this.time = zipUtil.dateToDos(time, forceLocalTime); }; /** * Sets the UNIX file permissions for the entry. * * @param mode */ ZipArchiveEntry.prototype.setUnixMode = function(mode) { mode |= this.isDirectory() ? constants.S_IFDIR : constants.S_IFREG; var extattr = 0; extattr |= (mode << constants.SHORT_SHIFT) | (this.isDirectory() ? constants.S_DOS_D : constants.S_DOS_A); this.setExternalAttributes(extattr); this.mode = mode & constants.MODE_MASK; this.platform = constants.PLATFORM_UNIX; }; /** * Sets the version of ZIP needed to extract this entry. * * @param minver */ ZipArchiveEntry.prototype.setVersionNeededToExtract = function(minver) { this.minver = minver; }; /** * Returns true if this entry represents a directory. * * @returns {boolean} */ ZipArchiveEntry.prototype.isDirectory = function() { return this.getName().slice(-1) === '/'; }; /** * Returns true if this entry represents a unix symlink, * in which case the entry's content contains the target path * for the symlink. * * @returns {boolean} */ ZipArchiveEntry.prototype.isUnixSymlink = function() { return (this.getUnixMode() & UnixStat.FILE_TYPE_FLAG) === UnixStat.LINK_FLAG; }; /** * Returns true if this entry is using the ZIP64 extension of ZIP. * * @returns {boolean} */ ZipArchiveEntry.prototype.isZip64 = function() { return this.csize > constants.ZIP64_MAGIC || this.size > constants.ZIP64_MAGIC; };