|
|
@@ -10,6 +10,7 @@ import (
|
|
|
"errors"
|
|
|
"io"
|
|
|
"io/fs"
|
|
|
+ "net/url"
|
|
|
"path"
|
|
|
"path/filepath"
|
|
|
"regexp"
|
|
|
@@ -42,6 +43,16 @@ type ShortcutData struct {
|
|
|
Name string //The name of the shortcut
|
|
|
Path string //The path of shortcut
|
|
|
Icon string //The icon of shortcut
|
|
|
+
|
|
|
+ //Optional launch options, stored as key=value lines after the first four.
|
|
|
+ //Only honoured for url shortcuts; module shortcuts take them from init.agi
|
|
|
+ WindowTitle string //Custom floatWindow title, empty = shortcut name
|
|
|
+ OpenIn string //"float" (default) or "tab"
|
|
|
+ WindowWidth int //Initial floatWindow width, 0 = default
|
|
|
+ WindowHeight int //Initial floatWindow height, 0 = default
|
|
|
+
|
|
|
+ //Unknown key=value lines, kept so a rewrite does not drop them
|
|
|
+ Extra map[string]string `json:"-"`
|
|
|
}
|
|
|
|
|
|
var (
|
|
|
@@ -70,6 +81,7 @@ var (
|
|
|
//Operation errors
|
|
|
ErrOperationNotSupported = errors.New("FS_OPR_NOT_SUPPORTED")
|
|
|
ErrNullOperation = errors.New("FS_NULL_OPR")
|
|
|
+ ErrPathEscapesRoot = errors.New("FS_PATH_ESCAPES_ROOT")
|
|
|
)
|
|
|
|
|
|
// Generate a File Manager redirection error message
|
|
|
@@ -196,3 +208,28 @@ func Base(filename string) string {
|
|
|
return c[len(c)-1]
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+// ResolvePathWithinRoot decodes a relative path, normalizes separators, and
|
|
|
+// ensures the final path remains under rootPath.
|
|
|
+func ResolvePathWithinRoot(rootPath string, relativePath string) (string, error) {
|
|
|
+ decodedRelPath, err := url.PathUnescape(relativePath)
|
|
|
+ if err != nil {
|
|
|
+ return "", err
|
|
|
+ }
|
|
|
+
|
|
|
+ cleanRoot := filepath.Clean(rootPath)
|
|
|
+ normalizedRelPath := strings.ReplaceAll(decodedRelPath, "\\", "/")
|
|
|
+ targetPath := filepath.Join(cleanRoot, filepath.FromSlash(normalizedRelPath))
|
|
|
+
|
|
|
+ relToRoot, err := filepath.Rel(cleanRoot, targetPath)
|
|
|
+ if err != nil {
|
|
|
+ return "", err
|
|
|
+ }
|
|
|
+
|
|
|
+ cleanRelToRoot := filepath.ToSlash(relToRoot)
|
|
|
+ if cleanRelToRoot == ".." || strings.HasPrefix(cleanRelToRoot, "../") {
|
|
|
+ return "", ErrPathEscapesRoot
|
|
|
+ }
|
|
|
+
|
|
|
+ return targetPath, nil
|
|
|
+}
|