From c09800790b000dbb444fcadef33a3dbc3b2ca36a Mon Sep 17 00:00:00 2001 From: Noah Hsu Date: Tue, 22 Nov 2022 15:54:18 +0800 Subject: [PATCH] feat: custom filename char mapping fixes #2447 #2446 #2440 #2409 #2006 #1979 #1507 #324 #691 #518 #430 --- go.sum | 4 ---- internal/bootstrap/data/setting.go | 1 + internal/conf/const.go | 14 +++++++------- internal/conf/var.go | 1 + internal/db/settinghooks.go | 12 ++++++++++++ internal/op/fs.go | 3 ++- pkg/utils/str.go | 10 ++++++++++ server/handles/fsread.go | 6 +++--- server/webdav/file.go | 4 +++- server/webdav/prop.go | 6 ++++-- 10 files changed, 43 insertions(+), 18 deletions(-) create mode 100644 pkg/utils/str.go diff --git a/go.sum b/go.sum index 1ce9c6d3..0e6e7ff0 100644 --- a/go.sum +++ b/go.sum @@ -12,8 +12,6 @@ github.com/aliyun/aliyun-oss-go-sdk v2.2.5+incompatible h1:QoRMR0TCctLDqBCMyOu1e github.com/aliyun/aliyun-oss-go-sdk v2.2.5+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= github.com/andreburgaud/crypt2go v1.1.0 h1:eitZxTPY1krUsxinsng3Qvt/Ud7q/aQmmYRh8p4hyPw= github.com/andreburgaud/crypt2go v1.1.0/go.mod h1:4qhZPzarj1dCIRmCkpdgCklwp+hBq9yEt0zPe9Ayuhc= -github.com/aws/aws-sdk-go v1.44.139 h1:Mj/OZBy9RTbzJ8pfgK6rOL8xgUEAIn8pfIN6qWFtpAk= -github.com/aws/aws-sdk-go v1.44.139/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/aws/aws-sdk-go v1.44.142 h1:KZ1/FDwCSft1DuNllFaBtWpcG0CW2NgQjvOrE1TdlXE= github.com/aws/aws-sdk-go v1.44.142/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/bluele/gcache v0.0.2 h1:WcbfdXICg7G/DGBh1PFfcirkWOQV+v077yF1pSy3DGw= @@ -381,8 +379,6 @@ gorm.io/driver/sqlite v1.4.3/go.mod h1:0Aq3iPO+v9ZKbcdiz8gLWRw5VOPcBOPUQJFLq5e2e gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= gorm.io/gorm v1.24.0/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA= gorm.io/gorm v1.24.1-0.20221019064659-5dd2bb482755/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA= -gorm.io/gorm v1.24.1 h1:CgvzRniUdG67hBAzsxDGOAuq4Te1osVMYsa1eQbd4fs= -gorm.io/gorm v1.24.1/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA= gorm.io/gorm v1.24.2 h1:9wR6CFD+G8nOusLdvkZelOEhpJVwwHzpQOUM+REd6U0= gorm.io/gorm v1.24.2/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= diff --git a/internal/bootstrap/data/setting.go b/internal/bootstrap/data/setting.go index d7028f8e..636af4a2 100644 --- a/internal/bootstrap/data/setting.go +++ b/internal/bootstrap/data/setting.go @@ -121,6 +121,7 @@ func InitialSettings() []model.SettingItem { (?U)access_token=(.*)&`, Type: conf.TypeText, Group: model.GLOBAL, Flag: model.PRIVATE}, {Key: conf.OcrApi, Value: "https://api.nn.ci/ocr/file/json", Type: conf.TypeString, Group: model.GLOBAL}, + {Key: conf.FilenameCharMapping, Value: `{"/": "|"}`, Type: conf.TypeText, Group: model.GLOBAL}, // aria2 settings {Key: conf.Aria2Uri, Value: "http://localhost:6800/jsonrpc", Type: conf.TypeString, Group: model.ARIA2, Flag: model.PRIVATE}, {Key: conf.Aria2Secret, Value: "", Type: conf.TypeString, Group: model.ARIA2, Flag: model.PRIVATE}, diff --git a/internal/conf/const.go b/internal/conf/const.go index 08ac2df1..400928c5 100644 --- a/internal/conf/const.go +++ b/internal/conf/const.go @@ -33,13 +33,13 @@ const ( VideoAutoplay = "video_autoplay" // global - HideFiles = "hide_files" - GlobalReadme = "global_readme" - CustomizeHead = "customize_head" - CustomizeBody = "customize_body" - LinkExpiration = "link_expiration" - PrivacyRegs = "privacy_regs" - OcrApi = "ocr_api" + HideFiles = "hide_files" + CustomizeHead = "customize_head" + CustomizeBody = "customize_body" + LinkExpiration = "link_expiration" + PrivacyRegs = "privacy_regs" + OcrApi = "ocr_api" + FilenameCharMapping = "filename_char_mapping" // aria2 Aria2Uri = "aria2_uri" diff --git a/internal/conf/var.go b/internal/conf/var.go index f1d7e0f9..cfe80d5b 100644 --- a/internal/conf/var.go +++ b/internal/conf/var.go @@ -16,6 +16,7 @@ var ( ) var TypesMap = make(map[string][]string) +var FilenameCharMap = make(map[string]string) var PrivacyReg []*regexp.Regexp var ( diff --git a/internal/db/settinghooks.go b/internal/db/settinghooks.go index a49019ea..6d968729 100644 --- a/internal/db/settinghooks.go +++ b/internal/db/settinghooks.go @@ -6,7 +6,9 @@ import ( "github.com/alist-org/alist/v3/internal/conf" "github.com/alist-org/alist/v3/internal/model" + "github.com/alist-org/alist/v3/pkg/utils" "github.com/pkg/errors" + log "github.com/sirupsen/logrus" ) type SettingItemHook struct { @@ -65,6 +67,16 @@ var SettingItemHooks = map[string]SettingItemHook{ return nil }, }, + conf.FilenameCharMapping: { + Hook: func(item *model.SettingItem) error { + err := utils.Json.UnmarshalFromString(item.Value, &conf.FilenameCharMap) + if err != nil { + return err + } + log.Debugf("filename char mapping: %+v", conf.FilenameCharMap) + return nil + }, + }, } func HandleSettingItem(item *model.SettingItem) (bool, error) { diff --git a/internal/op/fs.go b/internal/op/fs.go index bdeb669e..4bf45038 100644 --- a/internal/op/fs.go +++ b/internal/op/fs.go @@ -8,6 +8,7 @@ import ( "time" "github.com/Xhofe/go-cache" + "github.com/alist-org/alist/v3/internal/conf" "github.com/alist-org/alist/v3/internal/driver" "github.com/alist-org/alist/v3/internal/errs" "github.com/alist-org/alist/v3/internal/model" @@ -122,7 +123,7 @@ func Get(ctx context.Context, storage driver.Driver, path string) (model.Obj, er } for _, f := range files { // TODO maybe copy obj here - if f.GetName() == name { + if utils.MappingName(f.GetName(), conf.FilenameCharMap) == name { // use path as id, why don't set id in List function? // because files maybe cache, set id here can reduce memory usage if f.GetPath() == "" { diff --git a/pkg/utils/str.go b/pkg/utils/str.go new file mode 100644 index 00000000..f7ffb2fc --- /dev/null +++ b/pkg/utils/str.go @@ -0,0 +1,10 @@ +package utils + +import "strings" + +func MappingName(name string, m map[string]string) string { + for k, v := range m { + name = strings.ReplaceAll(name, k, v) + } + return name +} diff --git a/server/handles/fsread.go b/server/handles/fsread.go index 8d6e7d14..8e546bdb 100644 --- a/server/handles/fsread.go +++ b/server/handles/fsread.go @@ -140,7 +140,7 @@ func filterDirs(objs []model.Obj) []DirResp { for _, obj := range objs { if obj.IsDir() { dirs = append(dirs, DirResp{ - Name: obj.GetName(), + Name: utils.MappingName(obj.GetName(), conf.FilenameCharMap), Modified: obj.ModTime(), }) } @@ -208,7 +208,7 @@ func toObjResp(objs []model.Obj, parent string, encrypt bool) []ObjResp { tp = utils.GetFileType(obj.GetName()) } resp = append(resp, ObjResp{ - Name: obj.GetName(), + Name: utils.MappingName(obj.GetName(), conf.FilenameCharMap), Size: obj.GetSize(), IsDir: obj.IsDir(), Modified: obj.ModTime(), @@ -306,7 +306,7 @@ func FsGet(c *gin.Context) { parentMeta, _ := db.GetNearestMeta(parentPath) common.SuccessResp(c, FsGetResp{ ObjResp: ObjResp{ - Name: obj.GetName(), + Name: utils.MappingName(obj.GetName(), conf.FilenameCharMap), Size: obj.GetSize(), IsDir: obj.IsDir(), Modified: obj.ModTime(), diff --git a/server/webdav/file.go b/server/webdav/file.go index 4840f126..d3d8e319 100644 --- a/server/webdav/file.go +++ b/server/webdav/file.go @@ -10,9 +10,11 @@ import ( "path" "path/filepath" + "github.com/alist-org/alist/v3/internal/conf" "github.com/alist-org/alist/v3/internal/db" "github.com/alist-org/alist/v3/internal/fs" "github.com/alist-org/alist/v3/internal/model" + "github.com/alist-org/alist/v3/pkg/utils" ) // slashClean is equivalent to but slightly more efficient than @@ -99,7 +101,7 @@ func walkFS(ctx context.Context, depth int, name string, info model.Obj, walkFn } for _, fileInfo := range objs { - filename := path.Join(name, fileInfo.GetName()) + filename := path.Join(name, utils.MappingName(fileInfo.GetName(), conf.FilenameCharMap)) if err != nil { if err := walkFn(filename, fileInfo, err); err != nil && err != filepath.SkipDir { return err diff --git a/server/webdav/prop.go b/server/webdav/prop.go index 73f92a2f..fa7a15bc 100644 --- a/server/webdav/prop.go +++ b/server/webdav/prop.go @@ -15,7 +15,9 @@ import ( "path" "strconv" + "github.com/alist-org/alist/v3/internal/conf" "github.com/alist-org/alist/v3/internal/model" + "github.com/alist-org/alist/v3/pkg/utils" ) // Proppatch describes a property update instruction as defined in RFC 4918. @@ -197,7 +199,7 @@ func props(ctx context.Context, ls LockSystem, fi model.Obj, pnames []xml.Name) } // Otherwise, it must either be a live property or we don't know it. if prop := liveProps[pn]; prop.findFn != nil && (prop.dir || !isDir) { - innerXML, err := prop.findFn(ctx, ls, fi.GetName(), fi) + innerXML, err := prop.findFn(ctx, ls, utils.MappingName(fi.GetName(), conf.FilenameCharMap), fi) if err != nil { return nil, err } @@ -373,7 +375,7 @@ func findDisplayName(ctx context.Context, ls LockSystem, name string, fi model.O // Hide the real name of a possibly prefixed root directory. return "", nil } - return escapeXML(fi.GetName()), nil + return escapeXML(utils.MappingName(fi.GetName(), conf.FilenameCharMap)), nil } func findContentLength(ctx context.Context, ls LockSystem, name string, fi model.Obj) (string, error) {