UNPKG

appjs-package

Version:

module for handling AppJS packaged applications

214 lines (181 loc) 7.08 kB
var ZipEntry = require("./zipEntry"), Headers = require("./headers"); Utils = require("./util"); module.exports = function(/*Buffer*/buf) { var entryList = [], entryTable = {}, _comment = '', endHeader = new Headers.MainHeader(); if (buf) { readMainHeader(); } function readEntries() { entryTable = {}; entryList = new Array(endHeader.diskEntries); // total number of entries var index = endHeader.offset; // offset of first CEN header for(var i = 0; i < entryList.length; i++) { var tmp = index, entry = new ZipEntry(); entry.header = buf.slice(tmp, tmp += Utils.Constants.CENHDR); entry.entryName = buf.toString('utf8', tmp, tmp += entry.header.fileNameLength); if (entry.header.extraLength) entry.extra = buf.slice(tmp, tmp += entry.header.extraLength); if (entry.header.commentLength) entry.comment = buf.toString('utf8', tmp, tmp + entry.header.commentLength); index += entry.header.entryHeaderSize; if (!entry.isDirectory) { // read data entry.setCompressedData(buf.slice(entry.header.offset, entry.header.offset + Utils.Constants.LOCHDR + entry.header.compressedSize + entry.entryName.length)); } entryList[i] = entry; entryTable[entry.entryName] = entry; } } function readMainHeader() { var i = buf.length - Utils.Constants.ENDHDR, // END header size n = Math.max(0, i - 0xFFFF), // 0xFFFF is the max zip file comment length endOffset = 0; // Start offset of the END header for (i; i >= n; i--) { if (buf[i] != 0x50) continue; // quick check that the byte is 'P' if (buf.readUInt32LE(i) == Utils.Constants.ENDSIG) { // "PK\005\006" endOffset = i; break; } } if (!endOffset) throw Utils.Errors.INVALID_FORMAT; endHeader.loadFromBinary(buf.slice(endOffset, endOffset + Utils.Constants.ENDHDR)); if (endHeader.commentLength) { _comment = buf.toString('utf8', endOffset + Utils.Constants.ENDHDR); } readEntries(); } return { /** * Returns an array of ZipEntry objects existent in the current opened archive * @return Array */ get entries () { return entryList; }, /** * Archive comment * @return {String} */ get comment () { return _comment; }, set comment(val) { endHeader.commentLength = val.length; _comment = val; }, /** * Returns a reference to the entry with the given name or null if entry is inexistent * * @param entryName * @return ZipEntry */ getEntry : function(/*String*/entryName) { return entryTable[entryName] || null; }, /** * Adds the given entry to the entry list * * @param entry */ setEntry : function(/*ZipEntry*/entry) { entryList.push(entry); entryTable[entry.entryName] = entry; endHeader.totalEntries = entryList.length; }, /** * Removes the entry with the given name from the entry list. * * If the entry is a directory, then all nested files and directories will be removed * @param entryName */ deleteEntry : function(/*String*/entryName) { var entry = entryTable[entryName]; if (entry && entry.isDirectory) { var _self = this; this.getEntryChildren(entry).forEach(function(child) { if (child.entryName != entryName) { _self.deleteEntry(child.entryName) } }) } entryList.slice(entryList.indexOf(entry), 1); delete(entryTable[entryName]); endHeader.totalEntries = entryList.length; }, /** * Iterates and returns all nested files and directories of the given entry * * @param entry * @return Array */ getEntryChildren : function(/*ZipEntry*/entry) { if (entry.isDirectory) { var list = [], name = entry.entryName, len = name.length; entryList.forEach(function(zipEntry) { if (zipEntry.entryName.substr(0, len) == name) { list.push(zipEntry); } }); return list; } return [] }, /** * Returns the zip file * * @return Buffer */ toBuffer : function() { entryList.sort(function(a, b) { var nameA = a.entryName.toLowerCase( ); var nameB = b.entryName.toLowerCase( ); if (nameA < nameB) {return -1} if (nameA > nameB) {return 1} return 0; }); var totalSize = 0, data = [], header = [], dindex = 0; endHeader.size = 0; endHeader.offset = 0; entryList.forEach(function(entry) { entry.header.offset = dindex; var compressedData = entry.getCompressedData(); dindex += compressedData.length; data.push(compressedData); var headerData = entry.packHeader(); header.push(headerData); endHeader.size += headerData.length; totalSize += compressedData.length + headerData.length; }); totalSize += endHeader.mainHeaderSize; // point to end of data and begining of central directory first record endHeader.offset = dindex; dindex = 0; var outBuffer = new Buffer(totalSize); data.forEach(function(content) { content.copy(outBuffer, dindex); // write data dindex += content.length; }); header.forEach(function(content) { content.copy(outBuffer, dindex); // write data dindex += content.length; }); var mainHeader = endHeader.toBinary(); if (_comment) { mainHeader.write(_comment, Utils.Constants.ENDHDR); } mainHeader.copy(outBuffer, dindex); return outBuffer }, toAsyncBuffer : function(/*Function*/callback) { } } };