1- 'use strict' ;
2- const path = require ( 'path' ) ;
3- const fs = require ( 'graceful-fs' ) ;
4- const decompressTar = require ( 'decompress-tar' ) ;
5- const decompressTarbz2 = require ( 'decompress-tarbz2' ) ;
6- const decompressTargz = require ( 'decompress-targz' ) ;
7- const decompressUnzip = require ( 'decompress-unzip' ) ;
8- const makeDir = require ( 'make-dir' ) ;
9- const pify = require ( 'pify' ) ;
10- const stripDirs = require ( 'strip-dirs' ) ;
1+ import { Buffer } from 'node:buffer' ;
2+ import path from 'node:path' ;
3+ import process from 'node:process' ;
4+ import decompressTar from 'decompress-tar' ;
5+ import decompressTarbz2 from 'decompress-tarbz2' ;
6+ import decompressTargz from 'decompress-targz' ;
7+ import decompressUnzip from 'decompress-unzip' ;
8+ import fs from 'graceful-fs' ;
9+ import makeDir from 'make-dir' ;
10+ import pify from 'pify' ;
11+ import stripDirs from 'strip-dirs' ;
1112
1213const fsP = pify ( fs ) ;
1314
14- const runPlugins = ( input , opts ) => {
15- if ( opts . plugins . length === 0 ) {
15+ const runPlugins = ( input , options ) => {
16+ if ( options . plugins . length === 0 ) {
1617 return Promise . resolve ( [ ] ) ;
1718 }
1819
19- return Promise . all ( opts . plugins . map ( x => x ( input , opts ) ) ) . then ( files => files . reduce ( ( a , b ) => a . concat ( b ) ) ) ;
20+ return Promise . all ( options . plugins . map ( x => x ( input , options ) ) )
21+ . then ( files => files . reduce ( ( a , b ) => a . concat ( b ) ) ) ; // eslint-disable-line unicorn/no-array-reduce, unicorn/prefer-spread
2022} ;
2123
22- const safeMakeDir = ( dir , realOutputPath ) => {
23- return fsP . realpath ( dir )
24- . catch ( _ => {
25- const parent = path . dirname ( dir ) ;
26- return safeMakeDir ( parent , realOutputPath ) ;
27- } )
28- . then ( realParentPath => {
29- if ( realParentPath . indexOf ( realOutputPath ) !== 0 ) {
30- throw ( new Error ( 'Refusing to create a directory outside the output path.' ) ) ;
31- }
32-
33- return makeDir ( dir ) . then ( fsP . realpath ) ;
34- } ) ;
35- } ;
24+ const safeMakeDir = ( dir , realOutputPath ) => fsP . realpath ( dir )
25+ . catch ( _ => {
26+ const parent = path . dirname ( dir ) ;
27+ return safeMakeDir ( parent , realOutputPath ) ;
28+ } )
29+ . then ( realParentPath => {
30+ if ( realParentPath . indexOf ( realOutputPath ) !== 0 ) {
31+ throw new Error ( 'Refusing to create a directory outside the output path.' ) ;
32+ }
3633
37- const preventWritingThroughSymlink = ( destination , realOutputPath ) => {
38- return fsP . readlink ( destination )
39- . catch ( _ => {
40- // Either no file exists, or it's not a symlink. In either case, this is
41- // not an escape we need to worry about in this phase.
42- return null ;
43- } )
44- . then ( symlinkPointsTo => {
45- if ( symlinkPointsTo ) {
46- throw new Error ( 'Refusing to write into a symlink' ) ;
47- }
48-
49- // No symlink exists at `destination`, so we can continue
50- return realOutputPath ;
51- } ) ;
52- } ;
34+ return makeDir ( dir ) . then ( fsP . realpath ) ;
35+ } ) ;
36+
37+ const preventWritingThroughSymlink = ( destination , realOutputPath ) => fsP . readlink ( destination )
38+ // Either no file exists, or it's not a symlink. In either case, this is
39+ // not an escape we need to worry about in this phase.
40+ . catch ( _ => null )
41+ . then ( symlinkPointsTo => {
42+ if ( symlinkPointsTo ) {
43+ throw new Error ( 'Refusing to write into a symlink' ) ;
44+ }
45+
46+ // No symlink exists at `destination`, so we can continue
47+ return realOutputPath ;
48+ } ) ;
5349
54- const extractFile = ( input , output , opts ) => runPlugins ( input , opts ) . then ( files => {
55- if ( opts . strip > 0 ) {
50+ const extractFile = ( input , output , options ) => runPlugins ( input , options ) . then ( files => {
51+ if ( options . strip > 0 ) {
5652 files = files
5753 . map ( x => {
58- x . path = stripDirs ( x . path , opts . strip ) ;
54+ x . path = stripDirs ( x . path , options . strip ) ;
5955 return x ;
6056 } )
6157 . filter ( x => x . path !== '.' ) ;
6258 }
6359
64- if ( typeof opts . filter === 'function' ) {
65- files = files . filter ( opts . filter ) ;
60+ if ( typeof options . filter === 'function' ) {
61+ files = files . filter ( options . filter ) ; // eslint-disable-line unicorn/no-array-callback-reference
6662 }
6763
68- if ( typeof opts . map === 'function' ) {
69- files = files . map ( opts . map ) ;
64+ if ( typeof options . map === 'function' ) {
65+ files = files . map ( options . map ) ; // eslint-disable-line unicorn/no-array-callback-reference
7066 }
7167
7268 if ( ! output ) {
@@ -75,7 +71,7 @@ const extractFile = (input, output, opts) => runPlugins(input, opts).then(files
7571
7672 return Promise . all ( files . map ( x => {
7773 const dest = path . join ( output , x . path ) ;
78- const mode = x . mode & ~ process . umask ( ) ;
74+ const mode = x . mode & ~ process . umask ( ) ; // eslint-disable-line no-bitwise
7975 const now = new Date ( ) ;
8076
8177 if ( x . type === 'directory' ) {
@@ -88,26 +84,23 @@ const extractFile = (input, output, opts) => runPlugins(input, opts).then(files
8884
8985 return makeDir ( output )
9086 . then ( outputPath => fsP . realpath ( outputPath ) )
91- . then ( realOutputPath => {
87+ . then ( realOutputPath =>
9288 // Attempt to ensure parent directory exists (failing if it's outside the output dir)
93- return safeMakeDir ( path . dirname ( dest ) , realOutputPath )
94- . then ( ( ) => realOutputPath ) ;
95- } )
89+ safeMakeDir ( path . dirname ( dest ) , realOutputPath ) . then ( ( ) => realOutputPath ) ,
90+ )
9691 . then ( realOutputPath => {
9792 if ( x . type === 'file' ) {
9893 return preventWritingThroughSymlink ( dest , realOutputPath ) ;
9994 }
10095
10196 return realOutputPath ;
10297 } )
103- . then ( realOutputPath => {
104- return fsP . realpath ( path . dirname ( dest ) )
105- . then ( realDestinationDir => {
106- if ( realDestinationDir . indexOf ( realOutputPath ) !== 0 ) {
107- throw ( new Error ( 'Refusing to write outside output directory: ' + realDestinationDir ) ) ;
108- }
109- } ) ;
110- } )
98+ . then ( realOutputPath => fsP . realpath ( path . dirname ( dest ) )
99+ . then ( realDestinationDir => {
100+ if ( realDestinationDir . indexOf ( realOutputPath ) !== 0 ) {
101+ throw new Error ( `Refusing to write outside output directory: ${ realDestinationDir } ` ) ;
102+ }
103+ } ) )
111104 . then ( ( ) => {
112105 if ( x . type === 'link' ) {
113106 return fsP . link ( x . linkname , dest ) ;
@@ -128,24 +121,29 @@ const extractFile = (input, output, opts) => runPlugins(input, opts).then(files
128121 } ) ) ;
129122} ) ;
130123
131- module . exports = ( input , output , opts ) => {
124+ const decompress = ( input , output , options ) => {
132125 if ( typeof input !== 'string' && ! Buffer . isBuffer ( input ) ) {
133126 return Promise . reject ( new TypeError ( 'Input file required' ) ) ;
134127 }
135128
136129 if ( typeof output === 'object' ) {
137- opts = output ;
130+ options = output ;
138131 output = null ;
139132 }
140133
141- opts = Object . assign ( { plugins : [
142- decompressTar ( ) ,
143- decompressTarbz2 ( ) ,
144- decompressTargz ( ) ,
145- decompressUnzip ( )
146- ] } , opts ) ;
134+ options = {
135+ plugins : [
136+ decompressTar ( ) ,
137+ decompressTarbz2 ( ) ,
138+ decompressTargz ( ) ,
139+ decompressUnzip ( ) ,
140+ ] ,
141+ ...options ,
142+ } ;
147143
148144 const read = typeof input === 'string' ? fsP . readFile ( input ) : Promise . resolve ( input ) ;
149145
150- return read . then ( buf => extractFile ( buf , output , opts ) ) ;
146+ return read . then ( buf => extractFile ( buf , output , options ) ) ;
151147} ;
148+
149+ export default decompress ;
0 commit comments