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)
|
if (!(this instanceof Extract)) return new Extract(opts)
|
||||||
Writable.call(this, opts)
|
Writable.call(this, opts)
|
||||||
|
|
||||||
|
opts = opts || {}
|
||||||
|
|
||||||
this._offset = 0
|
this._offset = 0
|
||||||
this._buffer = bl()
|
this._buffer = bl()
|
||||||
this._missing = 0
|
this._missing = 0
|
||||||
|
@ -102,14 +104,14 @@ var Extract = function (opts) {
|
||||||
|
|
||||||
var ongnulongpath = function () {
|
var ongnulongpath = function () {
|
||||||
var size = self._header.size
|
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)
|
b.consume(size)
|
||||||
onstreamend()
|
onstreamend()
|
||||||
}
|
}
|
||||||
|
|
||||||
var ongnulonglinkpath = function () {
|
var ongnulonglinkpath = function () {
|
||||||
var size = self._header.size
|
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)
|
b.consume(size)
|
||||||
onstreamend()
|
onstreamend()
|
||||||
}
|
}
|
||||||
|
@ -118,7 +120,7 @@ var Extract = function (opts) {
|
||||||
var offset = self._offset
|
var offset = self._offset
|
||||||
var header
|
var header
|
||||||
try {
|
try {
|
||||||
header = self._header = headers.decode(b.slice(0, 512))
|
header = self._header = headers.decode(b.slice(0, 512), opts.filenameEncoding)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
self.emit('error', 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) {
|
var decodeStr = function (val, offset, length, encoding) {
|
||||||
return val.slice(offset, indexOf(val, 0, offset, offset + length)).toString()
|
return val.slice(offset, indexOf(val, 0, offset, offset + length)).toString(encoding)
|
||||||
}
|
}
|
||||||
|
|
||||||
var addLength = function (str) {
|
var addLength = function (str) {
|
||||||
|
@ -161,8 +161,8 @@ var addLength = function (str) {
|
||||||
return (len + digits) + str
|
return (len + digits) + str
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.decodeLongPath = function (buf) {
|
exports.decodeLongPath = function (buf, encoding) {
|
||||||
return decodeStr(buf, 0, buf.length)
|
return decodeStr(buf, 0, buf.length, encoding)
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.encodePax = function (opts) { // TODO: encode more stuff in pax
|
exports.encodePax = function (opts) { // TODO: encode more stuff in pax
|
||||||
|
@ -240,23 +240,23 @@ exports.encode = function (opts) {
|
||||||
return buf
|
return buf
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.decode = function (buf) {
|
exports.decode = function (buf, filenameEncoding) {
|
||||||
var typeflag = buf[156] === 0 ? 0 : buf[156] - ZERO_OFFSET
|
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 mode = decodeOct(buf, 100, 8)
|
||||||
var uid = decodeOct(buf, 108, 8)
|
var uid = decodeOct(buf, 108, 8)
|
||||||
var gid = decodeOct(buf, 116, 8)
|
var gid = decodeOct(buf, 116, 8)
|
||||||
var size = decodeOct(buf, 124, 12)
|
var size = decodeOct(buf, 124, 12)
|
||||||
var mtime = decodeOct(buf, 136, 12)
|
var mtime = decodeOct(buf, 136, 12)
|
||||||
var type = toType(typeflag)
|
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 uname = decodeStr(buf, 265, 32)
|
||||||
var gname = decodeStr(buf, 297, 32)
|
var gname = decodeStr(buf, 297, 32)
|
||||||
var devmajor = decodeOct(buf, 329, 8)
|
var devmajor = decodeOct(buf, 329, 8)
|
||||||
var devminor = decodeOct(buf, 337, 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
|
// to support old tar versions that use trailing / to indicate dirs
|
||||||
if (typeflag === 0 && name && name[name.length - 1] === '/') typeflag = 5
|
if (typeflag === 0 && name && name[name.length - 1] === '/') typeflag = 5
|
||||||
|
|
|
@ -589,3 +589,40 @@ test('huge', function (t) {
|
||||||
var reader = fs.createReadStream(fixtures.HUGE)
|
var reader = fs.createReadStream(fixtures.HUGE)
|
||||||
reader.pipe(gunzip).pipe(extract)
|
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.LARGE_UID_GID = path.join(__dirname, 'large-uid-gid.tar')
|
||||||
exports.BASE_256_SIZE = path.join(__dirname, 'base-256-size.tar')
|
exports.BASE_256_SIZE = path.join(__dirname, 'base-256-size.tar')
|
||||||
exports.HUGE = path.join(__dirname, 'huge.tar.gz')
|
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