Spaces:
Paused
Paused
| // Credits: https://pkg.go.dev/github.com/rclone/rclone@v1.65.2/cmd/serve/s3 | |
| // Package s3 implements a fake s3 server for alist | |
| package s3 | |
| import ( | |
| "context" | |
| "encoding/json" | |
| "strings" | |
| "github.com/Mikubill/gofakes3" | |
| "github.com/alist-org/alist/v3/internal/conf" | |
| "github.com/alist-org/alist/v3/internal/errs" | |
| "github.com/alist-org/alist/v3/internal/fs" | |
| "github.com/alist-org/alist/v3/internal/model" | |
| "github.com/alist-org/alist/v3/internal/op" | |
| "github.com/alist-org/alist/v3/internal/setting" | |
| ) | |
| type Bucket struct { | |
| Name string `json:"name"` | |
| Path string `json:"path"` | |
| } | |
| func getAndParseBuckets() ([]Bucket, error) { | |
| var res []Bucket | |
| err := json.Unmarshal([]byte(setting.GetStr(conf.S3Buckets)), &res) | |
| return res, err | |
| } | |
| func getBucketByName(name string) (Bucket, error) { | |
| buckets, err := getAndParseBuckets() | |
| if err != nil { | |
| return Bucket{}, err | |
| } | |
| for _, b := range buckets { | |
| if b.Name == name { | |
| return b, nil | |
| } | |
| } | |
| return Bucket{}, gofakes3.BucketNotFound(name) | |
| } | |
| func getDirEntries(path string) ([]model.Obj, error) { | |
| ctx := context.Background() | |
| meta, _ := op.GetNearestMeta(path) | |
| fi, err := fs.Get(context.WithValue(ctx, "meta", meta), path, &fs.GetArgs{}) | |
| if errs.IsNotFoundError(err) { | |
| return nil, gofakes3.ErrNoSuchKey | |
| } else if err != nil { | |
| return nil, gofakes3.ErrNoSuchKey | |
| } | |
| if !fi.IsDir() { | |
| return nil, gofakes3.ErrNoSuchKey | |
| } | |
| dirEntries, err := fs.List(context.WithValue(ctx, "meta", meta), path, &fs.ListArgs{}) | |
| if err != nil { | |
| return nil, err | |
| } | |
| return dirEntries, nil | |
| } | |
| // func getFileHashByte(node interface{}) []byte { | |
| // b, err := hex.DecodeString(getFileHash(node)) | |
| // if err != nil { | |
| // return nil | |
| // } | |
| // return b | |
| // } | |
| func getFileHash(node interface{}) string { | |
| // var o fs.Object | |
| // switch b := node.(type) { | |
| // case vfs.Node: | |
| // fsObj, ok := b.DirEntry().(fs.Object) | |
| // if !ok { | |
| // fs.Debugf("serve s3", "File uploading - reading hash from VFS cache") | |
| // in, err := b.Open(os.O_RDONLY) | |
| // if err != nil { | |
| // return "" | |
| // } | |
| // defer func() { | |
| // _ = in.Close() | |
| // }() | |
| // h, err := hash.NewMultiHasherTypes(hash.NewHashSet(hash.MD5)) | |
| // if err != nil { | |
| // return "" | |
| // } | |
| // _, err = io.Copy(h, in) | |
| // if err != nil { | |
| // return "" | |
| // } | |
| // return h.Sums()[hash.MD5] | |
| // } | |
| // o = fsObj | |
| // case fs.Object: | |
| // o = b | |
| // } | |
| // hash, err := o.Hash(context.Background(), hash.MD5) | |
| // if err != nil { | |
| // return "" | |
| // } | |
| // return hash | |
| return "" | |
| } | |
| func prefixParser(p *gofakes3.Prefix) (path, remaining string) { | |
| idx := strings.LastIndexByte(p.Prefix, '/') | |
| if idx < 0 { | |
| return "", p.Prefix | |
| } | |
| return p.Prefix[:idx], p.Prefix[idx+1:] | |
| } | |
| // // FIXME this could be implemented by VFS.MkdirAll() | |
| // func mkdirRecursive(path string, VFS *vfs.VFS) error { | |
| // path = strings.Trim(path, "/") | |
| // dirs := strings.Split(path, "/") | |
| // dir := "" | |
| // for _, d := range dirs { | |
| // dir += "/" + d | |
| // if _, err := VFS.Stat(dir); err != nil { | |
| // err := VFS.Mkdir(dir, 0777) | |
| // if err != nil { | |
| // return err | |
| // } | |
| // } | |
| // } | |
| // return nil | |
| // } | |
| // func rmdirRecursive(p string, VFS *vfs.VFS) { | |
| // dir := path.Dir(p) | |
| // if !strings.ContainsAny(dir, "/\\") { | |
| // // might be bucket(root) | |
| // return | |
| // } | |
| // if _, err := VFS.Stat(dir); err == nil { | |
| // err := VFS.Remove(dir) | |
| // if err != nil { | |
| // return | |
| // } | |
| // rmdirRecursive(dir, VFS) | |
| // } | |
| // } | |
| func authlistResolver() map[string]string { | |
| s3accesskeyid := setting.GetStr(conf.S3AccessKeyId) | |
| s3secretaccesskey := setting.GetStr(conf.S3SecretAccessKey) | |
| if s3accesskeyid == "" && s3secretaccesskey == "" { | |
| return nil | |
| } | |
| authList := make(map[string]string) | |
| authList[s3accesskeyid] = s3secretaccesskey | |
| return authList | |
| } | |