EASYAIuniappNewUI/node_modules/adm-zip/zipEntry.js
2025-02-08 18:50:38 +08:00

406 lines
15 KiB
JavaScript

var Utils = require("./util"),
Headers = require("./headers"),
Constants = Utils.Constants,
Methods = require("./methods");
module.exports = function (/** object */ options, /*Buffer*/ input) {
var _centralHeader = new Headers.EntryHeader(),
_entryName = Buffer.alloc(0),
_comment = Buffer.alloc(0),
_isDirectory = false,
uncompressedData = null,
_extra = Buffer.alloc(0),
_extralocal = Buffer.alloc(0),
_efs = true;
// assign options
const opts = options;
const decoder = typeof opts.decoder === "object" ? opts.decoder : Utils.decoder;
_efs = decoder.hasOwnProperty("efs") ? decoder.efs : false;
function getCompressedDataFromZip() {
//if (!input || !Buffer.isBuffer(input)) {
if (!input || !(input instanceof Uint8Array)) {
return Buffer.alloc(0);
}
_extralocal = _centralHeader.loadLocalHeaderFromBinary(input);
return input.slice(_centralHeader.realDataOffset, _centralHeader.realDataOffset + _centralHeader.compressedSize);
}
function crc32OK(data) {
// if bit 3 (0x08) of the general-purpose flags field is set, then the CRC-32 and file sizes are not known when the local header is written
if (!_centralHeader.flags_desc) {
if (Utils.crc32(data) !== _centralHeader.localHeader.crc) {
return false;
}
} else {
const descriptor = {};
const dataEndOffset = _centralHeader.realDataOffset + _centralHeader.compressedSize;
// no descriptor after compressed data, instead new local header
if (input.readUInt32LE(dataEndOffset) == Constants.LOCSIG || input.readUInt32LE(dataEndOffset) == Constants.CENSIG) {
throw Utils.Errors.DESCRIPTOR_NOT_EXIST();
}
// get decriptor data
if (input.readUInt32LE(dataEndOffset) == Constants.EXTSIG) {
// descriptor with signature
descriptor.crc = input.readUInt32LE(dataEndOffset + Constants.EXTCRC);
descriptor.compressedSize = input.readUInt32LE(dataEndOffset + Constants.EXTSIZ);
descriptor.size = input.readUInt32LE(dataEndOffset + Constants.EXTLEN);
} else if (input.readUInt16LE(dataEndOffset + 12) === 0x4b50) {
// descriptor without signature (we check is new header starting where we expect)
descriptor.crc = input.readUInt32LE(dataEndOffset + Constants.EXTCRC - 4);
descriptor.compressedSize = input.readUInt32LE(dataEndOffset + Constants.EXTSIZ - 4);
descriptor.size = input.readUInt32LE(dataEndOffset + Constants.EXTLEN - 4);
} else {
throw Utils.Errors.DESCRIPTOR_UNKNOWN();
}
// check data integrity
if (descriptor.compressedSize !== _centralHeader.compressedSize || descriptor.size !== _centralHeader.size || descriptor.crc !== _centralHeader.crc) {
throw Utils.Errors.DESCRIPTOR_FAULTY();
}
if (Utils.crc32(data) !== descriptor.crc) {
return false;
}
// @TODO: zip64 bit descriptor fields
// if bit 3 is set and any value in local header "zip64 Extended information" extra field are set 0 (place holder)
// then 64-bit descriptor format is used instead of 32-bit
// central header - "zip64 Extended information" extra field should store real values and not place holders
}
return true;
}
function decompress(/*Boolean*/ async, /*Function*/ callback, /*String, Buffer*/ pass) {
if (typeof callback === "undefined" && typeof async === "string") {
pass = async;
async = void 0;
}
if (_isDirectory) {
if (async && callback) {
callback(Buffer.alloc(0), Utils.Errors.DIRECTORY_CONTENT_ERROR()); //si added error.
}
return Buffer.alloc(0);
}
var compressedData = getCompressedDataFromZip();
if (compressedData.length === 0) {
// File is empty, nothing to decompress.
if (async && callback) callback(compressedData);
return compressedData;
}
if (_centralHeader.encrypted) {
if ("string" !== typeof pass && !Buffer.isBuffer(pass)) {
throw Utils.Errors.INVALID_PASS_PARAM();
}
compressedData = Methods.ZipCrypto.decrypt(compressedData, _centralHeader, pass);
}
var data = Buffer.alloc(_centralHeader.size);
switch (_centralHeader.method) {
case Utils.Constants.STORED:
compressedData.copy(data);
if (!crc32OK(data)) {
if (async && callback) callback(data, Utils.Errors.BAD_CRC()); //si added error
throw Utils.Errors.BAD_CRC();
} else {
//si added otherwise did not seem to return data.
if (async && callback) callback(data);
return data;
}
case Utils.Constants.DEFLATED:
var inflater = new Methods.Inflater(compressedData, _centralHeader.size);
if (!async) {
const result = inflater.inflate(data);
result.copy(data, 0);
if (!crc32OK(data)) {
throw Utils.Errors.BAD_CRC(`"${decoder.decode(_entryName)}"`);
}
return data;
} else {
inflater.inflateAsync(function (result) {
result.copy(result, 0);
if (callback) {
if (!crc32OK(result)) {
callback(result, Utils.Errors.BAD_CRC()); //si added error
} else {
callback(result);
}
}
});
}
break;
default:
if (async && callback) callback(Buffer.alloc(0), Utils.Errors.UNKNOWN_METHOD());
throw Utils.Errors.UNKNOWN_METHOD();
}
}
function compress(/*Boolean*/ async, /*Function*/ callback) {
if ((!uncompressedData || !uncompressedData.length) && Buffer.isBuffer(input)) {
// no data set or the data wasn't changed to require recompression
if (async && callback) callback(getCompressedDataFromZip());
return getCompressedDataFromZip();
}
if (uncompressedData.length && !_isDirectory) {
var compressedData;
// Local file header
switch (_centralHeader.method) {
case Utils.Constants.STORED:
_centralHeader.compressedSize = _centralHeader.size;
compressedData = Buffer.alloc(uncompressedData.length);
uncompressedData.copy(compressedData);
if (async && callback) callback(compressedData);
return compressedData;
default:
case Utils.Constants.DEFLATED:
var deflater = new Methods.Deflater(uncompressedData);
if (!async) {
var deflated = deflater.deflate();
_centralHeader.compressedSize = deflated.length;
return deflated;
} else {
deflater.deflateAsync(function (data) {
compressedData = Buffer.alloc(data.length);
_centralHeader.compressedSize = data.length;
data.copy(compressedData);
callback && callback(compressedData);
});
}
deflater = null;
break;
}
} else if (async && callback) {
callback(Buffer.alloc(0));
} else {
return Buffer.alloc(0);
}
}
function readUInt64LE(buffer, offset) {
return (buffer.readUInt32LE(offset + 4) << 4) + buffer.readUInt32LE(offset);
}
function parseExtra(data) {
try {
var offset = 0;
var signature, size, part;
while (offset + 4 < data.length) {
signature = data.readUInt16LE(offset);
offset += 2;
size = data.readUInt16LE(offset);
offset += 2;
part = data.slice(offset, offset + size);
offset += size;
if (Constants.ID_ZIP64 === signature) {
parseZip64ExtendedInformation(part);
}
}
} catch (error) {
throw Utils.Errors.EXTRA_FIELD_PARSE_ERROR();
}
}
//Override header field values with values from the ZIP64 extra field
function parseZip64ExtendedInformation(data) {
var size, compressedSize, offset, diskNumStart;
if (data.length >= Constants.EF_ZIP64_SCOMP) {
size = readUInt64LE(data, Constants.EF_ZIP64_SUNCOMP);
if (_centralHeader.size === Constants.EF_ZIP64_OR_32) {
_centralHeader.size = size;
}
}
if (data.length >= Constants.EF_ZIP64_RHO) {
compressedSize = readUInt64LE(data, Constants.EF_ZIP64_SCOMP);
if (_centralHeader.compressedSize === Constants.EF_ZIP64_OR_32) {
_centralHeader.compressedSize = compressedSize;
}
}
if (data.length >= Constants.EF_ZIP64_DSN) {
offset = readUInt64LE(data, Constants.EF_ZIP64_RHO);
if (_centralHeader.offset === Constants.EF_ZIP64_OR_32) {
_centralHeader.offset = offset;
}
}
if (data.length >= Constants.EF_ZIP64_DSN + 4) {
diskNumStart = data.readUInt32LE(Constants.EF_ZIP64_DSN);
if (_centralHeader.diskNumStart === Constants.EF_ZIP64_OR_16) {
_centralHeader.diskNumStart = diskNumStart;
}
}
}
return {
get entryName() {
return decoder.decode(_entryName);
},
get rawEntryName() {
return _entryName;
},
set entryName(val) {
_entryName = Utils.toBuffer(val, decoder.encode);
var lastChar = _entryName[_entryName.length - 1];
_isDirectory = lastChar === 47 || lastChar === 92;
_centralHeader.fileNameLength = _entryName.length;
},
get efs() {
if (typeof _efs === "function") {
return _efs(this.entryName);
} else {
return _efs;
}
},
get extra() {
return _extra;
},
set extra(val) {
_extra = val;
_centralHeader.extraLength = val.length;
parseExtra(val);
},
get comment() {
return decoder.decode(_comment);
},
set comment(val) {
_comment = Utils.toBuffer(val, decoder.encode);
_centralHeader.commentLength = _comment.length;
if (_comment.length > 0xffff) throw Utils.Errors.COMMENT_TOO_LONG();
},
get name() {
var n = decoder.decode(_entryName);
return _isDirectory
? n
.substr(n.length - 1)
.split("/")
.pop()
: n.split("/").pop();
},
get isDirectory() {
return _isDirectory;
},
getCompressedData: function () {
return compress(false, null);
},
getCompressedDataAsync: function (/*Function*/ callback) {
compress(true, callback);
},
setData: function (value) {
uncompressedData = Utils.toBuffer(value, Utils.decoder.encode);
if (!_isDirectory && uncompressedData.length) {
_centralHeader.size = uncompressedData.length;
_centralHeader.method = Utils.Constants.DEFLATED;
_centralHeader.crc = Utils.crc32(value);
_centralHeader.changed = true;
} else {
// folders and blank files should be stored
_centralHeader.method = Utils.Constants.STORED;
}
},
getData: function (pass) {
if (_centralHeader.changed) {
return uncompressedData;
} else {
return decompress(false, null, pass);
}
},
getDataAsync: function (/*Function*/ callback, pass) {
if (_centralHeader.changed) {
callback(uncompressedData);
} else {
decompress(true, callback, pass);
}
},
set attr(attr) {
_centralHeader.attr = attr;
},
get attr() {
return _centralHeader.attr;
},
set header(/*Buffer*/ data) {
_centralHeader.loadFromBinary(data);
},
get header() {
return _centralHeader;
},
packCentralHeader: function () {
_centralHeader.flags_efs = this.efs;
_centralHeader.extraLength = _extra.length;
// 1. create header (buffer)
var header = _centralHeader.centralHeaderToBinary();
var addpos = Utils.Constants.CENHDR;
// 2. add file name
_entryName.copy(header, addpos);
addpos += _entryName.length;
// 3. add extra data
_extra.copy(header, addpos);
addpos += _centralHeader.extraLength;
// 4. add file comment
_comment.copy(header, addpos);
return header;
},
packLocalHeader: function () {
let addpos = 0;
_centralHeader.flags_efs = this.efs;
_centralHeader.extraLocalLength = _extralocal.length;
// 1. construct local header Buffer
const localHeaderBuf = _centralHeader.localHeaderToBinary();
// 2. localHeader - crate header buffer
const localHeader = Buffer.alloc(localHeaderBuf.length + _entryName.length + _centralHeader.extraLocalLength);
// 2.1 add localheader
localHeaderBuf.copy(localHeader, addpos);
addpos += localHeaderBuf.length;
// 2.2 add file name
_entryName.copy(localHeader, addpos);
addpos += _entryName.length;
// 2.3 add extra field
_extralocal.copy(localHeader, addpos);
addpos += _extralocal.length;
return localHeader;
},
toJSON: function () {
const bytes = function (nr) {
return "<" + ((nr && nr.length + " bytes buffer") || "null") + ">";
};
return {
entryName: this.entryName,
name: this.name,
comment: this.comment,
isDirectory: this.isDirectory,
header: _centralHeader.toJSON(),
compressedData: bytes(input),
data: bytes(uncompressedData)
};
},
toString: function () {
return JSON.stringify(this.toJSON(), null, "\t");
}
};
};