Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alist-org
GitHub Repository: alist-org/alist
Path: blob/main/internal/archive/rardecode/rardecode.go
1562 views
1
package rardecode
2
3
import (
4
"github.com/alist-org/alist/v3/internal/archive/tool"
5
"github.com/alist-org/alist/v3/internal/errs"
6
"github.com/alist-org/alist/v3/internal/model"
7
"github.com/alist-org/alist/v3/internal/stream"
8
"github.com/nwaples/rardecode/v2"
9
"io"
10
"os"
11
stdpath "path"
12
"strings"
13
)
14
15
type RarDecoder struct{}
16
17
func (RarDecoder) AcceptedExtensions() []string {
18
return []string{".rar"}
19
}
20
21
func (RarDecoder) AcceptedMultipartExtensions() map[string]tool.MultipartExtension {
22
return map[string]tool.MultipartExtension{
23
".part1.rar": {".part%d.rar", 2},
24
}
25
}
26
27
func (RarDecoder) GetMeta(ss []*stream.SeekableStream, args model.ArchiveArgs) (model.ArchiveMeta, error) {
28
l, err := list(ss, args.Password)
29
if err != nil {
30
return nil, err
31
}
32
_, tree := tool.GenerateMetaTreeFromFolderTraversal(l)
33
return &model.ArchiveMetaInfo{
34
Comment: "",
35
Encrypted: false,
36
Tree: tree,
37
}, nil
38
}
39
40
func (RarDecoder) List(ss []*stream.SeekableStream, args model.ArchiveInnerArgs) ([]model.Obj, error) {
41
return nil, errs.NotSupport
42
}
43
44
func (RarDecoder) Extract(ss []*stream.SeekableStream, args model.ArchiveInnerArgs) (io.ReadCloser, int64, error) {
45
reader, err := getReader(ss, args.Password)
46
if err != nil {
47
return nil, 0, err
48
}
49
innerPath := strings.TrimPrefix(args.InnerPath, "/")
50
for {
51
var header *rardecode.FileHeader
52
header, err = reader.Next()
53
if err == io.EOF {
54
break
55
}
56
if err != nil {
57
return nil, 0, err
58
}
59
if header.Name == innerPath {
60
if header.IsDir {
61
break
62
}
63
return io.NopCloser(reader), header.UnPackedSize, nil
64
}
65
}
66
return nil, 0, errs.ObjectNotFound
67
}
68
69
func (RarDecoder) Decompress(ss []*stream.SeekableStream, outputPath string, args model.ArchiveInnerArgs, up model.UpdateProgress) error {
70
reader, err := getReader(ss, args.Password)
71
if err != nil {
72
return err
73
}
74
if args.InnerPath == "/" {
75
for {
76
var header *rardecode.FileHeader
77
header, err = reader.Next()
78
if err == io.EOF {
79
break
80
}
81
if err != nil {
82
return err
83
}
84
name := header.Name
85
if header.IsDir {
86
name = name + "/"
87
}
88
err = decompress(reader, header, name, outputPath)
89
if err != nil {
90
return err
91
}
92
}
93
} else {
94
innerPath := strings.TrimPrefix(args.InnerPath, "/")
95
innerBase := stdpath.Base(innerPath)
96
createdBaseDir := false
97
for {
98
var header *rardecode.FileHeader
99
header, err = reader.Next()
100
if err == io.EOF {
101
break
102
}
103
if err != nil {
104
return err
105
}
106
name := header.Name
107
if header.IsDir {
108
name = name + "/"
109
}
110
if name == innerPath {
111
err = _decompress(reader, header, outputPath, up)
112
if err != nil {
113
return err
114
}
115
break
116
} else if strings.HasPrefix(name, innerPath+"/") {
117
targetPath := stdpath.Join(outputPath, innerBase)
118
if !createdBaseDir {
119
err = os.Mkdir(targetPath, 0700)
120
if err != nil {
121
return err
122
}
123
createdBaseDir = true
124
}
125
restPath := strings.TrimPrefix(name, innerPath+"/")
126
err = decompress(reader, header, restPath, targetPath)
127
if err != nil {
128
return err
129
}
130
}
131
}
132
}
133
return nil
134
}
135
136
var _ tool.Tool = (*RarDecoder)(nil)
137
138
func init() {
139
tool.RegisterTool(RarDecoder{})
140
}
141
142