refactor(gui): разделить app.go на binding-файлы по доменам, вынести sync apply
- app.go (1810→280 строк): только App struct, startup, DTOs, helpers
- bindings_{nodes,files,notes,actions,worklog,activity,sync,settings}.go
- sync_apply.go: все applyRemote* методы
- i18n: internal/i18n (Go, embed JSON) + frontend/src/lib/i18n (JS)
- core/sync/safe_path.go: SafeVaultPath
- scripts/check-i18n.sh: проверка хардкода кириллицы и bidi-символов
- build.sh: NVM loading, set -e
Все сборки (CLI, server, gui, frontend), go vet, go test проходят.
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
package sync
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// SafeVaultPath validates that relPath is a safe relative path within vaultRoot.
|
||||
// It rejects absolute paths, paths with ".." that escape vaultRoot, and empty paths.
|
||||
func SafeVaultPath(vaultRoot, relPath string) (string, error) {
|
||||
if relPath == "" {
|
||||
return "", fmt.Errorf("empty path")
|
||||
}
|
||||
if filepath.IsAbs(relPath) {
|
||||
return "", fmt.Errorf("absolute path not allowed: %s", relPath)
|
||||
}
|
||||
clean := filepath.Clean(relPath)
|
||||
if strings.HasPrefix(clean, "..") || strings.Contains(clean, "../") || strings.HasPrefix(clean, "\\..") {
|
||||
return "", fmt.Errorf("path escapes vault: %s", relPath)
|
||||
}
|
||||
joined := filepath.Join(vaultRoot, clean)
|
||||
// Verify we're still inside vaultRoot after Clean.
|
||||
if !strings.HasPrefix(joined, filepath.Clean(vaultRoot)+string(filepath.Separator)) && joined != filepath.Clean(vaultRoot) {
|
||||
return "", fmt.Errorf("path escapes vault after join: %s", relPath)
|
||||
}
|
||||
return clean, nil
|
||||
}
|
||||
|
||||
// SafeVaultPaths validates multiple paths and returns the first error.
|
||||
func SafeVaultPaths(vaultRoot string, paths ...string) error {
|
||||
for _, p := range paths {
|
||||
if _, err := SafeVaultPath(vaultRoot, p); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user