Support custom filename encoding option (#72)
This commit is contained in:
parent
a9f74facbf
commit
b3b840b14d
5 changed files with 51 additions and 11 deletions
|
@ -43,6 +43,8 @@ var Extract = function (opts) {
|
|||
if (!(this instanceof Extract)) return new Extract(opts)
|
||||
Writable.call(this, opts)
|
||||
|
||||
opts = opts || {}
|
||||
|
||||
this._offset = 0
|
||||
this._buffer = bl()
|
||||
this._missing = 0
|
||||
|
@ -102,14 +104,14 @@ var Extract = function (opts) {
|
|||
|
||||
var ongnulongpath = function () {
|
||||
var size = self._header.size
|
||||
this._gnuLongPath = headers.decodeLongPath(b.slice(0, size))
|
||||
this._gnuLongPath = headers.decodeLongPath(b.slice(0, size), opts.filenameEncoding)
|
||||
b.consume(size)
|
||||
onstreamend()
|
||||
}
|
||||
|
||||
var ongnulonglinkpath = function () {
|
||||
var size = self._header.size
|
||||
this._gnuLongLinkPath = headers.decodeLongPath(b.slice(0, size))
|
||||
this._gnuLongLinkPath = headers.decodeLongPath(b.slice(0, size), opts.filenameEncoding)
|
||||
b.consume(size)
|
||||
onstreamend()
|
||||
}
|
||||
|
@ -118,7 +120,7 @@ var Extract = function (opts) {
|
|||
var offset = self._offset
|
||||
var header
|
||||
try {
|
||||
header = self._header = headers.decode(b.slice(0, 512))
|
||||
header = self._header = headers.decode(b.slice(0, 512), opts.filenameEncoding)
|
||||
} catch (err) {
|
||||
self.emit('error', err)
|
||||
}
|
||||
|
|
16
headers.js
16
headers.js
|
@ -149,8 +149,8 @@ var decodeOct = function (val, offset, length) {
|
|||
}
|
||||
}
|
||||
|
||||
var decodeStr = function (val, offset, length) {
|
||||
return val.slice(offset, indexOf(val, 0, offset, offset + length)).toString()
|
||||
var decodeStr = function (val, offset, length, encoding) {
|
||||
return val.slice(offset, indexOf(val, 0, offset, offset + length)).toString(encoding)
|
||||
}
|
||||
|
||||
var addLength = function (str) {
|
||||
|
@ -161,8 +161,8 @@ var addLength = function (str) {
|
|||
return (len + digits) + str
|
||||
}
|
||||
|
||||
exports.decodeLongPath = function (buf) {
|
||||
return decodeStr(buf, 0, buf.length)
|
||||
exports.decodeLongPath = function (buf, encoding) {
|
||||
return decodeStr(buf, 0, buf.length, encoding)
|
||||
}
|
||||
|
||||
exports.encodePax = function (opts) { // TODO: encode more stuff in pax
|
||||
|
@ -240,23 +240,23 @@ exports.encode = function (opts) {
|
|||
return buf
|
||||
}
|
||||
|
||||
exports.decode = function (buf) {
|
||||
exports.decode = function (buf, filenameEncoding) {
|
||||
var typeflag = buf[156] === 0 ? 0 : buf[156] - ZERO_OFFSET
|
||||
|
||||
var name = decodeStr(buf, 0, 100)
|
||||
var name = decodeStr(buf, 0, 100, filenameEncoding)
|
||||
var mode = decodeOct(buf, 100, 8)
|
||||
var uid = decodeOct(buf, 108, 8)
|
||||
var gid = decodeOct(buf, 116, 8)
|
||||
var size = decodeOct(buf, 124, 12)
|
||||
var mtime = decodeOct(buf, 136, 12)
|
||||
var type = toType(typeflag)
|
||||
var linkname = buf[157] === 0 ? null : decodeStr(buf, 157, 100)
|
||||
var linkname = buf[157] === 0 ? null : decodeStr(buf, 157, 100, filenameEncoding)
|
||||
var uname = decodeStr(buf, 265, 32)
|
||||
var gname = decodeStr(buf, 297, 32)
|
||||
var devmajor = decodeOct(buf, 329, 8)
|
||||
var devminor = decodeOct(buf, 337, 8)
|
||||
|
||||
if (buf[345]) name = decodeStr(buf, 345, 155) + '/' + name
|
||||
if (buf[345]) name = decodeStr(buf, 345, 155, filenameEncoding) + '/' + name
|
||||
|
||||
// to support old tar versions that use trailing / to indicate dirs
|
||||
if (typeflag === 0 && name && name[name.length - 1] === '/') typeflag = 5
|
||||
|
|
|
@ -589,3 +589,40 @@ test('huge', function (t) {
|
|||
var reader = fs.createReadStream(fixtures.HUGE)
|
||||
reader.pipe(gunzip).pipe(extract)
|
||||
})
|
||||
|
||||
test('latin-1', function (t) { // can unpack filenames encoded in latin-1
|
||||
t.plan(3)
|
||||
|
||||
// This is the older name for the "latin1" encoding in Node
|
||||
var extract = tar.extract({ filenameEncoding: 'binary' })
|
||||
var noEntries = false
|
||||
|
||||
extract.on('entry', function (header, stream, callback) {
|
||||
t.deepEqual(header, {
|
||||
name: 'En français, s\'il vous plaît?.txt',
|
||||
mode: parseInt('644', 8),
|
||||
uid: 0,
|
||||
gid: 0,
|
||||
size: 14,
|
||||
mtime: new Date(1495941034000),
|
||||
type: 'file',
|
||||
linkname: null,
|
||||
uname: 'root',
|
||||
gname: 'root',
|
||||
devmajor: 0,
|
||||
devminor: 0
|
||||
})
|
||||
|
||||
stream.pipe(concat(function (data) {
|
||||
noEntries = true
|
||||
t.same(data.toString(), 'Hello, world!\n')
|
||||
callback()
|
||||
}))
|
||||
})
|
||||
|
||||
extract.on('finish', function () {
|
||||
t.ok(noEntries)
|
||||
})
|
||||
|
||||
extract.end(fs.readFileSync(fixtures.LATIN1_TAR))
|
||||
})
|
||||
|
|
1
test/fixtures/index.js
vendored
1
test/fixtures/index.js
vendored
|
@ -15,3 +15,4 @@ exports.BASE_256_UID_GID = path.join(__dirname, 'base-256-uid-gid.tar')
|
|||
exports.LARGE_UID_GID = path.join(__dirname, 'large-uid-gid.tar')
|
||||
exports.BASE_256_SIZE = path.join(__dirname, 'base-256-size.tar')
|
||||
exports.HUGE = path.join(__dirname, 'huge.tar.gz')
|
||||
exports.LATIN1_TAR = path.join(__dirname, 'latin1.tar')
|
||||
|
|
BIN
test/fixtures/latin1.tar
vendored
Normal file
BIN
test/fixtures/latin1.tar
vendored
Normal file
Binary file not shown.
Loading…
Reference in a new issue