Skip to content

Commit c95f3c8

Browse files
committed
Integrate archiver to simplify download
Right now, archiver doesn't handle security issue but there is an existing PR to handle it. Added walker to handle until upstream is fixed. When it's updated with go modules, walker can be dropped.
1 parent b9a0e88 commit c95f3c8

File tree

4 files changed

+141
-324
lines changed

4 files changed

+141
-324
lines changed

go.mod

+8-1
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,25 @@ module sigs.k8s.io/krew
33
go 1.12
44

55
require (
6+
github.com/dsnet/compress v0.0.1 // indirect
67
github.com/fatih/color v1.7.0
8+
github.com/frankban/quicktest v1.6.0 // indirect
79
github.com/gogo/protobuf v1.2.1 // indirect
810
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
9-
github.com/google/go-cmp v0.3.0
11+
github.com/golang/snappy v0.0.1 // indirect
12+
github.com/google/go-cmp v0.3.1
1013
github.com/inconshreveable/mousetrap v1.0.0 // indirect
1114
github.com/kylelemons/godebug v1.1.0 // indirect
1215
github.com/mattn/go-colorable v0.1.2 // indirect
1316
github.com/mattn/go-isatty v0.0.8
17+
github.com/mholt/archiver v3.1.1+incompatible
18+
github.com/nwaples/rardecode v1.0.0 // indirect
19+
github.com/pierrec/lz4 v2.3.0+incompatible // indirect
1420
github.com/pkg/errors v0.8.0
1521
github.com/sahilm/fuzzy v0.0.5
1622
github.com/spf13/cobra v0.0.3
1723
github.com/spf13/pflag v1.0.3
24+
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
1825
golang.org/x/net v0.0.0-20190628185345-da137c7871d7 // indirect
1926
golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7 // indirect
2027
gopkg.in/inf.v0 v0.9.1 // indirect

go.sum

+21
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,16 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
66
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
77
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
88
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
9+
github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q=
10+
github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo=
11+
github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
912
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
1013
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
1114
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
1215
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
1316
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
17+
github.com/frankban/quicktest v1.6.0 h1:Cd62nl66vQsx8Uv1t8M0eICyxIwZG7MxiAOrdnnUSW0=
18+
github.com/frankban/quicktest v1.6.0/go.mod h1:jaStnuzAqU1AJdCO0l53JDCJrVDKcS03DbaAcR7Ks/o=
1419
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
1520
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680 h1:ZktWZesgun21uEDrwW7iEV1zPCGQldM2atlJZ3TdvVM=
1621
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
@@ -27,8 +32,12 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfU
2732
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
2833
github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
2934
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
35+
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
36+
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
3037
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
3138
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
39+
github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
40+
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
3241
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
3342
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
3443
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -44,6 +53,8 @@ github.com/json-iterator/go v1.1.6 h1:MrUvLMLTMxbqFJ9kzlvat/rYZqZnW3u4wkLzWTaFwK
4453
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
4554
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
4655
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
56+
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
57+
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
4758
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
4859
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
4960
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
@@ -56,18 +67,24 @@ github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx
5667
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
5768
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
5869
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
70+
github.com/mholt/archiver v3.1.1+incompatible h1:1dCVxuqs0dJseYEhi5pl7MYPH9zDa1wBi7mF09cbNkU=
71+
github.com/mholt/archiver v3.1.1+incompatible/go.mod h1:Dh2dOXnSdiLxRiPoVfIr/fI1TwETms9B8CTWfeh7ROU=
5972
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
6073
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
6174
github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
6275
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
6376
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
6477
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
6578
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
79+
github.com/nwaples/rardecode v1.0.0 h1:r7vGuS5akxOnR4JQSkko62RJ1ReCMXxQRPtxsiFMBOs=
80+
github.com/nwaples/rardecode v1.0.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
6681
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
6782
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
6883
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
6984
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
7085
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
86+
github.com/pierrec/lz4 v2.3.0+incompatible h1:CZzRn4Ut9GbUkHlQ7jqBXeZQV41ZSKWFc302ZU6lUTk=
87+
github.com/pierrec/lz4 v2.3.0+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
7188
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
7289
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
7390
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@@ -84,6 +101,10 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
84101
github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
85102
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
86103
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
104+
github.com/ulikunitz/xz v0.5.6 h1:jGHAfXawEGZQ3blwU5wnWKQJvAraT7Ftq9EXjnXYgt8=
105+
github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
106+
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
107+
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
87108
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
88109
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
89110
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=

pkg/download/downloader.go

+52-149
Original file line numberDiff line numberDiff line change
@@ -17,145 +17,35 @@ package download
1717
import (
1818
"archive/tar"
1919
"archive/zip"
20-
"bytes"
21-
"compress/gzip"
2220
"io"
2321
"io/ioutil"
2422
"net/http"
2523
"os"
26-
"path/filepath"
2724
"strings"
2825

2926
"github.com/golang/glog"
27+
"github.com/mholt/archiver"
3028
"github.com/pkg/errors"
3129
)
3230

3331
// download gets a file from the internet in memory and writes it content
3432
// to a Verifier.
35-
func download(url string, verifier Verifier, fetcher Fetcher) (io.ReaderAt, int64, error) {
33+
func download(url string, verifier Verifier, fetcher Fetcher) ([]byte, error) {
3634
glog.V(2).Infof("Fetching %q", url)
3735
body, err := fetcher.Get(url)
3836
if err != nil {
39-
return nil, 0, errors.Wrapf(err, "could not download %q", url)
37+
return nil, errors.Wrapf(err, "could not download %q", url)
4038
}
4139
defer body.Close()
4240

4341
glog.V(3).Infof("Reading download data into memory")
4442
data, err := ioutil.ReadAll(io.TeeReader(body, verifier))
4543
if err != nil {
46-
return nil, 0, errors.Wrap(err, "could not read download content")
44+
return nil, errors.Wrap(err, "could not read download content")
4745
}
4846
glog.V(2).Infof("Read %d bytes of download data into memory", len(data))
4947

50-
return bytes.NewReader(data), int64(len(data)), verifier.Verify()
51-
}
52-
53-
// extractZIP extracts a zip file into the target directory.
54-
func extractZIP(targetDir string, read io.ReaderAt, size int64) error {
55-
glog.V(4).Infof("Extracting download zip to %q", targetDir)
56-
zipReader, err := zip.NewReader(read, size)
57-
if err != nil {
58-
return err
59-
}
60-
61-
for _, f := range zipReader.File {
62-
if err := suspiciousPath(f.Name); err != nil {
63-
return err
64-
}
65-
66-
path := filepath.Join(targetDir, filepath.FromSlash(f.Name))
67-
if f.FileInfo().IsDir() {
68-
if err := os.MkdirAll(path, f.Mode()); err != nil {
69-
return errors.Wrap(err, "can't create directory tree")
70-
}
71-
continue
72-
}
73-
74-
src, err := f.Open()
75-
if err != nil {
76-
return errors.Wrap(err, "could not open inflating zip file")
77-
}
78-
79-
dst, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, f.Mode())
80-
if err != nil {
81-
src.Close()
82-
return errors.Wrap(err, "can't create file in zip destination dir")
83-
}
84-
close := func() {
85-
src.Close()
86-
dst.Close()
87-
}
88-
89-
if _, err := io.Copy(dst, src); err != nil {
90-
close()
91-
return errors.Wrap(err, "can't copy content to zip destination file")
92-
}
93-
close()
94-
}
95-
96-
return nil
97-
}
98-
99-
// extractTARGZ extracts a gzipped tar file into the target directory.
100-
func extractTARGZ(targetDir string, at io.ReaderAt, size int64) error {
101-
glog.V(4).Infof("tar: extracting to %q", targetDir)
102-
in := io.NewSectionReader(at, 0, size)
103-
104-
gzr, err := gzip.NewReader(in)
105-
if err != nil {
106-
return errors.Wrap(err, "failed to create gzip reader")
107-
}
108-
defer gzr.Close()
109-
110-
tr := tar.NewReader(gzr)
111-
for {
112-
hdr, err := tr.Next()
113-
if err == io.EOF {
114-
break
115-
}
116-
if err != nil {
117-
return errors.Wrap(err, "tar extraction error")
118-
}
119-
glog.V(4).Infof("tar: processing %q (type=%d, mode=%s)", hdr.Name, hdr.Typeflag, os.FileMode(hdr.Mode))
120-
// see https://golang.org/cl/78355 for handling pax_global_header
121-
if hdr.Name == "pax_global_header" {
122-
glog.V(4).Infof("tar: skipping pax_global_header file")
123-
continue
124-
}
125-
126-
if err := suspiciousPath(hdr.Name); err != nil {
127-
return err
128-
}
129-
130-
path := filepath.Join(targetDir, filepath.FromSlash(hdr.Name))
131-
switch hdr.Typeflag {
132-
case tar.TypeDir:
133-
if err := os.MkdirAll(path, os.FileMode(hdr.Mode)); err != nil {
134-
return errors.Wrap(err, "failed to create directory from tar")
135-
}
136-
case tar.TypeReg:
137-
dir := filepath.Dir(path)
138-
glog.V(4).Infof("tar: ensuring parent dirs exist for regular file, dir=%s", dir)
139-
if err := os.MkdirAll(dir, 0755); err != nil {
140-
return errors.Wrap(err, "failed to create directory for tar")
141-
}
142-
f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, os.FileMode(hdr.Mode))
143-
if err != nil {
144-
return errors.Wrapf(err, "failed to create file %q", path)
145-
}
146-
close := func() { f.Close() }
147-
if _, err := io.Copy(f, tr); err != nil {
148-
close()
149-
return errors.Wrapf(err, "failed to copy %q from tar into file", hdr.Name)
150-
}
151-
close()
152-
default:
153-
return errors.Errorf("unable to handle file type %d for %q in tar", hdr.Typeflag, hdr.Name)
154-
}
155-
glog.V(4).Infof("tar: processed %q", hdr.Name)
156-
}
157-
glog.V(4).Infof("tar extraction to %s complete", targetDir)
158-
return nil
48+
return data, verifier.Verify()
15949
}
16050

16151
func suspiciousPath(path string) error {
@@ -170,44 +60,38 @@ func suspiciousPath(path string) error {
17060
return nil
17161
}
17262

173-
func detectMIMEType(at io.ReaderAt) (string, error) {
174-
buf := make([]byte, 512)
175-
n, err := at.ReadAt(buf, 0)
176-
if err != nil && err != io.EOF {
177-
return "", errors.Wrap(err, "failed to read first 512 bytes")
178-
}
179-
if n < 512 {
180-
glog.V(5).Infof("Did only read %d of 512 bytes to determine the file type", n)
181-
}
63+
func isSuspiciousArchive(path string) error {
64+
return archiver.Walk(path, func(f archiver.File) error {
65+
switch h := f.Header.(type) {
66+
case *tar.Header:
67+
return suspiciousPath(h.Name)
68+
case zip.FileHeader:
69+
return suspiciousPath(h.Name)
70+
default:
71+
return errors.Errorf("Unknow header type: %T", h)
72+
}
73+
})
74+
}
18275

76+
func detectMIMEType(data []byte) string {
77+
n := 512
78+
if l := len(data); l < n {
79+
n = l
80+
}
18381
// Cut off mime extra info beginning with ';' i.e:
18482
// "text/plain; charset=utf-8" should result in "text/plain".
185-
return strings.Split(http.DetectContentType(buf[:n]), ";")[0], nil
186-
}
187-
188-
type extractor func(targetDir string, read io.ReaderAt, size int64) error
189-
190-
var defaultExtractors = map[string]extractor{
191-
"application/zip": extractZIP,
192-
"application/x-gzip": extractTARGZ,
83+
return strings.Split(http.DetectContentType(data[:n]), ";")[0]
19384
}
19485

195-
func extractArchive(dst string, at io.ReaderAt, size int64) error {
196-
// TODO(ahmetb) This package is not architected well, this method should not
197-
// be receiving this many args. Primary problem is at GetInsecure and
198-
// GetWithSha256 methods that embed extraction in them, which is orthogonal.
199-
200-
t, err := detectMIMEType(at)
201-
if err != nil {
202-
return errors.Wrap(err, "failed to determine content type")
86+
func extensionFromMIME(mime string) (string, error) {
87+
switch mime {
88+
case "application/zip":
89+
return "zip", nil
90+
case "application/x-gzip":
91+
return "tar.gz", nil
92+
default:
93+
return "", errors.Errorf("unknown mime type to extract: %q", mime)
20394
}
204-
glog.V(4).Infof("detected %q file type", t)
205-
exf, ok := defaultExtractors[t]
206-
if !ok {
207-
return errors.Errorf("mime type %q for downloaded file is not a supported archive format", t)
208-
}
209-
return errors.Wrap(exf(dst, at, size), "failed to extract file")
210-
21195
}
21296

21397
// Downloader is responsible for fetching, verifying and extracting a binary.
@@ -227,9 +111,28 @@ func NewDownloader(v Verifier, f Fetcher) Downloader {
227111
// Get pulls the uri and verifies it. On success, the download gets extracted
228112
// into dst.
229113
func (d Downloader) Get(uri, dst string) error {
230-
body, size, err := download(uri, d.verifier, d.fetcher)
114+
data, err := download(uri, d.verifier, d.fetcher)
115+
if err != nil {
116+
return err
117+
}
118+
extension, err := extensionFromMIME(detectMIMEType(data))
231119
if err != nil {
232120
return err
233121
}
234-
return extractArchive(dst, body, size)
122+
123+
f, err := ioutil.TempFile("", "plugin.*."+extension)
124+
if err != nil {
125+
return errors.Wrap(err, "failed to create temp file to write")
126+
}
127+
defer os.Remove(f.Name())
128+
if n, err := f.Write(data); err != nil {
129+
return errors.Wrap(err, "failed to write temp download file")
130+
} else if n != len(data) {
131+
return errors.Errorf("failed to write whole download archive")
132+
}
133+
134+
if err := isSuspiciousArchive(f.Name()); err != nil {
135+
return err
136+
}
137+
return archiver.Unarchive(f.Name(), dst)
235138
}

0 commit comments

Comments
 (0)