Skip to content

Commit

Permalink
fix(archive): split internal and driver extraction api
Browse files Browse the repository at this point in the history
  • Loading branch information
KirCute committed Jan 16, 2025
1 parent 46b0cc5 commit 4bbf7a3
Show file tree
Hide file tree
Showing 14 changed files with 337 additions and 126 deletions.
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ require (
github.com/pkg/sftp v1.13.6
github.com/pquerna/otp v1.4.0
github.com/rclone/rclone v1.67.0
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d
github.com/sirupsen/logrus v1.9.3
github.com/spf13/afero v1.11.0
github.com/spf13/cobra v1.8.1
Expand Down Expand Up @@ -243,7 +244,7 @@ require (
golang.org/x/sync v0.10.0 // indirect
golang.org/x/sys v0.28.0 // indirect
golang.org/x/term v0.27.0 // indirect
golang.org/x/text v0.21.0 // indirect
golang.org/x/text v0.21.0
golang.org/x/tools v0.24.0 // indirect
google.golang.org/api v0.169.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,8 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk=
github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46 h1:GHRpF1pTW19a8tTFrMLUcfWwyC0pnifVo2ClaLq+hP8=
github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46/go.mod h1:uAQ5PCi+MFsC7HjREoAz1BU+Mq60+05gifQSsHSDG/8=
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d h1:hrujxIzL1woJ7AwssoOcM/tq5JjjG2yYOc8odClEiXA=
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU=
github.com/secsy/goftp v0.0.0-20200609142545-aa2de14babf4 h1:PT+ElG/UUFMfqy5HrxJxNzj3QBOf7dZwupeVC+mG1Lo=
github.com/secsy/goftp v0.0.0-20200609142545-aa2de14babf4/go.mod h1:MnkX001NG75g3p8bhFycnyIjeQoOjGL6CEIsdE/nKSY=
github.com/shabbyrobe/gocovmerge v0.0.0-20230507112040-c3350d9342df h1:S77Pf5fIGMa7oSwp8SQPp7Hb4ZiI38K3RNBKD2LLeEM=
Expand Down
24 changes: 18 additions & 6 deletions internal/archive/archives/archives.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"github.com/alist-org/alist/v3/internal/model"
"github.com/alist-org/alist/v3/internal/stream"
"github.com/alist-org/alist/v3/pkg/utils"
"io"
"io/fs"
"os"
stdpath "path"
Expand All @@ -29,15 +30,22 @@ func (_ *Archives) GetMeta(ss *stream.SeekableStream, args model.ArchiveArgs) (m
if err != nil {
return nil, filterPassword(err)
}
return &tool.EmptyMeta{}, nil
return &model.ArchiveMetaInfo{
Comment: "",
Encrypted: false,
}, nil
}

func (_ *Archives) List(ss *stream.SeekableStream, args model.ArchiveInnerArgs) ([]model.Obj, error) {
fsys, err := getFs(ss, args.ArchiveArgs)
if err != nil {
return nil, err
}
obj, err := fsys.ReadDir(strings.TrimPrefix(args.InnerPath, "/"))
innerPath := strings.TrimPrefix(args.InnerPath, "/")
if innerPath == "" {
innerPath = "."
}
obj, err := fsys.ReadDir(innerPath)
if err != nil {
return nil, filterPassword(err)
}
Expand All @@ -50,16 +58,20 @@ func (_ *Archives) List(ss *stream.SeekableStream, args model.ArchiveInnerArgs)
})
}

func (_ *Archives) Extract(ss *stream.SeekableStream, args model.ArchiveInnerArgs) (*model.Link, error) {
func (_ *Archives) Extract(ss *stream.SeekableStream, args model.ArchiveInnerArgs) (io.ReadCloser, int64, error) {
fsys, err := getFs(ss, args.ArchiveArgs)
if err != nil {
return nil, err
return nil, 0, err
}
file, err := fsys.Open(strings.TrimPrefix(args.InnerPath, "/"))
if err != nil {
return nil, filterPassword(err)
return nil, 0, filterPassword(err)
}
stat, err := file.Stat()
if err != nil {
return nil, 0, filterPassword(err)
}
return &model.Link{MFile: &tool.SequentialFile{Reader: file}}, nil
return file, stat.Size(), nil
}

func (_ *Archives) Decompress(ss *stream.SeekableStream, outputPath string, args model.ArchiveInnerArgs, up model.UpdateProgress) error {
Expand Down
3 changes: 2 additions & 1 deletion internal/archive/tool/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ package tool
import (
"github.com/alist-org/alist/v3/internal/model"
"github.com/alist-org/alist/v3/internal/stream"
"io"
)

type Tool interface {
AcceptedExtensions() []string
GetMeta(ss *stream.SeekableStream, args model.ArchiveArgs) (model.ArchiveMeta, error)
List(ss *stream.SeekableStream, args model.ArchiveInnerArgs) ([]model.Obj, error)
Extract(ss *stream.SeekableStream, args model.ArchiveInnerArgs) (*model.Link, error)
Extract(ss *stream.SeekableStream, args model.ArchiveInnerArgs) (io.ReadCloser, int64, error)
Decompress(ss *stream.SeekableStream, outputPath string, args model.ArchiveInnerArgs, up model.UpdateProgress) error
}
36 changes: 0 additions & 36 deletions internal/archive/tool/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ package tool

import (
"github.com/alist-org/alist/v3/internal/errs"
"github.com/alist-org/alist/v3/internal/model"
"io"
)

var (
Expand All @@ -23,37 +21,3 @@ func GetArchiveTool(ext string) (Tool, error) {
}
return t, nil
}

type SequentialFile struct {
Reader io.ReadCloser
}

func (s *SequentialFile) Read(p []byte) (n int, err error) {
return s.Reader.Read(p)
}

func (s *SequentialFile) ReadAt(p []byte, off int64) (n int, err error) {
return 0, errs.NotSupport
}

func (s *SequentialFile) Seek(offset int64, whence int) (int64, error) {
return 0, errs.NotSupport
}

func (s *SequentialFile) Close() error {
return s.Reader.Close()
}

type EmptyMeta struct{}

func (e *EmptyMeta) GetComment() string {
return ""
}

func (e *EmptyMeta) IsEncrypted() bool {
return false
}

func (e *EmptyMeta) GetTree() []model.ObjTree {
return nil
}
110 changes: 92 additions & 18 deletions internal/archive/zip/utils.go
Original file line number Diff line number Diff line change
@@ -1,34 +1,30 @@
package zip

import (
"bytes"
"github.com/alist-org/alist/v3/internal/errs"
"github.com/alist-org/alist/v3/internal/model"
"github.com/alist-org/alist/v3/internal/stream"
"github.com/saintfish/chardet"
"github.com/yeka/zip"
"golang.org/x/text/encoding"
"golang.org/x/text/encoding/charmap"
"golang.org/x/text/encoding/japanese"
"golang.org/x/text/encoding/korean"
"golang.org/x/text/encoding/simplifiedchinese"
"golang.org/x/text/encoding/traditionalchinese"
"golang.org/x/text/encoding/unicode"
"golang.org/x/text/encoding/unicode/utf32"
"golang.org/x/text/transform"
"io"
"os"
stdpath "path"
"strings"
)

type zipMeta struct {
Comment string
Encrypted bool
}

func (m *zipMeta) GetComment() string {
return m.Comment
}

func (m *zipMeta) IsEncrypted() bool {
return m.Encrypted
}

func (m *zipMeta) GetTree() []model.ObjTree {
return nil
}

func toModelObj(file os.FileInfo) *model.Object {
return &model.Object{
Name: file.Name(),
Name: decodeName(file.Name()),
Size: file.Size(),
Modified: file.ModTime(),
IsFolder: file.IsDir(),
Expand Down Expand Up @@ -80,3 +76,81 @@ func _decompress(file *zip.File, targetPath, password string, up model.UpdatePro
}
return nil
}

func filterPassword(err error) error {
if err != nil && strings.Contains(err.Error(), "password") {
return errs.WrongArchivePassword
}
return err
}

func decodeName(name string) string {
b := []byte(name)
detector := chardet.NewTextDetector()
result, err := detector.DetectBest(b)
if err != nil {
return name
}
enc := getEncoding(result.Charset)
if enc == nil {
return name
}
i := bytes.NewReader(b)
decoder := transform.NewReader(i, enc.NewDecoder())
content, _ := io.ReadAll(decoder)
return string(content)
}

func getEncoding(name string) (enc encoding.Encoding) {
switch name {
case "UTF-16BE":
enc = unicode.UTF16(unicode.BigEndian, unicode.IgnoreBOM)
case "UTF-16LE":
enc = unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM)
case "UTF-32BE":
enc = utf32.UTF32(utf32.BigEndian, utf32.IgnoreBOM)
case "UTF-32LE":
enc = utf32.UTF32(utf32.LittleEndian, utf32.IgnoreBOM)
case "ISO-8859-1":
enc = charmap.ISO8859_1
case "ISO-8859-2":
enc = charmap.ISO8859_2
case "ISO-8859-3":
enc = charmap.ISO8859_3
case "ISO-8859-4":
enc = charmap.ISO8859_4
case "ISO-8859-5":
enc = charmap.ISO8859_5
case "ISO-8859-6":
enc = charmap.ISO8859_6
case "ISO-8859-7":
enc = charmap.ISO8859_7
case "ISO-8859-8":
enc = charmap.ISO8859_8
case "ISO-8859-8-I":
enc = charmap.ISO8859_8I
case "ISO-8859-9":
enc = charmap.ISO8859_9
case "windows-1251":
enc = charmap.Windows1251
case "windows-1256":
enc = charmap.Windows1256
case "KOI8-R":
enc = charmap.KOI8R
case "Shift_JIS":
enc = japanese.ShiftJIS
case "GB-18030":
enc = simplifiedchinese.GB18030
case "EUC-JP":
enc = japanese.EUCJP
case "EUC-KR":
enc = korean.EUCKR
case "Big5":
enc = traditionalchinese.Big5
case "ISO-2022-JP":
enc = japanese.ISO2022JP
default:
enc = nil
}
return
}
Loading

0 comments on commit 4bbf7a3

Please sign in to comment.