返回 DeepSeek-Reasonix
refs_external_path.go
根目录 / internal / control / refs_external_path.go
1 package control
2
3 import (
4 "os"
5 "path/filepath"
6 "slices"
7 "strings"
8 )
9
10 // ExternalFolderRefLocalPath resolves a registered external-folder token path
11 // to the local filesystem path authorized for this controller session.
12 func (c *Controller) ExternalFolderRefLocalPath(tokenPath string) (path, displayPath string, ok bool) {
13 _, rel, abs, ok := c.externalFolderRefTarget(tokenPath)
14 if !ok {
15 return "", "", false
16 }
17 path, ok = canonicalExternalFolderPath(abs, filepath.Join(abs, filepath.FromSlash(rel)))
18 if !ok {
19 return "", "", false
20 }
21 return path, externalFolderDisplayPath(abs, rel), true
22 }
23
24 // AuthorizedExternalFolderLocalPath validates an absolute path against the
25 // directories explicitly registered by the user for this controller session.
26 func (c *Controller) AuthorizedExternalFolderLocalPath(path string) (string, bool) {
27 if c == nil || strings.TrimSpace(path) == "" {
28 return "", false
29 }
30 c.externalFolderRefsMu.RLock()
31 roots := make([]string, 0, len(c.externalFolderRefs))
32 for _, root := range c.externalFolderRefs {
33 roots = append(roots, root)
34 }
35 c.externalFolderRefsMu.RUnlock()
36 for _, root := range roots {
37 if canonical, ok := canonicalExternalFolderPath(root, path); ok {
38 return canonical, true
39 }
40 }
41 return "", false
42 }
43
44 func canonicalExternalFolderPath(root, candidate string) (string, bool) {
45 realRoot, err := filepath.EvalSymlinks(root)
46 if err != nil {
47 return "", false
48 }
49 realCandidate, err := evalSymlinksAllowMissing(candidate)
50 if err != nil {
51 return "", false
52 }
53 rel, err := filepath.Rel(realRoot, realCandidate)
54 if err != nil || rel == ".." || strings.HasPrefix(rel, ".."+string(os.PathSeparator)) {
55 return "", false
56 }
57 return filepath.Clean(realCandidate), true
58 }
59
60 // evalSymlinksAllowMissing resolves all existing ancestors but permits a
61 // not-yet-created leaf used by display and open-path flows.
62 func evalSymlinksAllowMissing(path string) (string, error) {
63 path = filepath.Clean(path)
64 current := path
65 missing := make([]string, 0, 2)
66 for {
67 resolved, err := filepath.EvalSymlinks(current)
68 if err == nil {
69 for _, component := range slices.Backward(missing) {
70 resolved = filepath.Join(resolved, component)
71 }
72 return filepath.Clean(resolved), nil
73 }
74 if !os.IsNotExist(err) {
75 return "", err
76 }
77 parent := filepath.Dir(current)
78 if parent == current {
79 return "", err
80 }
81 missing = append(missing, filepath.Base(current))
82 current = parent
83 }
84 }
85
85 lines GO