feat: initial commit — unarr CLI

Search, inspect, stream, and download torrents from the terminal.
Replaces the entire *arr stack with a single binary.
This commit is contained in:
Deivid Soto 2026-03-28 11:29:42 +01:00
commit 29cf0a0126
85 changed files with 10178 additions and 0 deletions

View file

@ -0,0 +1,37 @@
package engine
import (
"fmt"
"path/filepath"
"strings"
)
// isWithinDir checks that resolved is a child of baseDir (prevents path traversal).
// Both paths must be absolute and clean.
func isWithinDir(baseDir, resolved string) bool {
base := filepath.Clean(baseDir)
target := filepath.Clean(resolved)
return target == base || strings.HasPrefix(target, base+string(filepath.Separator))
}
// safePath constructs a path under baseDir and validates it doesn't escape.
// Returns an error if the resulting path is outside baseDir.
// If the resulting path exists and is a symlink that resolves outside baseDir,
// it is also rejected.
func safePath(baseDir, untrusted string) (string, error) {
resolved := filepath.Join(baseDir, untrusted) // Join already cleans
if !isWithinDir(baseDir, resolved) {
return "", fmt.Errorf("path traversal blocked: %q escapes %q", untrusted, baseDir)
}
// Resolve symlinks if the path already exists on disk
if real, err := filepath.EvalSymlinks(resolved); err == nil {
if !isWithinDir(baseDir, real) {
return "", fmt.Errorf("path traversal blocked: %q resolves outside %q via symlink", untrusted, baseDir)
}
return real, nil
}
return resolved, nil
}