Path: blob/main/internal/archive/rardecode/rardecode.go
1562 views
package rardecode12import (3"github.com/alist-org/alist/v3/internal/archive/tool"4"github.com/alist-org/alist/v3/internal/errs"5"github.com/alist-org/alist/v3/internal/model"6"github.com/alist-org/alist/v3/internal/stream"7"github.com/nwaples/rardecode/v2"8"io"9"os"10stdpath "path"11"strings"12)1314type RarDecoder struct{}1516func (RarDecoder) AcceptedExtensions() []string {17return []string{".rar"}18}1920func (RarDecoder) AcceptedMultipartExtensions() map[string]tool.MultipartExtension {21return map[string]tool.MultipartExtension{22".part1.rar": {".part%d.rar", 2},23}24}2526func (RarDecoder) GetMeta(ss []*stream.SeekableStream, args model.ArchiveArgs) (model.ArchiveMeta, error) {27l, err := list(ss, args.Password)28if err != nil {29return nil, err30}31_, tree := tool.GenerateMetaTreeFromFolderTraversal(l)32return &model.ArchiveMetaInfo{33Comment: "",34Encrypted: false,35Tree: tree,36}, nil37}3839func (RarDecoder) List(ss []*stream.SeekableStream, args model.ArchiveInnerArgs) ([]model.Obj, error) {40return nil, errs.NotSupport41}4243func (RarDecoder) Extract(ss []*stream.SeekableStream, args model.ArchiveInnerArgs) (io.ReadCloser, int64, error) {44reader, err := getReader(ss, args.Password)45if err != nil {46return nil, 0, err47}48innerPath := strings.TrimPrefix(args.InnerPath, "/")49for {50var header *rardecode.FileHeader51header, err = reader.Next()52if err == io.EOF {53break54}55if err != nil {56return nil, 0, err57}58if header.Name == innerPath {59if header.IsDir {60break61}62return io.NopCloser(reader), header.UnPackedSize, nil63}64}65return nil, 0, errs.ObjectNotFound66}6768func (RarDecoder) Decompress(ss []*stream.SeekableStream, outputPath string, args model.ArchiveInnerArgs, up model.UpdateProgress) error {69reader, err := getReader(ss, args.Password)70if err != nil {71return err72}73if args.InnerPath == "/" {74for {75var header *rardecode.FileHeader76header, err = reader.Next()77if err == io.EOF {78break79}80if err != nil {81return err82}83name := header.Name84if header.IsDir {85name = name + "/"86}87err = decompress(reader, header, name, outputPath)88if err != nil {89return err90}91}92} else {93innerPath := strings.TrimPrefix(args.InnerPath, "/")94innerBase := stdpath.Base(innerPath)95createdBaseDir := false96for {97var header *rardecode.FileHeader98header, err = reader.Next()99if err == io.EOF {100break101}102if err != nil {103return err104}105name := header.Name106if header.IsDir {107name = name + "/"108}109if name == innerPath {110err = _decompress(reader, header, outputPath, up)111if err != nil {112return err113}114break115} else if strings.HasPrefix(name, innerPath+"/") {116targetPath := stdpath.Join(outputPath, innerBase)117if !createdBaseDir {118err = os.Mkdir(targetPath, 0700)119if err != nil {120return err121}122createdBaseDir = true123}124restPath := strings.TrimPrefix(name, innerPath+"/")125err = decompress(reader, header, restPath, targetPath)126if err != nil {127return err128}129}130}131}132return nil133}134135var _ tool.Tool = (*RarDecoder)(nil)136137func init() {138tool.RegisterTool(RarDecoder{})139}140141142