12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758 |
- package convert
- import (
- "archive/zip"
- "errors"
- "io"
- "io/fs"
- "os"
- "path/filepath"
- )
- type ZipReader struct {
- r *zip.Reader
- p string
- // limit is the maximum size of a file that can be read directly
- // from the zip archive. Files larger than this size will be extracted
- limit int64
- }
- func NewZipReader(r *zip.Reader, p string, limit int64) fs.FS {
- return &ZipReader{r, p, limit}
- }
- func (z *ZipReader) Open(name string) (fs.File, error) {
- r, err := z.r.Open(name)
- if err != nil {
- return nil, err
- }
- defer r.Close()
- if fi, err := r.Stat(); err != nil {
- return nil, err
- } else if fi.Size() < z.limit {
- return r, nil
- }
- if !filepath.IsLocal(name) {
- return nil, zip.ErrInsecurePath
- }
- n := filepath.Join(z.p, name)
- if _, err := os.Stat(n); errors.Is(err, os.ErrNotExist) {
- w, err := os.Create(n)
- if err != nil {
- return nil, err
- }
- defer w.Close()
- if _, err := io.Copy(w, r); err != nil {
- return nil, err
- }
- } else if err != nil {
- return nil, err
- }
- return os.Open(n)
- }
|