|
1 | 1 | package xtractr |
2 | 2 |
|
3 | 3 | import ( |
4 | | - "archive/zip" |
5 | | - "fmt" |
6 | | - "os" |
7 | | - "path/filepath" |
8 | | - "strings" |
| 4 | + "archive/zip" |
| 5 | + "fmt" |
| 6 | + "os" |
| 7 | + "path/filepath" |
| 8 | + "strings" |
9 | 9 | ) |
10 | 10 |
|
11 | 11 | /* How to extract a ZIP file. */ |
12 | 12 |
|
13 | 13 | // ExtractZIP extracts a zip file.. to a destination. Simple enough. |
14 | 14 | func ExtractZIP(xFile *XFile) (int64, []string, error) { |
15 | | - zipReader, err := zip.OpenReader(xFile.FilePath) |
16 | | - if err != nil { |
17 | | - return 0, nil, fmt.Errorf("zip.OpenReader: %w", err) |
18 | | - } |
19 | | - defer zipReader.Close() |
| 15 | + zipReader, err := zip.OpenReader(xFile.FilePath) |
| 16 | + if err != nil { |
| 17 | + return 0, nil, fmt.Errorf("zip.OpenReader: %w", err) |
| 18 | + } |
| 19 | + defer zipReader.Close() |
20 | 20 |
|
21 | | - files := []string{} |
22 | | - size := int64(0) |
| 21 | + files := []string{} |
| 22 | + size := int64(0) |
23 | 23 |
|
24 | | - for _, zipFile := range zipReader.Reader.File { |
25 | | - fSize, err := xFile.unzip(zipFile) |
26 | | - if err != nil { |
27 | | - return size, files, fmt.Errorf("%s: %w", xFile.FilePath, err) |
28 | | - } |
| 24 | + for _, zipFile := range zipReader.Reader.File { |
| 25 | + fSize, err := xFile.unzip(zipFile) |
| 26 | + if err != nil { |
| 27 | + return size, files, fmt.Errorf("%s: %w", xFile.FilePath, err) |
| 28 | + } |
29 | 29 |
|
30 | | - files = append(files, filepath.Join(xFile.OutputDir, zipFile.Name)) //nolint: gosec |
31 | | - size += fSize |
32 | | - } |
| 30 | + files = append(files, filepath.Join(xFile.OutputDir, zipFile.Name)) //nolint:gosec |
| 31 | + size += fSize |
| 32 | + } |
33 | 33 |
|
34 | | - return size, files, nil |
| 34 | + return size, files, nil |
35 | 35 | } |
36 | 36 |
|
37 | 37 | func (x *XFile) unzip(zipFile *zip.File) (int64, error) { //nolint:dupl |
38 | | - wfile := x.clean(zipFile.Name) |
39 | | - if !strings.HasPrefix(wfile, x.OutputDir) { |
40 | | - // The file being written is trying to write outside of our base path. Malicious archive? |
41 | | - return 0, fmt.Errorf("%s: %w: %s (from: %s)", zipFile.FileInfo().Name(), ErrInvalidPath, wfile, zipFile.Name) |
42 | | - } |
| 38 | + wfile := x.clean(zipFile.Name) |
| 39 | + outputDir := filepath.Clean(x.OutputDir) |
| 40 | + if !strings.HasPrefix(wfile, outputDir) { |
| 41 | + // The file being written is trying to write outside of our base path. Malicious archive? |
| 42 | + return 0, fmt.Errorf("%s: %w: %s (from: %s)", zipFile.FileInfo().Name(), ErrInvalidPath, wfile, zipFile.Name) |
| 43 | + } |
43 | 44 |
|
44 | | - if strings.HasSuffix(wfile, "/") || zipFile.FileInfo().IsDir() { |
45 | | - if err := os.MkdirAll(wfile, x.DirMode); err != nil { |
46 | | - return 0, fmt.Errorf("making zipFile dir: %w", err) |
47 | | - } |
| 45 | + if strings.HasSuffix(wfile, "/") || zipFile.FileInfo().IsDir() { |
| 46 | + if err := os.MkdirAll(wfile, x.DirMode); err != nil { |
| 47 | + return 0, fmt.Errorf("making zipFile dir: %w", err) |
| 48 | + } |
48 | 49 |
|
49 | | - return 0, nil |
50 | | - } |
| 50 | + return 0, nil |
| 51 | + } |
51 | 52 |
|
52 | | - zFile, err := zipFile.Open() |
53 | | - if err != nil { |
54 | | - return 0, fmt.Errorf("zipFile.Open: %w", err) |
55 | | - } |
56 | | - defer zFile.Close() |
| 53 | + zFile, err := zipFile.Open() |
| 54 | + if err != nil { |
| 55 | + return 0, fmt.Errorf("zipFile.Open: %w", err) |
| 56 | + } |
| 57 | + defer zFile.Close() |
57 | 58 |
|
58 | | - s, err := writeFile(wfile, zFile, x.FileMode, x.DirMode) |
59 | | - if err != nil { |
60 | | - return s, fmt.Errorf("%s: %w: %s (from: %s)", zipFile.FileInfo().Name(), err, wfile, zipFile.Name) |
61 | | - } |
| 59 | + s, err := writeFile(wfile, zFile, x.FileMode, x.DirMode) |
| 60 | + if err != nil { |
| 61 | + return s, fmt.Errorf("%s: %w: %s (from: %s)", zipFile.FileInfo().Name(), err, wfile, zipFile.Name) |
| 62 | + } |
62 | 63 |
|
63 | | - return s, nil |
| 64 | + return s, nil |
64 | 65 | } |
0 commit comments