From 899ab31fff9b34bc125faf75b79a89e390deb2cf Mon Sep 17 00:00:00 2001 From: Joram Wilander Date: Fri, 1 Sep 2017 09:00:27 -0400 Subject: Implement experimental REST API endpoints for plugins (#7279) * Implement experimental REST API endpoints for plugins * Updates per feedback and rebase * Update tests * Further updates * Update extraction of plugins * Use OS temp dir for plugins instead of search path * Fail extraction on paths that attempt to traverse upward * Update pluginenv ActivePlugins() --- utils/extract.go | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 utils/extract.go (limited to 'utils/extract.go') diff --git a/utils/extract.go b/utils/extract.go new file mode 100644 index 000000000..0559c6ce8 --- /dev/null +++ b/utils/extract.go @@ -0,0 +1,83 @@ +// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package utils + +import ( + "archive/tar" + "compress/gzip" + "fmt" + "io" + "os" + "path/filepath" +) + +// ExtractTarGz takes in an io.Reader containing the bytes for a .tar.gz file and +// a destination string to extract to. A list of the file and directory names that +// were extracted is returned. +func ExtractTarGz(gzipStream io.Reader, dst string) ([]string, error) { + uncompressedStream, err := gzip.NewReader(gzipStream) + if err != nil { + return nil, fmt.Errorf("ExtractTarGz: NewReader failed: %s", err.Error()) + } + defer uncompressedStream.Close() + + tarReader := tar.NewReader(uncompressedStream) + + filenames := []string{} + + for true { + header, err := tarReader.Next() + + if err == io.EOF { + break + } + + if err != nil { + return nil, fmt.Errorf("ExtractTarGz: Next() failed: %s", err.Error()) + } + + switch header.Typeflag { + case tar.TypeDir: + if PathTraversesUpward(header.Name) { + return nil, fmt.Errorf("ExtractTarGz: path attempts to traverse upwards") + } + + path := filepath.Join(dst, header.Name) + if err := os.Mkdir(path, 0744); err != nil && !os.IsExist(err) { + return nil, fmt.Errorf("ExtractTarGz: Mkdir() failed: %s", err.Error()) + } + + filenames = append(filenames, header.Name) + case tar.TypeReg: + if PathTraversesUpward(header.Name) { + return nil, fmt.Errorf("ExtractTarGz: path attempts to traverse upwards") + } + + path := filepath.Join(dst, header.Name) + dir := filepath.Dir(path) + + if err := os.MkdirAll(dir, 0744); err != nil { + return nil, fmt.Errorf("ExtractTarGz: MkdirAll() failed: %s", err.Error()) + } + + outFile, err := os.Create(path) + if err != nil { + return nil, fmt.Errorf("ExtractTarGz: Create() failed: %s", err.Error()) + } + defer outFile.Close() + if _, err := io.Copy(outFile, tarReader); err != nil { + return nil, fmt.Errorf("ExtractTarGz: Copy() failed: %s", err.Error()) + } + + filenames = append(filenames, header.Name) + default: + return nil, fmt.Errorf( + "ExtractTarGz: unknown type: %v in %v", + header.Typeflag, + header.Name) + } + } + + return filenames, nil +} -- cgit v1.2.3-1-g7c22