github.com/hashicorp/go-getter/v2@v2.2.2/decompress.go (about)

     1  package getter
     2  
     3  import (
     4  	"os"
     5  	"strings"
     6  )
     7  
     8  // Decompressor defines the interface that must be implemented to add
     9  // support for decompressing a type.
    10  //
    11  // Important: if you're implementing a decompressor, please use the
    12  // containsDotDot helper in this file to ensure that files can't be
    13  // decompressed outside of the specified directory.
    14  type Decompressor interface {
    15  	// Decompress should decompress src to dst. dir specifies whether dst
    16  	// is a directory or single file. src is guaranteed to be a single file
    17  	// that exists. dst is not guaranteed to exist already.
    18  	Decompress(dst, src string, dir bool, umask os.FileMode) error
    19  }
    20  
    21  // LimitedDecompressors creates the set of Decompressors, but with each compressor configured
    22  // with the given filesLimit and/or fileSizeLimit where applicable.
    23  func LimitedDecompressors(filesLimit int, fileSizeLimit int64) map[string]Decompressor {
    24  	tarDecompressor := &TarDecompressor{FilesLimit: filesLimit, FileSizeLimit: fileSizeLimit}
    25  	tbzDecompressor := &TarBzip2Decompressor{FilesLimit: filesLimit, FileSizeLimit: fileSizeLimit}
    26  	tgzDecompressor := &TarGzipDecompressor{FilesLimit: filesLimit, FileSizeLimit: fileSizeLimit}
    27  	txzDecompressor := &TarXzDecompressor{FilesLimit: filesLimit, FileSizeLimit: fileSizeLimit}
    28  	tzstDecompressor := &TarZstdDecompressor{FilesLimit: filesLimit, FileSizeLimit: fileSizeLimit}
    29  	bzipDecompressor := &Bzip2Decompressor{FileSizeLimit: fileSizeLimit}
    30  	gzipDecompressor := &GzipDecompressor{FileSizeLimit: fileSizeLimit}
    31  	xzDecompressor := &XzDecompressor{FileSizeLimit: fileSizeLimit}
    32  	zipDecompressor := &ZipDecompressor{FilesLimit: filesLimit, FileSizeLimit: fileSizeLimit}
    33  	zstDecompressor := &ZstdDecompressor{FileSizeLimit: fileSizeLimit}
    34  
    35  	return map[string]Decompressor{
    36  		"bz2":     bzipDecompressor,
    37  		"gz":      gzipDecompressor,
    38  		"xz":      xzDecompressor,
    39  		"tar":     tarDecompressor,
    40  		"tar.bz2": tbzDecompressor,
    41  		"tar.gz":  tgzDecompressor,
    42  		"tar.xz":  txzDecompressor,
    43  		"tar.zst": tzstDecompressor,
    44  		"tbz2":    tbzDecompressor,
    45  		"tgz":     tgzDecompressor,
    46  		"txz":     txzDecompressor,
    47  		"tzst":    tzstDecompressor,
    48  		"zip":     zipDecompressor,
    49  		"zst":     zstDecompressor,
    50  	}
    51  }
    52  
    53  const (
    54  	noFilesLimit    = 0
    55  	noFileSizeLimit = 0
    56  )
    57  
    58  // Decompressors is the mapping of extension to the Decompressor implementation
    59  // configured with default settings that will decompress that extension/type.
    60  //
    61  // Note: these decompressors by default do not limit the number of files or the
    62  // maximum file size created by the decompressed payload.
    63  var Decompressors = LimitedDecompressors(noFilesLimit, noFileSizeLimit)
    64  
    65  // containsDotDot checks if the filepath value v contains a ".." entry.
    66  // This will check filepath components by splitting along / or \. This
    67  // function is copied directly from the Go net/http implementation.
    68  func containsDotDot(v string) bool {
    69  	if !strings.Contains(v, "..") {
    70  		return false
    71  	}
    72  	for _, ent := range strings.FieldsFunc(v, isSlashRune) {
    73  		if ent == ".." {
    74  			return true
    75  		}
    76  	}
    77  	return false
    78  }
    79  
    80  func isSlashRune(r rune) bool { return r == '/' || r == '\\' }