package fsUtils import ( "archive/zip" "fmt" "io" "os" "path/filepath" "strings" "github.com/rs/zerolog/log" ) func AddFileToZip(zipWriter *zip.Writer, filename string) error { fileToZip, err := os.Open(filename) if err != nil { return fmt.Errorf("failed to open file %s, %w", filename, err) } defer fileToZip.Close() // Get the file information info, err := fileToZip.Stat() if err != nil { return fmt.Errorf("failed to get file information %s, %w", filename, err) } header, err := zip.FileInfoHeader(info) if err != nil { return err } // Using FileInfoHeader() above only uses the basename of the file. If we want // to preserve the folder structure we can overwrite this with the full path. header.Name = filepath.Base(filename) // Change to deflate to gain better compression // see http://golang.org/pkg/archive/zip/#pkg-constants header.Method = zip.Deflate writer, err := zipWriter.CreateHeader(header) if err != nil { return fmt.Errorf("failed to create header in zip for %s, %w", filename, err) } _, err = io.Copy(writer, fileToZip) return err } func AddStrToZip(writer *zip.Writer, logs string, fileName string) error { if zipFile, err := writer.Create(fileName); err != nil { return fmt.Errorf("couldn't create a log file inside zip for %s, %w", fileName, err) } else { if _, err = zipFile.Write([]byte(logs)); err != nil { return fmt.Errorf("couldn't write logs to zip file: %s, %w", fileName, err) } } return nil } func Unzip(reader *zip.Reader, dest string) error { dest, _ = filepath.Abs(dest) _ = os.MkdirAll(dest, os.ModePerm) // Closure to address file descriptors issue with all the deferred .Close() methods extractAndWriteFile := func(f *zip.File) error { rc, err := f.Open() if err != nil { return err } defer func() { if err := rc.Close(); err != nil { panic(err) } }() path := filepath.Join(dest, f.Name) // Check for ZipSlip (Directory traversal) if !strings.HasPrefix(path, filepath.Clean(dest)+string(os.PathSeparator)) { return fmt.Errorf("illegal file path: %s", path) } if f.FileInfo().IsDir() { _ = os.MkdirAll(path, f.Mode()) } else { _ = os.MkdirAll(filepath.Dir(path), f.Mode()) log.Info().Str("path", path).Msg("Writing HAR file...") f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode()) if err != nil { return err } defer func() { if err := f.Close(); err != nil { panic(err) } log.Info().Str("path", path).Msg("HAR file at:") }() _, err = io.Copy(f, rc) if err != nil { return err } } return nil } for _, f := range reader.File { err := extractAndWriteFile(f) if err != nil { return err } } return nil }