Support custom filename encoding option (#72)

This commit is contained in:
Nicholas Sherlock 2018-03-17 12:22:49 +13:00 committed by Jesús Leganés-Combarro
parent a9f74facbf
commit b3b840b14d
5 changed files with 51 additions and 11 deletions

View file

@ -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)
} }

View file

@ -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

View file

@ -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))
})

View file

@ -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

Binary file not shown.