fix support for sub folders

This commit is contained in:
visionmercer 2026-03-23 12:13:35 +01:00
commit a4c02cdbc1
2 changed files with 21 additions and 17 deletions

View file

@ -4,7 +4,6 @@ import (
"fmt"
"html/template"
"io"
"log"
"mime"
"net/http"
"net/url"
@ -22,6 +21,12 @@ type Handler struct {
tmpl *template.Template
}
// breadcrumb represents a link in the navigation chain
type breadcrumb struct {
Name string
URL string
}
func New(dir string) *Handler {
h := &Handler{dir: dir}
h.tmpl = template.Must(
@ -50,11 +55,9 @@ type libraryEntry struct {
}
func (h *Handler) ListISOs(w http.ResponseWriter, r *http.Request) {
// The path after / is the directory we are browsing in the library
relDir := strings.TrimPrefix(r.URL.Path, "/")
fullPath := filepath.Join(h.dir, relDir)
// Security check
if strings.Contains(relDir, "..") {
http.Error(w, "Invalid path", http.StatusBadRequest)
return
@ -85,11 +88,9 @@ func (h *Handler) ListISOs(w http.ResponseWriter, r *http.Request) {
if isISO {
basePath := filepath.Join(h.dir, relDir, strings.TrimSuffix(name, ".iso"))
// Metadata
if d, err := os.ReadFile(basePath + ".txt"); err == nil {
item.Description = string(d)
}
// Cover Image
for _, ext := range []string{".png", ".jpg", ".jpeg"} {
if _, err := os.Stat(basePath + ext); err == nil {
item.HasImage = true
@ -99,7 +100,6 @@ func (h *Handler) ListISOs(w http.ResponseWriter, r *http.Request) {
}
}
// Only show Directories or ISO files
if item.IsDir || item.IsISO {
items = append(items, item)
}
@ -118,9 +118,6 @@ func (h *Handler) ListISOs(w http.ResponseWriter, r *http.Request) {
})
}
// ... BrowseISO, DownloadFile, and RawFile remain largely same as previous version ...
// ... Ensure BrowseISO and DownloadFile use the full relative path to open the ISO ...
func (h *Handler) BrowseISO(w http.ResponseWriter, r *http.Request) {
isoPath, internalPath, ok := parsePath(r.URL.Path, "/browse/")
if !ok {
@ -222,15 +219,20 @@ func buildLibraryBreadcrumbs(relDir string) []breadcrumb {
acc := ""
for _, p := range strings.Split(relDir, "/") {
if p == "" { continue }
acc = filepath.Join(acc, p)
if acc == "" { acc = p } else { acc = filepath.Join(acc, p) }
crumbs = append(crumbs, breadcrumb{Name: p, URL: "/" + filepath.ToSlash(acc)})
}
return crumbs
}
func buildISOBreadcrumbs(isoPath, internalPath string) []breadcrumb {
crumbs := buildLibraryBreadcrumbs(filepath.Dir(isoPath))
if crumbs[len(crumbs)-1].Name == "." { crumbs = crumbs[:len(crumbs)-1] }
parentDir := filepath.Dir(isoPath)
var crumbs []breadcrumb
if parentDir == "." {
crumbs = []breadcrumb{{Name: "Library", URL: "/"}}
} else {
crumbs = buildLibraryBreadcrumbs(parentDir)
}
crumbs = append(crumbs, breadcrumb{Name: filepath.Base(isoPath), URL: "/browse/" + url.PathEscape(isoPath)})
if internalPath != "" {
@ -256,7 +258,8 @@ func fileIcon(name string) string {
switch ext {
case ".iso": return "💿"
case ".pdf": return "📄"
case ".jpg", ".png": return "🖼️"
case ".jpg", ".png", ".jpeg": return "🖼️"
case ".txt", ".md": return "📝"
default: return "📄"
}
}
@ -273,7 +276,7 @@ const allTemplates = `
.logo { color: var(--accent); font-weight: bold; text-decoration: none; font-family: monospace; }
main { max-width: 1100px; margin: 0 auto; padding: 2rem; }
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 1.5rem; }
.card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; display: flex; flex-direction: column; text-decoration: none; color: inherit; transition: transform 0.1s; }
.card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; display: flex; flex-direction: column; text-decoration: none; color: inherit; transition: transform 0.1s; position: relative;}
.card:hover { transform: translateY(-3px); border-color: var(--accent); }
.card-img { width: 100%; height: 150px; object-fit: cover; background: #000; }
.folder-icon { height: 150px; display: flex; align-items: center; justify-content: center; font-size: 4rem; background: #1c202d; color: #f7c948; }
@ -287,6 +290,7 @@ const allTemplates = `
.tbl th { text-align: left; padding: 1rem; background: #1e2132; color: var(--muted); font-size: 0.75rem; }
.tbl td { padding: 1rem; border-bottom: 1px solid var(--border); }
.dl-btn { border: 1px solid var(--accent); color: var(--accent); padding: 0.2rem 0.5rem; border-radius: 4px; font-size: 0.7rem; text-decoration: none; }
.dl-btn:hover { background: var(--accent); color: #fff; }
</style>
{{end}}
@ -318,7 +322,8 @@ const allTemplates = `
<a href="/browse/{{urlenc .RelativePath}}" class="card-name">{{.Name}}</a>
<p class="card-desc">{{if .Description}}{{.Description}}{{else}}ISO Disk Image{{end}}</p>
<div style="margin-top:1rem; display:flex; gap:0.5rem;">
<a href="/raw/{{urlenc .RelativePath}}" class="dl-btn" download>Download ISO</a>
<a href="/browse/{{urlenc .RelativePath}}" class="dl-btn">Browse</a>
<a href="/raw/{{urlenc .RelativePath}}" class="dl-btn" download>ISO</a>
</div>
</div>
</div>