11 // ZipDecompressor is an implementation of Decompressor that can
12 // decompress zip files.
13 type ZipDecompressor struct{}
15 func (d *ZipDecompressor) Decompress(dst, src string, dir bool) error {
16 // If we're going into a directory we should make that first
19 mkdir = filepath.Dir(dst)
21 if err := os.MkdirAll(mkdir, 0755); err != nil {
26 zipR, err := zip.OpenReader(src)
32 // Check the zip integrity
33 if len(zipR.File) == 0 {
35 return fmt.Errorf("empty archive: %s", src)
37 if !dir && len(zipR.File) > 1 {
38 return fmt.Errorf("expected a single file: %s", src)
41 // Go through and unarchive
42 for _, f := range zipR.File {
45 // Disallow parent traversal
46 if containsDotDot(f.Name) {
47 return fmt.Errorf("entry contains '..': %s", f.Name)
50 path = filepath.Join(path, f.Name)
53 if f.FileInfo().IsDir() {
55 return fmt.Errorf("expected a single file: %s", src)
58 // A directory, just make the directory and continue unarchiving...
59 if err := os.MkdirAll(path, 0755); err != nil {
66 // Create the enclosing directories if we must. ZIP files aren't
67 // required to contain entries for just the directories so this
70 if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
75 // Open the file for reading
81 // Open the file for writing
82 dstF, err := os.Create(path)
87 _, err = io.Copy(dstF, srcF)
95 if err := os.Chmod(path, f.Mode()); err != nil {