Skip to content

Commit

Permalink
Implement StripComponents to zip
Browse files Browse the repository at this point in the history
  • Loading branch information
illiliti authored and AJ ONeal committed Oct 13, 2020
1 parent fd5996a commit 2e9f979
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 8 deletions.
1 change: 1 addition & 0 deletions cmd/arc/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ func getFormat(subcommand string) (interface{}, error) {
v.MkdirAll = mkdirAll
v.SelectiveCompression = selectiveCompression
v.ImplicitTopLevelFolder = implicitTopLevelFolder
v.StripComponents = stripComponents
v.ContinueOnError = continueOnError
case *archiver.Gz:
v.CompressionLevel = compressionLevel
Expand Down
31 changes: 23 additions & 8 deletions zip.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ type Zip struct {
// especially on extraction.
ImplicitTopLevelFolder bool

// Strip number of leading paths. This feature is available
// only during unpacking of the entire archive.
StripComponents int

// If true, errors encountered during reading
// or writing a single file will be logged and
// the operation will continue on remaining files.
Expand Down Expand Up @@ -243,19 +247,30 @@ func (z *Zip) extractNext(to string) error {
}
defer f.Close()

errPath := z.CheckPath(to, f.Header.(zip.FileHeader).Name)
header, ok := f.Header.(zip.FileHeader)
if !ok {
return fmt.Errorf("expected header to be zip.FileHeader but was %T", f.Header)
}

errPath := z.CheckPath(to, header.Name)
if errPath != nil {
return fmt.Errorf("checking path traversal attempt: %v", errPath)
}
return z.extractFile(f, to)
}

func (z *Zip) extractFile(f File, to string) error {
header, ok := f.Header.(zip.FileHeader)
if !ok {
return fmt.Errorf("expected header to be zip.FileHeader but was %T", f.Header)
if z.StripComponents > 0 {
if strings.Count(header.Name, "/") < z.StripComponents {
return nil // skip path with fewer components
}

for i := 0; i < z.StripComponents; i++ {
slash := strings.Index(header.Name, "/")
header.Name = header.Name[slash+1:]
}
}
return z.extractFile(f, to, &header)
}

func (z *Zip) extractFile(f File, to string, header *zip.FileHeader) error {
to = filepath.Join(to, header.Name)

// if a directory, no content; simply make the directory and return
Expand Down Expand Up @@ -583,7 +598,7 @@ func (z *Zip) Extract(source, target, destination string) error {
}
joined := filepath.Join(destination, end)

err = z.extractFile(f, joined)
err = z.extractFile(f, joined, &zfh)
if err != nil {
return fmt.Errorf("extracting file %s: %v", zfh.Name, err)
}
Expand Down

0 comments on commit 2e9f979

Please sign in to comment.