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 }