67 lines
1.3 KiB
Go
67 lines
1.3 KiB
Go
package api
|
|
|
|
import (
|
|
"errors"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
"sort"
|
|
"strings"
|
|
)
|
|
|
|
func (s *Server) handleSources(w http.ResponseWriter, r *http.Request) {
|
|
absPath, err := normalizeSourcePathQuery(r.URL.Query().Get("path"))
|
|
if err != nil {
|
|
jsonErr(w, http.StatusBadRequest, err.Error())
|
|
return
|
|
}
|
|
if absPath == "" {
|
|
jsonOK(w, map[string]any{"path": "", "items": []map[string]string{}})
|
|
return
|
|
}
|
|
|
|
entries, err := os.ReadDir(absPath)
|
|
if err != nil {
|
|
jsonOK(w, map[string]any{"path": absPath, "items": []map[string]string{}})
|
|
return
|
|
}
|
|
|
|
type item struct {
|
|
Name string `json:"name"`
|
|
Path string `json:"path"`
|
|
}
|
|
|
|
var items []item
|
|
for _, e := range entries {
|
|
if !e.IsDir() || strings.HasPrefix(e.Name(), ".") {
|
|
continue
|
|
}
|
|
childPath := filepath.Join(absPath, e.Name())
|
|
items = append(items, item{
|
|
Name: e.Name(),
|
|
Path: childPath,
|
|
})
|
|
}
|
|
|
|
sort.Slice(items, func(i, j int) bool {
|
|
return strings.ToLower(items[i].Name) < strings.ToLower(items[j].Name)
|
|
})
|
|
|
|
jsonOK(w, map[string]any{
|
|
"path": absPath,
|
|
"items": items,
|
|
})
|
|
}
|
|
|
|
func normalizeSourcePathQuery(raw string) (string, error) {
|
|
raw = strings.TrimSpace(raw)
|
|
if raw == "" || raw == "." {
|
|
return "", nil
|
|
}
|
|
clean := filepath.Clean(raw)
|
|
if !filepath.IsAbs(clean) {
|
|
return "", errors.New("invalid source path")
|
|
}
|
|
return clean, nil
|
|
}
|