Skip to content

Commit

Permalink
Add portable: true option to omit OS indicator
Browse files Browse the repository at this point in the history
  • Loading branch information
isaacs committed Oct 5, 2019
1 parent 00cf6c0 commit 5a8638d
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 3 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,10 @@ const decode = new zlib.BrotliDecompress()
const output = whereToWriteTheDecodedData()
input.pipe(decode).pipe(output)
```

## REPRODUCIBLE BUILDS

To create reproducible gzip compressed files across different operating
systems, set `portable: true` in the options. This causes minizlib to set
the `OS` indicator in byte 9 of the extended gzip header to `0xFF` for
'unknown'.
24 changes: 21 additions & 3 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const Minipass = require('minipass')

const OriginalBufferConcat = Buffer.concat

const _superWrite = Symbol('_superWrite')
class ZlibError extends Error {
constructor (err) {
super('zlib: ' + err.message)
Expand Down Expand Up @@ -164,19 +165,23 @@ class ZlibBase extends Minipass {
if (Array.isArray(result) && result.length > 0) {
// The first buffer is always `handle._outBuffer`, which would be
// re-used for later invocations; so, we always have to copy that one.
writeReturn = super.write(Buffer.from(result[0]))
writeReturn = this[_superWrite](Buffer.from(result[0]))
for (let i = 1; i < result.length; i++) {
writeReturn = super.write(result[i])
writeReturn = this[_superWrite](result[i])
}
} else {
writeReturn = super.write(Buffer.from(result))
writeReturn = this[_superWrite](Buffer.from(result))
}
}

if (cb)
cb()
return writeReturn
}

[_superWrite] (data) {
return super.write(data)
}
}

class Zlib extends ZlibBase {
Expand Down Expand Up @@ -243,9 +248,22 @@ class Inflate extends Zlib {
}

// gzip - bigger header, same deflate compression
const _portable = Symbol('_portable')
class Gzip extends Zlib {
constructor (opts) {
super(opts, 'Gzip')
this[_portable] = opts && !!opts.portable
}

[_superWrite] (data) {
if (!this[_portable])
return super[_superWrite](data)

// we'll always get the header emitted in one first chunk
// overwrite the OS indicator byte with 0xFF
this[_portable] = false
data[9] = 255
return super[_superWrite](data)
}
}

Expand Down
11 changes: 11 additions & 0 deletions test/omit-os-signifier.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const zlib = require('../')

const data = Buffer.from('hello world')
const t = require('tap')

const stream = new zlib.Gzip({portable: true})
const res = stream.end(data).read()
t.equal(res[9], 255)
const unc = new zlib.Gunzip({encoding: 'utf8'}).end(res).read()
t.equal(unc, 'hello world')
t.end()

0 comments on commit 5a8638d

Please sign in to comment.