Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alist-org
GitHub Repository: alist-org/alist
Path: blob/main/pkg/utils/path.go
1560 views
1
package utils
2
3
import (
4
"net/url"
5
stdpath "path"
6
"strings"
7
8
"github.com/alist-org/alist/v3/internal/errs"
9
)
10
11
// FixAndCleanPath
12
// The upper layer of the root directory is still the root directory.
13
// So ".." And "." will be cleared
14
// for example
15
// 1. ".." or "." => "/"
16
// 2. "../..." or "./..." => "/..."
17
// 3. "../.x." or "./.x." => "/.x."
18
// 4. "x//\\y" = > "/z/x"
19
func FixAndCleanPath(path string) string {
20
path = strings.ReplaceAll(path, "\\", "/")
21
if !strings.HasPrefix(path, "/") {
22
path = "/" + path
23
}
24
return stdpath.Clean(path)
25
}
26
27
// PathAddSeparatorSuffix Add path '/' suffix
28
// for example /root => /root/
29
func PathAddSeparatorSuffix(path string) string {
30
if !strings.HasSuffix(path, "/") {
31
path = path + "/"
32
}
33
return path
34
}
35
36
// PathEqual judge path is equal
37
func PathEqual(path1, path2 string) bool {
38
return FixAndCleanPath(path1) == FixAndCleanPath(path2)
39
}
40
41
func IsSubPath(path string, subPath string) bool {
42
path, subPath = FixAndCleanPath(path), FixAndCleanPath(subPath)
43
return path == subPath || strings.HasPrefix(subPath, PathAddSeparatorSuffix(path))
44
}
45
46
func Ext(path string) string {
47
ext := stdpath.Ext(path)
48
if len(ext) > 0 && ext[0] == '.' {
49
ext = ext[1:]
50
}
51
return strings.ToLower(ext)
52
}
53
54
func EncodePath(path string, all ...bool) string {
55
seg := strings.Split(path, "/")
56
toReplace := []struct {
57
Src string
58
Dst string
59
}{
60
{Src: "%", Dst: "%25"},
61
{"%", "%25"},
62
{"?", "%3F"},
63
{"#", "%23"},
64
}
65
for i := range seg {
66
if len(all) > 0 && all[0] {
67
seg[i] = url.PathEscape(seg[i])
68
} else {
69
for j := range toReplace {
70
seg[i] = strings.ReplaceAll(seg[i], toReplace[j].Src, toReplace[j].Dst)
71
}
72
}
73
}
74
return strings.Join(seg, "/")
75
}
76
77
func JoinBasePath(basePath, reqPath string) (string, error) {
78
/** relative path:
79
* 1. ..
80
* 2. ../
81
* 3. /..
82
* 4. /../
83
* 5. /a/b/..
84
*/
85
if reqPath == ".." ||
86
strings.HasSuffix(reqPath, "/..") ||
87
strings.HasPrefix(reqPath, "../") ||
88
strings.Contains(reqPath, "/../") {
89
return "", errs.RelativePath
90
}
91
92
reqPath = FixAndCleanPath(reqPath)
93
94
if strings.HasPrefix(reqPath, "/") {
95
return reqPath, nil
96
}
97
98
return stdpath.Join(FixAndCleanPath(basePath), FixAndCleanPath(reqPath)), nil
99
}
100
101
func GetFullPath(mountPath, path string) string {
102
return stdpath.Join(GetActualMountPath(mountPath), path)
103
}
104
105