mirror of https://github.com/portainer/portainer
				
				
				
			
		
			
				
	
	
		
			70 lines
		
	
	
		
			1.5 KiB
		
	
	
	
		
			Go
		
	
	
			
		
		
	
	
			70 lines
		
	
	
		
			1.5 KiB
		
	
	
	
		
			Go
		
	
	
package archive
 | 
						|
 | 
						|
import (
 | 
						|
	"archive/zip"
 | 
						|
	"fmt"
 | 
						|
	"io"
 | 
						|
	"os"
 | 
						|
	"path/filepath"
 | 
						|
	"strings"
 | 
						|
 | 
						|
	"github.com/pkg/errors"
 | 
						|
)
 | 
						|
 | 
						|
// UnzipFile will decompress a zip archive, moving all files and folders
 | 
						|
// within the zip file (parameter 1) to an output directory (parameter 2).
 | 
						|
func UnzipFile(src string, dest string) error {
 | 
						|
	r, err := zip.OpenReader(src)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	defer r.Close()
 | 
						|
 | 
						|
	for _, f := range r.File {
 | 
						|
		p := filepath.Join(dest, f.Name)
 | 
						|
 | 
						|
		// Check for ZipSlip. More Info: http://bit.ly/2MsjAWE
 | 
						|
		if !strings.HasPrefix(p, filepath.Clean(dest)+string(os.PathSeparator)) {
 | 
						|
			return fmt.Errorf("%s: illegal file path", p)
 | 
						|
		}
 | 
						|
 | 
						|
		if f.FileInfo().IsDir() {
 | 
						|
			// Make Folder
 | 
						|
			os.MkdirAll(p, os.ModePerm)
 | 
						|
 | 
						|
			continue
 | 
						|
		}
 | 
						|
 | 
						|
		if err := unzipFile(f, p); err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func unzipFile(f *zip.File, p string) error {
 | 
						|
	// Make File
 | 
						|
	if err := os.MkdirAll(filepath.Dir(p), os.ModePerm); err != nil {
 | 
						|
		return errors.Wrapf(err, "unzipFile: can't make a path %s", p)
 | 
						|
	}
 | 
						|
 | 
						|
	outFile, err := os.OpenFile(p, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
 | 
						|
	if err != nil {
 | 
						|
		return errors.Wrapf(err, "unzipFile: can't create file %s", p)
 | 
						|
	}
 | 
						|
	defer outFile.Close()
 | 
						|
 | 
						|
	rc, err := f.Open()
 | 
						|
	if err != nil {
 | 
						|
		return errors.Wrapf(err, "unzipFile: can't open zip file %s in the archive", f.Name)
 | 
						|
	}
 | 
						|
	defer rc.Close()
 | 
						|
 | 
						|
	if _, err = io.Copy(outFile, rc); err != nil {
 | 
						|
		return errors.Wrapf(err, "unzipFile: can't copy an archived file content")
 | 
						|
	}
 | 
						|
 | 
						|
	return nil
 | 
						|
}
 |