Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alist-org
GitHub Repository: alist-org/alist
Path: blob/main/internal/archive/zip/zip.go
1562 views
1
package zip
2
3
import (
4
"io"
5
stdpath "path"
6
"strings"
7
8
"github.com/alist-org/alist/v3/internal/archive/tool"
9
"github.com/alist-org/alist/v3/internal/errs"
10
"github.com/alist-org/alist/v3/internal/model"
11
"github.com/alist-org/alist/v3/internal/stream"
12
)
13
14
type Zip struct {
15
}
16
17
func (Zip) AcceptedExtensions() []string {
18
return []string{}
19
}
20
21
func (Zip) AcceptedMultipartExtensions() map[string]tool.MultipartExtension {
22
return map[string]tool.MultipartExtension{
23
".zip": {".z%.2d", 1},
24
".zip.001": {".zip.%.3d", 2},
25
}
26
}
27
28
func (Zip) GetMeta(ss []*stream.SeekableStream, args model.ArchiveArgs) (model.ArchiveMeta, error) {
29
zipReader, err := getReader(ss)
30
if err != nil {
31
return nil, err
32
}
33
encrypted, tree := tool.GenerateMetaTreeFromFolderTraversal(&WrapReader{Reader: zipReader})
34
return &model.ArchiveMetaInfo{
35
Comment: zipReader.Comment,
36
Encrypted: encrypted,
37
Tree: tree,
38
}, nil
39
}
40
41
func (Zip) List(ss []*stream.SeekableStream, args model.ArchiveInnerArgs) ([]model.Obj, error) {
42
zipReader, err := getReader(ss)
43
if err != nil {
44
return nil, err
45
}
46
if args.InnerPath == "/" {
47
ret := make([]model.Obj, 0)
48
passVerified := false
49
var dir *model.Object
50
for _, file := range zipReader.File {
51
if !passVerified && file.IsEncrypted() {
52
file.SetPassword(args.Password)
53
rc, e := file.Open()
54
if e != nil {
55
return nil, filterPassword(e)
56
}
57
_ = rc.Close()
58
passVerified = true
59
}
60
name := strings.TrimSuffix(decodeName(file.Name), "/")
61
if strings.Contains(name, "/") {
62
// 有些压缩包不压缩第一个文件夹
63
strs := strings.Split(name, "/")
64
if dir == nil && len(strs) == 2 {
65
dir = &model.Object{
66
Name: strs[0],
67
Modified: ss[0].ModTime(),
68
IsFolder: true,
69
}
70
}
71
continue
72
}
73
ret = append(ret, tool.MakeModelObj(&WrapFileInfo{FileInfo: file.FileInfo()}))
74
}
75
if len(ret) == 0 && dir != nil {
76
ret = append(ret, dir)
77
}
78
return ret, nil
79
} else {
80
innerPath := strings.TrimPrefix(args.InnerPath, "/") + "/"
81
ret := make([]model.Obj, 0)
82
exist := false
83
for _, file := range zipReader.File {
84
name := decodeName(file.Name)
85
dir := stdpath.Dir(strings.TrimSuffix(name, "/")) + "/"
86
if dir != innerPath {
87
continue
88
}
89
exist = true
90
ret = append(ret, tool.MakeModelObj(&WrapFileInfo{file.FileInfo()}))
91
}
92
if !exist {
93
return nil, errs.ObjectNotFound
94
}
95
return ret, nil
96
}
97
}
98
99
func (Zip) Extract(ss []*stream.SeekableStream, args model.ArchiveInnerArgs) (io.ReadCloser, int64, error) {
100
zipReader, err := getReader(ss)
101
if err != nil {
102
return nil, 0, err
103
}
104
innerPath := strings.TrimPrefix(args.InnerPath, "/")
105
for _, file := range zipReader.File {
106
if decodeName(file.Name) == innerPath {
107
if file.IsEncrypted() {
108
file.SetPassword(args.Password)
109
}
110
r, e := file.Open()
111
if e != nil {
112
return nil, 0, e
113
}
114
return r, file.FileInfo().Size(), nil
115
}
116
}
117
return nil, 0, errs.ObjectNotFound
118
}
119
120
func (Zip) Decompress(ss []*stream.SeekableStream, outputPath string, args model.ArchiveInnerArgs, up model.UpdateProgress) error {
121
zipReader, err := getReader(ss)
122
if err != nil {
123
return err
124
}
125
return tool.DecompressFromFolderTraversal(&WrapReader{Reader: zipReader}, outputPath, args, up)
126
}
127
128
var _ tool.Tool = (*Zip)(nil)
129
130
func init() {
131
tool.RegisterTool(Zip{})
132
}
133
134