2022-12-14 22:41:37 +00:00
|
|
|
package filer
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"path"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
2023-06-23 14:07:09 +00:00
|
|
|
// WorkspaceRootPath can be joined with a relative path and ensures that
|
2022-12-14 22:41:37 +00:00
|
|
|
// the returned path is always a strict child of the root path.
|
2023-06-23 14:07:09 +00:00
|
|
|
type WorkspaceRootPath struct {
|
2022-12-14 22:41:37 +00:00
|
|
|
rootPath string
|
|
|
|
}
|
|
|
|
|
2023-06-23 14:07:09 +00:00
|
|
|
// NewWorkspaceRootPath constructs and returns [RootPath].
|
2022-12-14 22:41:37 +00:00
|
|
|
// The named path is cleaned on construction.
|
2023-06-23 14:07:09 +00:00
|
|
|
func NewWorkspaceRootPath(name string) WorkspaceRootPath {
|
|
|
|
return WorkspaceRootPath{
|
2022-12-14 22:41:37 +00:00
|
|
|
rootPath: path.Clean(name),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Join returns the specified path name joined to the root.
|
|
|
|
// It returns an error if the resulting path is not a strict child of the root path.
|
2023-06-23 14:07:09 +00:00
|
|
|
func (p *WorkspaceRootPath) Join(name string) (string, error) {
|
2022-12-14 22:41:37 +00:00
|
|
|
absPath := path.Join(p.rootPath, name)
|
|
|
|
|
|
|
|
// Don't allow escaping the specified root using relative paths.
|
|
|
|
if !strings.HasPrefix(absPath, p.rootPath) {
|
|
|
|
return "", fmt.Errorf("relative path escapes root: %s", name)
|
|
|
|
}
|
|
|
|
|
|
|
|
return absPath, nil
|
|
|
|
}
|