Comparing version 0.4.5 to 0.4.6
@@ -96,2 +96,14 @@ /** | ||
Archiver.prototype._normalizeFileData = function(data) { | ||
data = util.defaults(data, { | ||
name: null, | ||
date: null | ||
}); | ||
data.name = util.sanitizeFilePath(data.name); | ||
data.date = util.dateify(data.date); | ||
return data; | ||
}; | ||
Archiver.prototype.append = function(source, data, callback) { | ||
@@ -101,2 +113,13 @@ var sourceCompatMode = false; | ||
data = this._normalizeFileData(data); | ||
if (typeof callback !== 'function') { | ||
callback = this._emitErrorCallback.bind(this); | ||
} | ||
if (typeof data.name !== 'string' || data.name.length === 0) { | ||
callback(new Error('File name is empty or not a valid string value')); | ||
return this; | ||
} | ||
if (typeof source === 'string') { | ||
@@ -114,6 +137,2 @@ source = new Buffer(source, 'utf-8'); | ||
if (typeof callback !== 'function') { | ||
callback = this._emitErrorCallback.bind(this); | ||
} | ||
if (this.archiver.processing || this.archiver.queue.length) { | ||
@@ -120,0 +139,0 @@ this.archiver.queue.push({ |
@@ -37,2 +37,15 @@ /** | ||
ArchiverTar.prototype._normalizeFileData = function(data) { | ||
data = util.defaults(data, { | ||
name: null, | ||
date: null | ||
}); | ||
data.name = util.sanitizeFilePath(data.name); | ||
data.date = util.dateify(data.date); | ||
data.size = 0; | ||
return data; | ||
}; | ||
ArchiverTar.prototype._processFile = function(source, data, callback) { | ||
@@ -42,40 +55,11 @@ var self = this; | ||
var file = util.defaults(data, { | ||
name: null, | ||
comment: '', | ||
date: null, | ||
gid: 0, | ||
mode: null, | ||
mtime: null, | ||
uid: 0 | ||
}); | ||
var file = self.archiver.file = data; | ||
if (typeof file.name !== 'string' || file.name.length === 0) { | ||
callback(new Error('File name is empty or not a valid string value')); | ||
if (file.name.length > 255) { | ||
callback(new Error('Filename "' + file.name + '" is too long even with prefix support [' + file.name.length + '/255]')); | ||
return; | ||
} | ||
file.name = util.sanitizeFilePath(file.name); | ||
file.type = '0'; | ||
file.size = 0; | ||
file.date = util.dateify(file.date); | ||
if (typeof file.mtime !== 'number') { | ||
file.mtime = util.octalDateTime(file.date); | ||
} | ||
file.gid = typeof file.gid === 'number' ? file.gid : 0; | ||
file.mode = typeof file.mode === 'number' ? file.mode : parseInt('777', 8) & 0xfff; | ||
file.uid = typeof file.uid === 'number' ? file.uid : 0; | ||
file.mode = util.padNumber(file.mode, 7); | ||
file.uid = util.padNumber(file.uid, 7); | ||
file.gid = util.padNumber(file.gid, 7); | ||
file.mtime = util.padNumber(file.mtime, 11); | ||
file.offset = self.archiver.pointer; | ||
self.archiver.file = file; | ||
var sourceBuffer; | ||
@@ -85,3 +69,3 @@ var extraBytes; | ||
function onend() { | ||
file.size = util.padNumber(sourceBuffer.length, 11); | ||
file.size = sourceBuffer.length; | ||
extraBytes = self.recordSize - (sourceBuffer.length % self.recordSize || self.recordSize); | ||
@@ -88,0 +72,0 @@ |
@@ -57,3 +57,3 @@ /** | ||
centralDirectoryBuffer = headers.encode('centralHeader', file); | ||
centralDirectoryBuffer = headers.encode('centralDirectory', file); | ||
centralDirectoryBuffers.push(centralDirectoryBuffer); | ||
@@ -68,4 +68,4 @@ ptr += centralDirectoryBuffer.length; | ||
directoryRecords: files.length, | ||
directorySize: cdsize, | ||
directoryOffset: cdoffset, | ||
centralDirectorySize: cdsize, | ||
centralDirectoryOffset: cdoffset, | ||
comment: comment | ||
@@ -82,39 +82,34 @@ }; | ||
ArchiverZip.prototype._processFile = function(source, data, callback) { | ||
var self = this; | ||
self.archiver.processing = true; | ||
var file = util.defaults(data, { | ||
ArchiverZip.prototype._normalizeFileData = function(data) { | ||
data = util.defaults(data, { | ||
name: null, | ||
comment: '', | ||
date: null, | ||
mode: null, | ||
store: false, | ||
lastModifiedDate: null | ||
comment: '' | ||
}); | ||
if (this.options.zlib && this.options.zlib.level === 0) { | ||
file.store = true; | ||
data.name = util.sanitizeFilePath(data.name); | ||
data.date = util.dateify(data.date); | ||
if (typeof data.lastModifiedDate !== 'number') { | ||
data.lastModifiedDate = util.dosDateTime(data.date, this.options.forceUTC); | ||
} | ||
if (typeof file.name !== 'string' || file.name.length === 0) { | ||
callback(new Error('File name is empty or not a valid string value')); | ||
return; | ||
if (this.options.zlib && this.options.zlib.level === 0) { | ||
data.store = true; | ||
} | ||
file.name = util.sanitizeFilePath(file.name); | ||
file.date = util.dateify(file.date); | ||
data.flags = (1<<3) | (1<<11); | ||
data.compressionMethod = data.store ? 0 : 8; | ||
data.uncompressedSize = 0; | ||
data.compressedSize = 0; | ||
if (typeof file.lastModifiedDate !== 'number') { | ||
file.lastModifiedDate = util.dosDateTime(file.date, self.options.forceUTC); | ||
} | ||
return data; | ||
}; | ||
file.versionMadeBy = 20; | ||
file.versionNeededToExtract = 20; | ||
file.flags = (1<<3) | (1<<11); | ||
file.compressionMethod = file.store ? 0 : 8; | ||
file.uncompressedSize = 0; | ||
file.compressedSize = 0; | ||
ArchiverZip.prototype._processFile = function(source, data, callback) { | ||
var self = this; | ||
self.archiver.processing = true; | ||
self.archiver.file = file; | ||
var file = self.archiver.file = data; | ||
@@ -121,0 +116,0 @@ file.offset = self.archiver.pointer; |
@@ -8,99 +8,216 @@ /** | ||
*/ | ||
var path = require('path'); | ||
var inherits = require('util').inherits; | ||
var util = require('../util'); | ||
var headers = {}; | ||
function HeaderTar() { | ||
this.bufferSize = 0; | ||
this.fields = []; | ||
} | ||
headers.file = { | ||
fields: [ | ||
{'field': 'name', 'length': 100, 'type': 'string'}, | ||
{'field': 'mode', 'length': 8, 'type': 'number'}, | ||
{'field': 'uid', 'length': 8, 'type': 'number'}, | ||
{'field': 'gid', 'length': 8, 'type': 'number'}, | ||
{'field': 'size','length': 12, 'type': 'number'}, | ||
{'field': 'mtime', 'length': 12, 'type': 'number'}, | ||
{'field': 'checksum', 'length': 8, 'type': 'string', 'default': util.repeat(' ', 8)}, | ||
{'field': 'type', 'length': 1, 'type': 'number'}, | ||
{'field': 'linkName', 'length': 100, 'type': 'string'}, | ||
{'field': 'ustar', 'length': 8, 'type': 'string', 'default': 'ustar '}, | ||
{'field': 'owner', 'length': 32, 'type': 'string'}, | ||
{'field': 'group', 'length': 32, 'type': 'string'}, | ||
{'field': 'majorNumber', 'length': 8, 'type': 'number'}, | ||
{'field': 'minorNumber', 'length': 8, 'type': 'number'}, | ||
{'field': 'filenamePrefix', 'length': 155, 'type': 'string'}, | ||
{'field': 'padding', 'length': 12} | ||
], | ||
function HeaderTarFile() { | ||
HeaderTar.call(this); | ||
toBuffer: function(data) { | ||
var self = this; | ||
this.bufferSize = 512; | ||
this.fields = [ | ||
{field: 'name', len: 100, type: 'string'}, | ||
{field: 'mode', len: 8, type: 'number'}, | ||
{field: 'uid', len: 8, type: 'number'}, | ||
{field: 'gid', len: 8, type: 'number'}, | ||
{field: 'size',len: 12, type: 'number'}, | ||
{field: 'mtime', len: 12, type: 'number'}, | ||
{field: 'checksum', len: 8, type: 'number'}, | ||
{field: 'type', len: 1, type: 'string', def: '0'}, | ||
{field: 'linkName', len: 100, type: 'string'}, | ||
{field: 'ustar', len: 6, type: 'string', def: 'ustar'}, | ||
{field: 'ustarVersion', len: 2, type: 'string', def: '00'}, | ||
{field: 'owner', len: 32, type: 'string', def: 'root'}, | ||
{field: 'group', len: 32, type: 'string', def: 'root'}, | ||
{field: 'devMajor', len: 8, type: 'number'}, | ||
{field: 'devMinor', len: 8, type: 'number'}, | ||
{field: 'prefix', len: 155, type: 'string'}, | ||
{field: 'padding', len: 12, type: 'padding'} | ||
]; | ||
} | ||
inherits(HeaderTarFile, HeaderTar); | ||
var buffer = util.cleanBuffer(512); | ||
var offset = 0; | ||
HeaderTarFile.prototype.toBuffer = function(data) { | ||
var self = this; | ||
var buf = util.cleanBuffer(self.bufferSize); | ||
var offset = 0; | ||
var val; | ||
var val; | ||
var fallback; | ||
self.fields.forEach(function(value) { | ||
val = data[value.field] || value.default || ''; | ||
data = self._normalize(data); | ||
buffer.write(val, offset); | ||
offset += value.length; | ||
}); | ||
self.fields.forEach(function(value) { | ||
fallback = (value.type === 'number') ? 0 : ''; | ||
val = data[value.field] || value.def || fallback; | ||
var checksum = self.createChecksum(buffer); | ||
for (var i = 0, length = 6; i < length; i += 1) { | ||
buffer[i + 148] = checksum.charCodeAt(i); | ||
if (value.field === 'checksum') { | ||
val = util.repeat(' ', 8); | ||
} else if (value.type === 'number') { | ||
val = self._prepNumeric(val, value.len); | ||
} else if (value.type === 'string') { | ||
if (typeof val === 'number') { | ||
val = val.toString(); | ||
} | ||
} | ||
buffer[154] = 0; | ||
buffer[155] = 0x20; | ||
buf.write(val, offset); | ||
return buffer; | ||
}, | ||
offset += value.len; | ||
}); | ||
toObject: function(buffer) { | ||
var self = this; | ||
var checksum = this._createChecksum(buf); | ||
var data = {}; | ||
var offset = 0; | ||
for (var i = 0, length = 6; i < length; i += 1) { | ||
buf[i + 148] = checksum.charCodeAt(i); | ||
} | ||
self.fields.forEach(function(value) { | ||
data[value.field] = buffer.toString('utf8', offset, offset + (value.length - 1)).replace(/\u0000.*/, ''); | ||
offset += value.length; | ||
}); | ||
buf[154] = 0; | ||
buf[155] = 0x20; | ||
delete data.padding; | ||
return buf; | ||
}; | ||
return data; | ||
}, | ||
HeaderTarFile.prototype.toObject = function(buf) { | ||
var self = this; | ||
createChecksum: function(buffer) { | ||
var checksum = 0; | ||
for (var i = 0, length = buffer.length; i < length; i += 1) { | ||
checksum += buffer[i]; | ||
} | ||
var data = {}; | ||
var offset = 0; | ||
var result; | ||
checksum = checksum.toString(8); | ||
while (checksum.length < 6) { | ||
checksum = '0' + checksum; | ||
self.fields.forEach(function(value) { | ||
result = buf.toString('utf8', offset, offset + value.len).replace(/\0+$/, ''); | ||
if (value.field === 'ustar') { | ||
result = (result === 'ustar'); | ||
} else if (value.field === 'mtime') { | ||
result = self._parseNumeric(result); | ||
data['date'] = util.convertDateTimeEpoch(result); | ||
} else if (value.type === 'number') { | ||
result = self._parseNumeric(result); | ||
} | ||
return checksum; | ||
data[value.field] = result; | ||
offset += value.len; | ||
}); | ||
delete data.padding; | ||
return data; | ||
}; | ||
HeaderTarFile.prototype._normalize = function(data) { | ||
data.name = util.sanitizeFilePath(data.name); | ||
data.mode = typeof data.mode === 'number' ? data.mode : 0664; | ||
data.mode = data.mode & 0777; | ||
data.uid = typeof data.uid === 'number' ? data.uid : 0; | ||
data.gid = typeof data.gid === 'number' ? data.gid : 0; | ||
if (typeof data.mtime !== 'number') { | ||
data.date = util.dateify(data.date); | ||
data.mtime = util.epochDateTime(data.date); | ||
} else { | ||
data.date = util.convertDateTimeEpoch(data.mtime); | ||
} | ||
var pathParts = this._splitFilePath(data.name); | ||
data.name = pathParts[0]; | ||
data.prefix = pathParts[1]; | ||
return data; | ||
}; | ||
HeaderTarFile.prototype._createChecksum = function(buf) { | ||
var checksum = 0; | ||
for (var i = 0, length = buf.length; i < length; i += 1) { | ||
checksum += buf[i]; | ||
} | ||
checksum = checksum.toString(8); | ||
while (checksum.length < 6) { | ||
checksum = '0' + checksum; | ||
} | ||
return checksum; | ||
}; | ||
var MAXNUM = { | ||
12: 077777777777, | ||
11: 07777777777, | ||
8: 07777777, | ||
7: 0777777 | ||
}; | ||
HeaderTarFile.prototype._prepNumeric = function(num, len) { | ||
num = num || 0; | ||
var max = MAXNUM[len] || 0; | ||
if (num > max || num < 0) { | ||
// need an extended header if negative or too big. someday just not today.. | ||
} | ||
var str = Math.floor(num).toString(8); | ||
if (num < MAXNUM[len - 1]) { | ||
str += ' '; | ||
} | ||
if (str.length < len) { | ||
str = util.repeat('0', len - str.length) + str; | ||
} | ||
return str; | ||
}; | ||
HeaderTarFile.prototype._parseNumeric = function(str) { | ||
var res = parseInt(str.trim(), 8); | ||
return isNaN(res) ? null : res; | ||
}; | ||
HeaderTarFile.prototype._splitFilePath = function(filepath) { | ||
var fileName = filepath; | ||
var filePrefix = ''; | ||
var sepIndex; | ||
if (filepath.length > 100 && filepath.length <= 255) { | ||
sepIndex = filepath.substring(0, 155).lastIndexOf('/'); | ||
if (sepIndex !== -1) { | ||
filePrefix = filepath.substring(0, sepIndex); | ||
fileName = filepath.substring(sepIndex + 1); | ||
} | ||
} | ||
return [fileName, filePrefix]; | ||
}; | ||
var headers = { | ||
file: new HeaderTarFile() | ||
}; | ||
var encode = exports.encode = function(type, data) { | ||
if (typeof headers[type].toBuffer === 'function') { | ||
return headers[type].toBuffer(data); | ||
} else { | ||
return false; | ||
if (!headers[type] || typeof headers[type].toBuffer !== 'function') { | ||
throw new Error('Unknown encode type'); | ||
} | ||
return headers[type].toBuffer(data); | ||
}; | ||
var decode = exports.decode = function(type, data) { | ||
if (typeof headers[type].toObject === 'function') { | ||
return headers[type].toObject(data); | ||
} else { | ||
return false; | ||
var decode = exports.decode = function(type, buf) { | ||
if (!headers[type] || typeof headers[type].toObject !== 'function') { | ||
throw new Error('Unknown decode type'); | ||
} | ||
}; | ||
return headers[type].toObject(buf); | ||
}; | ||
exports.file = HeaderTarFile; |
@@ -9,208 +9,176 @@ /** | ||
var headers = {}; | ||
var inherits = require('util').inherits; | ||
headers.file = { | ||
fields: [ | ||
{'field': 'signature', 'length': 4, 'type': 'UInt32LE', 'default': 0x04034b50}, | ||
{'field': 'versionNeededToExtract', 'length': 2, 'type': 'UInt16LE'}, | ||
{'field': 'flags', 'length': 2, 'type': 'UInt16LE'}, | ||
{'field': 'compressionMethod', 'length': 2, 'type': 'UInt16LE'}, | ||
{'field': 'lastModifiedDate', 'length': 4, 'type': 'UInt32LE'}, | ||
{'field': 'crc32', 'length': 4, 'type': 'Int32LE', 'default': 0}, | ||
{'field': 'compressedSize', 'length': 4, 'type': 'UInt32LE'}, | ||
{'field': 'uncompressedSize', 'length': 4, 'type': 'UInt32LE'}, | ||
{'field': 'filenameLength', 'length': 2, 'type': 'UInt16LE'}, | ||
{'field': 'extraFieldLength', 'length': 2, 'type': 'UInt16LE'}, | ||
{'field': 'name', 'length': -1, 'type': 'string'}, | ||
{'field': 'extraField', 'length': -1, 'type': 'string'} | ||
], | ||
function HeaderZip() { | ||
this.bufferSize = 0; | ||
this.fields = []; | ||
} | ||
toBuffer: function(data) { | ||
var self = this; | ||
HeaderZip.prototype.toBuffer = function(data) { | ||
var buf = new Buffer(this.bufferSize); | ||
var offset = 0; | ||
var val; | ||
var fallback; | ||
var buffer = new Buffer(1024); | ||
var offset = 0; | ||
var val; | ||
var fallback; | ||
data = this._normalize(data); | ||
self.fields.forEach(function(value) { | ||
fallback = (value.type === 'string') ? '' : 0; | ||
val = data[value.field] || value.default || fallback; | ||
this.fields.forEach(function(value) { | ||
fallback = (value.type === 'string') ? '' : 0; | ||
val = data[value.field] || value.def || fallback; | ||
if (value.field === 'name') { | ||
value.length = buffer.write(val, offset); | ||
buffer.writeUInt16LE(value.length, 26); | ||
} else if (value.field === 'extraField') { | ||
value.length = (val.length > 0) ? buffer.write(val, offset) : 0; | ||
buffer.writeUInt16LE(value.length, 28); | ||
} else if (value.type === 'UInt32LE') { | ||
buffer.writeUInt32LE(val, offset); | ||
} else if (value.type === 'Int32LE') { | ||
buffer.writeInt32LE(val, offset); | ||
} else if (value.type === 'UInt16LE') { | ||
buffer.writeUInt16LE(val, offset); | ||
} else { | ||
buffer.write(val, offset); | ||
} | ||
if (value.lenField) { | ||
value.len = (data[value.lenField] > 0) ? buf.write(val, offset) : 0; | ||
} else if (typeof buf['write' + value.type] === 'function') { | ||
buf['write' + value.type](val, offset); | ||
} else if (val.length > 0) { | ||
buf.write(val, offset); | ||
} | ||
offset += value.length; | ||
}); | ||
offset += value.len; | ||
}); | ||
return buffer.slice(0, offset); | ||
} | ||
return buf.slice(0, offset); | ||
}; | ||
headers.fileDescriptor = { | ||
fields: [ | ||
{'field': 'signature', 'length': 4, 'type': 'UInt32LE', 'default': 0x08074b50}, | ||
{'field': 'crc32', 'length': 4, 'type': 'Int32LE'}, | ||
{'field': 'compressedSize', 'length': 4, 'type': 'UInt32LE'}, | ||
{'field': 'uncompressedSize', 'length': 4, 'type': 'UInt32LE'} | ||
], | ||
HeaderZip.prototype.toObject = function(buf) { | ||
var data = {}; | ||
var offset = 0; | ||
toBuffer: function(data) { | ||
var self = this; | ||
this.fields.forEach(function(value) { | ||
if (value.lenField) { | ||
data[value.field] = (data[value.lenField] > 0) ? buf.toString('utf8', offset) : null; | ||
} else if (typeof buf['read' + value.type] === 'function') { | ||
data[value.field] = buf['read' + value.type](offset); | ||
} else { | ||
data[value.field] = buf.toString(null, offset, value.len); | ||
} | ||
var buffer = new Buffer(16); | ||
var offset = 0; | ||
var val; | ||
offset += value.len; | ||
}); | ||
self.fields.forEach(function(value) { | ||
val = data[value.field] || value.default || 0; | ||
return data; | ||
}; | ||
if (value.type === 'UInt32LE') { | ||
buffer.writeUInt32LE(val, offset); | ||
} else if (value.type === 'Int32LE') { | ||
buffer.writeInt32LE(val, offset); | ||
} | ||
HeaderZip.prototype._normalize = function(data) { | ||
if (data.name) { | ||
data.filenameLength = data.name.length; | ||
} | ||
offset += value.length; | ||
}); | ||
if (data.comment) { | ||
data.commentLength = data.comment.length; | ||
} | ||
return buffer; | ||
if (data.extraField) { | ||
data.extraFieldLength = data.extraField.length; | ||
} | ||
return data; | ||
}; | ||
headers.centralHeader = { | ||
fields: [ | ||
{'field': 'signature', 'length': 4, 'type': 'UInt32LE', 'default': 0x02014b50}, | ||
{'field': 'versionMadeBy', 'length': 2, 'type': 'UInt16LE'}, | ||
{'field': 'versionNeededToExtract', 'length': 2, 'type': 'UInt16LE'}, | ||
{'field': 'flags', 'length': 2, 'type': 'UInt16LE'}, | ||
{'field': 'compressionMethod', 'length': 2, 'type': 'UInt16LE'}, | ||
{'field': 'lastModifiedDate', 'length': 4, 'type': 'UInt32LE'}, | ||
{'field': 'crc32', 'length': 4, 'type': 'Int32LE'}, | ||
{'field': 'compressedSize', 'length': 4, 'type': 'UInt32LE'}, | ||
{'field': 'uncompressedSize', 'length': 4, 'type': 'UInt32LE'}, | ||
{'field': 'filenameLength', 'length': 2, 'type': 'UInt16LE'}, | ||
{'field': 'extraFieldLength', 'length': 2, 'type': 'UInt16LE'}, | ||
{'field': 'commentLength', 'length': 2, 'type': 'UInt16LE'}, | ||
{'field': 'diskNumberStart', 'length': 2, 'type': 'UInt16LE'}, | ||
{'field': 'internalFileAttributes', 'length': 2, 'type': 'UInt16LE'}, | ||
{'field': 'externalFileAttributes', 'length': 4, 'type': 'UInt32LE'}, | ||
{'field': 'offset', 'length': 4, 'type': 'UInt32LE'}, | ||
{'field': 'name', 'length': -1, 'type': 'string'}, | ||
{'field': 'extraField', 'length': -1, 'type': 'string'}, | ||
{'field': 'comment', 'length': -1, 'type': 'string'} | ||
], | ||
function HeaderZipFile() { | ||
HeaderZip.call(this); | ||
toBuffer: function(data) { | ||
var self = this; | ||
this.bufferSize = 1024; | ||
this.fields = [ | ||
{field: 'signature', len: 4, type: 'UInt32LE', def: 0x04034b50}, | ||
{field: 'versionNeededToExtract', len: 2, type: 'UInt16LE', def: 20}, | ||
{field: 'flags', len: 2, type: 'UInt16LE'}, | ||
{field: 'compressionMethod', len: 2, type: 'UInt16LE'}, | ||
{field: 'lastModifiedDate', len: 4, type: 'UInt32LE'}, | ||
{field: 'crc32', len: 4, type: 'Int32LE', def: 0}, | ||
{field: 'compressedSize', len: 4, type: 'UInt32LE'}, | ||
{field: 'uncompressedSize', len: 4, type: 'UInt32LE'}, | ||
{field: 'filenameLength', len: 2, type: 'UInt16LE'}, | ||
{field: 'extraFieldLength', len: 2, type: 'UInt16LE'}, | ||
{field: 'name', len: -1, lenField: 'filenameLength', type: 'string'}, | ||
{field: 'extraField', len: -1, lenField: 'extraFieldLength', type: 'string'} | ||
]; | ||
} | ||
inherits(HeaderZipFile, HeaderZip); | ||
var buffer = new Buffer(1024); | ||
var offset = 0; | ||
var val; | ||
var fallback; | ||
function HeaderZipFileDescriptor() { | ||
HeaderZip.call(this); | ||
var nameLength; | ||
this.bufferSize = 16; | ||
this.fields = [ | ||
{field: 'signature', len: 4, type: 'UInt32LE', def: 0x08074b50}, | ||
{field: 'crc32', len: 4, type: 'Int32LE'}, | ||
{field: 'compressedSize', len: 4, type: 'UInt32LE'}, | ||
{field: 'uncompressedSize', len: 4, type: 'UInt32LE'} | ||
]; | ||
} | ||
inherits(HeaderZipFileDescriptor, HeaderZip); | ||
self.fields.forEach(function(value) { | ||
fallback = (value.type === 'string') ? '' : 0; | ||
val = data[value.field] || value.default || fallback; | ||
function HeaderZipCentralDirectory() { | ||
HeaderZip.call(this); | ||
if (value.field === 'name') { | ||
value.length = buffer.write(val, offset); | ||
buffer.writeUInt16LE(value.length, 28); | ||
} else if (value.field === 'extraField') { | ||
value.length = (val.length > 0) ? buffer.write(val, offset) : 0; | ||
buffer.writeUInt16LE(value.length, 30); | ||
} else if (value.field === 'comment') { | ||
value.length = (val.length > 0) ? buffer.write(val, offset) : 0; | ||
buffer.writeUInt16LE(value.length, 32); | ||
} else if (value.type === 'UInt32LE') { | ||
buffer.writeUInt32LE(val, offset); | ||
} else if (value.type === 'Int32LE') { | ||
buffer.writeInt32LE(val, offset); | ||
} else if (value.type === 'UInt16LE') { | ||
buffer.writeUInt16LE(val, offset); | ||
} else { | ||
buffer.write(val, offset); | ||
} | ||
this.bufferSize = 1024; | ||
this.fields = [ | ||
{field: 'signature', len: 4, type: 'UInt32LE', def: 0x02014b50}, | ||
{field: 'versionMadeBy', len: 2, type: 'UInt16LE', def: 20}, | ||
{field: 'versionNeededToExtract', len: 2, type: 'UInt16LE', def: 20}, | ||
{field: 'flags', len: 2, type: 'UInt16LE'}, | ||
{field: 'compressionMethod', len: 2, type: 'UInt16LE'}, | ||
{field: 'lastModifiedDate', len: 4, type: 'UInt32LE'}, | ||
{field: 'crc32', len: 4, type: 'Int32LE'}, | ||
{field: 'compressedSize', len: 4, type: 'UInt32LE'}, | ||
{field: 'uncompressedSize', len: 4, type: 'UInt32LE'}, | ||
{field: 'filenameLength', len: 2, type: 'UInt16LE'}, | ||
{field: 'extraFieldLength', len: 2, type: 'UInt16LE'}, | ||
{field: 'commentLength', len: 2, type: 'UInt16LE'}, | ||
{field: 'diskNumberStart', len: 2, type: 'UInt16LE'}, | ||
{field: 'internalFileAttributes', len: 2, type: 'UInt16LE'}, | ||
{field: 'externalFileAttributes', len: 4, type: 'UInt32LE'}, | ||
{field: 'offset', len: 4, type: 'UInt32LE'}, | ||
{field: 'name', len: -1, lenField: 'filenameLength', type: 'string'}, | ||
{field: 'extraField', len: -1, lenField: 'extraFieldLength', type: 'string'}, | ||
{field: 'comment', len: -1, lenField: 'commentLength', type: 'string'} | ||
]; | ||
} | ||
inherits(HeaderZipCentralDirectory, HeaderZip); | ||
offset += value.length; | ||
}); | ||
function HeaderZipCentralFooter() { | ||
HeaderZip.call(this); | ||
return buffer.slice(0, offset); | ||
} | ||
this.bufferSize = 512; | ||
this.fields = [ | ||
{field: 'signature', len: 4, type: 'UInt32LE', def: 0x06054b50}, | ||
{field: 'diskNumber', len: 2, type: 'UInt16LE'}, | ||
{field: 'diskNumberStart', len: 2, type: 'UInt16LE'}, | ||
{field: 'directoryRecordsDisk', len: 2, type: 'UInt16LE'}, | ||
{field: 'directoryRecords', len: 2, type: 'UInt16LE'}, | ||
{field: 'centralDirectorySize', len: 4, type: 'UInt32LE'}, | ||
{field: 'centralDirectoryOffset', len: 4, type: 'UInt32LE'}, | ||
{field: 'commentLength', len: 2, type: 'UInt16LE'}, | ||
{field: 'comment', len: -1, lenField: 'commentLength', type: 'string'} | ||
]; | ||
} | ||
inherits(HeaderZipCentralFooter, HeaderZip); | ||
var headers = { | ||
file: new HeaderZipFile(), | ||
fileDescriptor: new HeaderZipFileDescriptor(), | ||
centralDirectory: new HeaderZipCentralDirectory(), | ||
centralFooter: new HeaderZipCentralFooter() | ||
}; | ||
headers.centralFooter = { | ||
fields: [ | ||
{'field': 'signature', 'length': 4, 'type': 'UInt32LE', 'default': 0x06054b50}, | ||
{'field': 'diskNumber', 'length': 2, 'type': 'UInt16LE'}, | ||
{'field': 'diskNumberStart', 'length': 2, 'type': 'UInt16LE'}, | ||
{'field': 'directoryRecordsDisk', 'length': 2, 'type': 'UInt16LE'}, | ||
{'field': 'directoryRecords', 'length': 2, 'type': 'UInt16LE'}, | ||
{'field': 'directorySize', 'length': 4, 'type': 'UInt32LE'}, | ||
{'field': 'directoryOffset', 'length': 4, 'type': 'UInt32LE'},, | ||
{'field': 'commentLength', 'length': 2, 'type': 'UInt16LE'}, | ||
{'field': 'comment', 'length': -1, 'type': 'string'} | ||
], | ||
var encode = exports.encode = function(type, data) { | ||
if (!headers[type] || typeof headers[type].toBuffer !== 'function') { | ||
throw new Error('Unknown encode type'); | ||
} | ||
toBuffer: function(data) { | ||
var self = this; | ||
return headers[type].toBuffer(data); | ||
}; | ||
var buffer = new Buffer(512); | ||
var offset = 0; | ||
var val; | ||
var fallback; | ||
self.fields.forEach(function(value) { | ||
fallback = (value.type === 'string') ? '' : 0; | ||
val = data[value.field] || value.default || fallback; | ||
if (value.field === 'comment') { | ||
value.length = (val.length > 0) ? buffer.write(val, offset) : 0; | ||
buffer.writeUInt16LE(value.length, 20); | ||
} else if (value.type === 'UInt32LE') { | ||
buffer.writeUInt32LE(val, offset); | ||
} else if (value.type === 'Int32LE') { | ||
buffer.writeInt32LE(val, offset); | ||
} else if (value.type === 'UInt16LE') { | ||
buffer.writeUInt16LE(val, offset); | ||
} else { | ||
buffer.write(val, offset); | ||
} | ||
offset += value.length; | ||
}); | ||
return buffer.slice(0, offset); | ||
var decode = exports.decode = function(type, buf) { | ||
if (!headers[type] || typeof headers[type].toObject !== 'function') { | ||
throw new Error('Unknown decode type'); | ||
} | ||
}; | ||
var encode = exports.encode = function(type, data) { | ||
if (typeof headers[type].toBuffer === 'function') { | ||
return headers[type].toBuffer(data); | ||
} else { | ||
return false; | ||
} | ||
return headers[type].toObject(buf); | ||
}; | ||
var decode = exports.decode = function(type, data) { | ||
if (typeof headers[type].toObject === 'function') { | ||
return headers[type].toObject(data); | ||
} else { | ||
return false; | ||
} | ||
}; | ||
exports.file = HeaderZipFile; | ||
exports.fileDescriptor = HeaderZipFileDescriptor; | ||
exports.centralDirectory = HeaderZipCentralDirectory; | ||
exports.centralFooter = HeaderZipCentralFooter; |
@@ -72,2 +72,8 @@ /** | ||
util.convertDateTimeEpoch = function(input) { | ||
input = input * 1000; | ||
return new Date(input); | ||
}; | ||
util.convertDateTimeOctal = function(input) { | ||
@@ -80,13 +86,13 @@ input = parseInt(input, 8) * 1000; | ||
util.dateify = function(dateish) { | ||
var date; | ||
dateish = dateish || new Date(); | ||
if (dateish instanceof Date) { | ||
date = dateish; | ||
dateish = dateish; | ||
} else if (typeof dateish === 'string') { | ||
date = new Date(dateish); | ||
dateish = new Date(dateish); | ||
} else { | ||
date = new Date(); | ||
dateish = new Date(); | ||
} | ||
return date; | ||
return dateish; | ||
}; | ||
@@ -150,2 +156,8 @@ | ||
util.epochDateTime = function(d) { | ||
d = (d instanceof Date) ? d : new Date(); | ||
return Math.round(d / 1000); | ||
}; | ||
util.keys = function(object) { | ||
@@ -201,2 +213,3 @@ if (!util.isObject(object)) { | ||
util.sanitizeFilePath = function(filepath) { | ||
filepath = filepath || ''; | ||
filepath = path.normalize(filepath); | ||
@@ -212,4 +225,61 @@ filepath = util.unixifyPath(filepath); | ||
util.scanBuffer = function(buf, search, offset) { | ||
if (!Buffer.isBuffer(buf)) { | ||
return false; | ||
} | ||
var origBufLength = buf.length; | ||
var negative = false; | ||
var wasOffset = false; | ||
if (offset) { | ||
if (offset < 0) { | ||
offset = offset * -1; | ||
negative = true; | ||
} | ||
if (offset <= origBufLength) { | ||
if (negative) { | ||
offset = offset * -1; | ||
} | ||
wasOffset = true; | ||
buf = buf.slice(offset); | ||
} | ||
} | ||
if (typeof search === 'string') { | ||
search = new Buffer(search); | ||
} else if (!Buffer.isBuffer(search)) { | ||
return false; | ||
} | ||
// simple but slow string search | ||
for (var i = 0; i <= buf.length - search.length + 1; i++) { | ||
for (var j = 0; j < search.length && buf[i + j] === search[j]; j++); | ||
if (j === search.length) { | ||
if (wasOffset) { | ||
return origBufLength - (buf.length - i); | ||
} | ||
return i; | ||
} | ||
} | ||
return false; | ||
}; | ||
util.scanBufferUInt32LE = function(buf, search, offset) { | ||
if (!search) { | ||
return false; | ||
} | ||
var searchBuf = new Buffer(4); | ||
searchBuf.writeUInt32LE(search, 0); | ||
return util.scanBuffer(buf, searchBuf, offset); | ||
}; | ||
util.unixifyPath = function(filepath) { | ||
return filepath.replace(/\\/g, '/'); | ||
}; |
{ | ||
"name": "archiver", | ||
"version": "0.4.5", | ||
"version": "0.4.6", | ||
"description": "Creates Archives (ZIP) via Node Streams.", | ||
@@ -35,5 +35,5 @@ "homepage": "https://github.com/ctalkington/node-archiver", | ||
"devDependencies": { | ||
"chai": "~1.6.0", | ||
"mocha": "~1.9.0", | ||
"rimraf": "~2.1.4", | ||
"chai": "~1.7.1", | ||
"mocha": "~1.11.0", | ||
"rimraf": "~2.2.0", | ||
"mkdirp": "~0.3.5", | ||
@@ -40,0 +40,0 @@ "stream-bench": "~0.1.2" |
@@ -1,2 +0,2 @@ | ||
# Archiver v0.4.5 [![Build Status](https://secure.travis-ci.org/ctalkington/node-archiver.png?branch=master)](http://travis-ci.org/ctalkington/node-archiver) | ||
# Archiver v0.4.6 [![Build Status](https://secure.travis-ci.org/ctalkington/node-archiver.png?branch=master)](http://travis-ci.org/ctalkington/node-archiver) | ||
@@ -3,0 +3,0 @@ Creates Archives (Zip, Tar) via Node Streams. Depends on Node's built-in zlib module for compression available since version 0.6.3. |
@@ -38,3 +38,3 @@ /*global before,describe,it */ | ||
testStream.on('close', function() { | ||
assert.equal(testStream.digest, 'e87af3cdd4b01bb72ebab46baa97ee1eb814a1d3'); | ||
assert.equal(testStream.digest, '3a8a9ff17087129cc05dc88be86573ecf3f9ca56'); | ||
done(); | ||
@@ -55,3 +55,3 @@ }); | ||
testStream.on('close', function() { | ||
assert.equal(testStream.digest, 'da02a931d670f725c0de20ef30b112b53d149a3d'); | ||
assert.equal(testStream.digest, '3e3271c503deeba9abe5031df6bca636f1eb115b'); | ||
done(); | ||
@@ -74,3 +74,3 @@ }); | ||
testStream.on('close', function() { | ||
assert.equal(testStream.digest, '76a580762b214851ec9c45a2915356b005ec068b'); | ||
assert.equal(testStream.digest, '54a94b8b72eac5f6acf5c1ec84aa2e69969267ca'); | ||
done(); | ||
@@ -97,3 +97,3 @@ }); | ||
testStream.on('close', function() { | ||
assert.equal(testStream.digest, '333f843838ba5ee7727b3cc8afa017cab3d70d72'); | ||
assert.equal(testStream.digest, 'fb620048e1bceefb0be06d3f18ea00929951b105'); | ||
done(); | ||
@@ -114,3 +114,3 @@ }); | ||
testStream.on('close', function() { | ||
assert.equal(testStream.digest, '0f2cfcb20ebc1958c2a9e78ad9d969fb7cae19df'); | ||
assert.equal(testStream.digest, '1437ef391a7c2c0de180bddff21b98c2f9778331'); | ||
done(); | ||
@@ -127,2 +127,23 @@ }); | ||
}); | ||
it('should use prefix for deep paths', function(done) { | ||
var archive = archiver('tar'); | ||
var testStream = new WriteHashStream('tmp/feature-prefix.tar'); | ||
testStream.on('close', function() { | ||
assert.equal(testStream.digest, 'aeb2496b2bd7458931ba942dba2b4bf28cbc187c'); | ||
done(); | ||
}); | ||
archive.pipe(testStream); | ||
var deepPath = 'vvmbtqhysigpregbdrc/pyqaznbelhppibmbykz/'; | ||
deepPath += 'qcbclwjhktiazmhnsjt/kpsgdfyfkarbvnlinrt/'; | ||
deepPath += 'holobndxfccyecblhcc/'; | ||
deepPath += deepPath; | ||
archive | ||
.append('deep path', { name: deepPath + 'file.txt', date: testDate }) | ||
.finalize(); | ||
}); | ||
}); | ||
@@ -129,0 +150,0 @@ |
@@ -12,2 +12,3 @@ /*global before,describe,it */ | ||
var testDate = new Date('Jan 03 2013 14:26:38 GMT'); | ||
var testDateEpoch = 1357223198; | ||
@@ -17,15 +18,4 @@ describe('headers', function() { | ||
describe('tar', function() { | ||
var fileObj = { | ||
name: 'test.txt', | ||
date: testDate, | ||
comment: '', | ||
gid: '0000000', | ||
mode: '0000777', | ||
mtime: '12071312436', | ||
uid: '0000000', | ||
type: '0', | ||
size: '00000000023' | ||
}; | ||
var fileFixture = fs.readFileSync('test/fixtures/headers/tar-file.bin'); | ||
var filePrefixFixture = fs.readFileSync('test/fixtures/headers/tar-fileprefix.bin'); | ||
@@ -35,3 +25,10 @@ describe('#encode(type, object)', function() { | ||
describe('type->file', function() { | ||
var actual = tar.encode('file', fileObj); | ||
var actual = tar.encode('file', { | ||
name: 'test.txt', | ||
date: testDate, | ||
mode: 0644, | ||
size: 23, | ||
owner: 'test', | ||
group: 'test' | ||
}); | ||
@@ -47,4 +44,21 @@ it('should return an instance of Buffer', function() { | ||
it('should match provided fixture', function() { | ||
assert.equal(actual.toString(), fileFixture.toString()); | ||
//fs.writeFileSync('test/fixtures/headers/tar-file.bin', actual); | ||
assert.deepEqual(actual.toString(), fileFixture.toString()); | ||
}); | ||
it('should use prefix for deep paths', function() { | ||
var deepPath = 'vvmbtqhysigpregbdrc/pyqaznbelhppibmbykz/'; | ||
deepPath += 'qcbclwjhktiazmhnsjt/kpsgdfyfkarbvnlinrt/'; | ||
deepPath += 'holobndxfccyecblhcc/'; | ||
deepPath += deepPath; | ||
var actual = tar.encode('file', { | ||
name: deepPath + 'test.txt', | ||
date: testDate, | ||
size: 23 | ||
}); | ||
//fs.writeFileSync('test/fixtures/headers/tar-fileprefix.bin', actual); | ||
assert.deepEqual(actual.toString(), filePrefixFixture.toString()); | ||
}); | ||
}); | ||
@@ -59,5 +73,28 @@ | ||
it('should match provided checksum', function() { | ||
assert.equal(actual.checksum, '007425'); | ||
it('should return an object', function() { | ||
assert.isObject(actual); | ||
}); | ||
it('should properly decode pre-posix attributes', function() { | ||
assert.equal(actual.name, 'test.txt'); | ||
assert.equal(actual.uid, 0); | ||
assert.equal(actual.gid, 0); | ||
assert.equal(actual.mode, 420); | ||
assert.equal(actual.size, 23); | ||
assert.deepEqual(actual.date, testDate); | ||
assert.equal(actual.mtime, testDateEpoch); | ||
assert.equal(actual.checksum, 5730); | ||
assert.equal(actual.type, '0'); | ||
assert.equal(actual.linkName, ''); | ||
}); | ||
it('should properly decode ustar attributes', function() { | ||
assert.equal(actual.ustar, true); | ||
assert.equal(actual.ustarVersion, '00'); | ||
assert.equal(actual.owner, 'test'); | ||
assert.equal(actual.group, 'test'); | ||
assert.equal(actual.devMajor, 0); | ||
assert.equal(actual.devMinor, 0); | ||
assert.equal(actual.prefix, ''); | ||
}); | ||
}); | ||
@@ -67,56 +104,50 @@ | ||
}); | ||
describe('HeaderTarFile', function() { | ||
var HeaderTarFile = tar.file; | ||
var thing = new HeaderTarFile(); | ||
describe('#_parseNumeric(num, len)', function() { | ||
it('should convert octal strings to numeric values', function() { | ||
assert.equal(thing._parseNumeric('21'), 17); | ||
assert.equal(thing._parseNumeric('0021'), 17); | ||
}); | ||
}); | ||
describe('zip', function() { | ||
var fileObj = { | ||
name: 'test.txt', | ||
date: testDate, | ||
comment: '', | ||
mode: null, | ||
store: true, | ||
lastModifiedDate: 1109619539, | ||
versionMadeBy: 20, | ||
versionNeededToExtract: 20, | ||
flags: 2056, | ||
compressionMethod: 0, | ||
uncompressedSize: 0, | ||
compressedSize: 0, | ||
offset: 0 | ||
}; | ||
describe('#_prepNumeric(num, len)', function() { | ||
it('should convert numeric values to octal strings', function() { | ||
assert.equal(thing._prepNumeric(17, 2), '21'); | ||
var fileDescriptorObj = { | ||
crc32: 585446183, | ||
uncompressedSize: 19, | ||
compressedSize: 19, | ||
}; | ||
}); | ||
var centralHeaderObj = { | ||
name: 'test.txt', | ||
date: testDate, | ||
store: true, | ||
comment: '', | ||
mode: null, | ||
lastModifiedDate: 1109619539, | ||
versionMadeBy: 20, | ||
versionNeededToExtract: 20, | ||
flags: 2056, | ||
compressionMethod: 0, | ||
uncompressedSize: 19, | ||
compressedSize: 19, | ||
offset: 0, | ||
crc32: 585446183 | ||
}; | ||
it('should zero pad when needed', function() { | ||
assert.equal(thing._prepNumeric(17, 4), '0021'); | ||
}); | ||
}); | ||
var centralFooterObj = { | ||
directoryRecordsDisk: 1, | ||
directoryRecords: 1, | ||
directorySize: 56, | ||
directoryOffset: 73, | ||
comment: '' | ||
}; | ||
describe('#_splitFilePath(filepath)', function() { | ||
it('should split a filepath into a name and prefix', function() { | ||
var deepPath = 'vvmbtqhysigpregbdrc/pyqaznbelhppibmbykz/'; | ||
deepPath += 'qcbclwjhktiazmhnsjt/kpsgdfyfkarbvnlinrt/'; | ||
deepPath += 'holobndxfccyecblhcc/'; | ||
deepPath += deepPath; | ||
var actual = thing._splitFilePath(deepPath + 'file.txt'); | ||
assert.deepEqual(actual, [ | ||
"qcbclwjhktiazmhnsjt/kpsgdfyfkarbvnlinrt/holobndxfccyecblhcc/file.txt", | ||
"vvmbtqhysigpregbdrc/pyqaznbelhppibmbykz/qcbclwjhktiazmhnsjt/kpsgdfyfkarbvnlinrt/" + | ||
"holobndxfccyecblhcc/vvmbtqhysigpregbdrc/pyqaznbelhppibmbykz" | ||
]); | ||
}); | ||
}); | ||
}); | ||
}); | ||
describe('zip', function() { | ||
var fileFixture = fs.readFileSync('test/fixtures/headers/zip-file.bin'); | ||
var fileDescriptorFixture = fs.readFileSync('test/fixtures/headers/zip-filedescriptor.bin'); | ||
var centralHeaderFixture = fs.readFileSync('test/fixtures/headers/zip-centralheader.bin'); | ||
var centralDirectoryFixture = fs.readFileSync('test/fixtures/headers/zip-centralheader.bin'); | ||
var centralFooterFixture = fs.readFileSync('test/fixtures/headers/zip-centralfooter.bin'); | ||
@@ -127,3 +158,18 @@ | ||
describe('type->file', function() { | ||
var actual = zip.encode('file', fileObj); | ||
var actual = zip.encode('file', { | ||
name: 'test.txt', | ||
filenameLength: 8, | ||
date: testDate, | ||
comment: '', | ||
mode: null, | ||
store: true, | ||
lastModifiedDate: 1109619539, | ||
versionMadeBy: 20, | ||
versionNeededToExtract: 20, | ||
flags: 2056, | ||
compressionMethod: 0, | ||
uncompressedSize: 0, | ||
compressedSize: 0, | ||
offset: 0 | ||
}); | ||
@@ -140,3 +186,7 @@ it('should return an instance of Buffer', function() { | ||
describe('type->fileDescriptor', function() { | ||
var actual = zip.encode('fileDescriptor', fileDescriptorObj); | ||
var actual = zip.encode('fileDescriptor', { | ||
crc32: 585446183, | ||
uncompressedSize: 19, | ||
compressedSize: 19, | ||
}); | ||
@@ -152,4 +202,20 @@ it('should return an instance of Buffer', function() { | ||
describe('type->centralHeader', function() { | ||
var actual = zip.encode('centralHeader', centralHeaderObj); | ||
describe('type->centralDirectory', function() { | ||
var actual = zip.encode('centralDirectory', { | ||
name: 'test.txt', | ||
filenameLength: 8, | ||
date: testDate, | ||
store: true, | ||
comment: '', | ||
mode: null, | ||
lastModifiedDate: 1109619539, | ||
versionMadeBy: 20, | ||
versionNeededToExtract: 20, | ||
flags: 2056, | ||
compressionMethod: 0, | ||
uncompressedSize: 19, | ||
compressedSize: 19, | ||
offset: 0, | ||
crc32: 585446183 | ||
}); | ||
@@ -161,3 +227,3 @@ it('should return an instance of Buffer', function() { | ||
it('should match provided fixture', function() { | ||
assert.deepEqual(actual, centralHeaderFixture); | ||
assert.deepEqual(actual, centralDirectoryFixture); | ||
}); | ||
@@ -167,3 +233,9 @@ }); | ||
describe('type->centralFooter', function() { | ||
var actual = zip.encode('centralFooter', centralFooterObj); | ||
var actual = zip.encode('centralFooter', { | ||
directoryRecordsDisk: 1, | ||
directoryRecords: 1, | ||
centralDirectorySize: 56, | ||
centralDirectoryOffset: 73, | ||
comment: '' | ||
}); | ||
@@ -183,2 +255,98 @@ it('should return an instance of Buffer', function() { | ||
describe('type->file', function() { | ||
var actual = zip.decode('file', fileFixture); | ||
it('should return an object', function() { | ||
assert.isObject(actual); | ||
}); | ||
it('should match provided fixture', function() { | ||
assert.deepEqual(actual, { | ||
signature: 67324752, | ||
versionNeededToExtract: 20, | ||
flags: 2056, | ||
compressionMethod: 0, | ||
lastModifiedDate: 1109619539, | ||
crc32: 0, | ||
compressedSize: 0, | ||
uncompressedSize: 0, | ||
filenameLength: 8, | ||
extraFieldLength: 0, | ||
name: 'test.txt', | ||
extraField: null | ||
}); | ||
}); | ||
}); | ||
describe('type->fileDescriptor', function() { | ||
var actual = zip.decode('fileDescriptor', fileDescriptorFixture); | ||
it('should return an object', function() { | ||
assert.isObject(actual); | ||
}); | ||
it('should match provided fixture', function() { | ||
assert.deepEqual(actual, { | ||
signature: 134695760, | ||
crc32: 585446183, | ||
uncompressedSize: 19, | ||
compressedSize: 19, | ||
}); | ||
}); | ||
}); | ||
describe('type->centralDirectory', function() { | ||
var actual = zip.decode('centralDirectory', centralDirectoryFixture); | ||
it('should return an object', function() { | ||
assert.isObject(actual); | ||
}); | ||
it('should match provided fixture', function() { | ||
assert.deepEqual(actual, { | ||
signature: 33639248, | ||
versionMadeBy: 20, | ||
versionNeededToExtract: 20, | ||
flags: 2056, | ||
compressionMethod: 0, | ||
lastModifiedDate: 1109619539, | ||
crc32: 585446183, | ||
compressedSize: 19, | ||
uncompressedSize: 19, | ||
filenameLength: 8, | ||
extraFieldLength: 0, | ||
commentLength: 0, | ||
diskNumberStart: 0, | ||
internalFileAttributes: 0, | ||
externalFileAttributes: 0, | ||
offset: 0, | ||
name: 'test.txt', | ||
extraField: null, | ||
comment: null | ||
}); | ||
}); | ||
}); | ||
describe('type->centralFooter', function() { | ||
var actual = zip.decode('centralFooter', centralFooterFixture); | ||
it('should return an object', function() { | ||
assert.isObject(actual); | ||
}); | ||
it('should match provided fixture', function() { | ||
assert.deepEqual(actual, { | ||
signature: 101010256, | ||
diskNumber: 0, | ||
diskNumberStart: 0, | ||
directoryRecordsDisk: 1, | ||
directoryRecords: 1, | ||
centralDirectorySize: 56, | ||
centralDirectoryOffset: 73, | ||
commentLength: 0, | ||
comment: null | ||
}); | ||
}); | ||
}); | ||
}); | ||
@@ -185,0 +353,0 @@ |
@@ -19,5 +19,6 @@ /*global describe,it */ | ||
var testDate = new Date('Jan 03 2013 14:26:38 GMT'); | ||
var testDateOctal = 12071312436; | ||
var testDateDos = 1109607251; | ||
var testDateDosUTC = 1109619539; | ||
var testDateEpoch = 1357223198; | ||
var testDateOctal = 12071312436; | ||
@@ -153,2 +154,8 @@ var testTimezoneOffset = testDate.getTimezoneOffset(); | ||
describe('convertDateTimeEpoch(input)', function() { | ||
it('should convert epoch input into an instance of Date', function() { | ||
assert.deepEqual(utils.convertDateTimeEpoch(testDateEpoch), testDate); | ||
}); | ||
}); | ||
describe('convertDateTimeOctal(input)', function() { | ||
@@ -240,2 +247,8 @@ it('should convert octal input into an instance of Date', function() { | ||
describe('epochDateTime(date)', function() { | ||
it('should convert date into its epoch representation', function() { | ||
assert.equal(utils.epochDateTime(testDate), testDateEpoch); | ||
}); | ||
}); | ||
describe('isStream(source)', function() { | ||
@@ -242,0 +255,0 @@ it('should return true if source is a stream', function() { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
82275
38
1982