diff --git a/internal/handlers/handlers.go b/internal/handlers/handlers.go index af3df85..301802a 100644 --- a/internal/handlers/handlers.go +++ b/internal/handlers/handlers.go @@ -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; } {{end}} @@ -318,7 +322,8 @@ const allTemplates = ` {{.Name}}
{{if .Description}}{{.Description}}{{else}}ISO Disk Image{{end}}
diff --git a/main.go b/main.go index 99c2a6a..0f37527 100644 --- a/main.go +++ b/main.go @@ -22,11 +22,10 @@ func main() { mux := http.NewServeMux() h := handlers.New(*dir) - // Routes mux.HandleFunc("/browse/", h.BrowseISO) mux.HandleFunc("/file/", h.DownloadFile) mux.HandleFunc("/raw/", h.RawFile) - mux.HandleFunc("/", h.ListISOs) // Catch-all for directory navigation + mux.HandleFunc("/", h.ListISOs) fmt.Printf("ISOSilo running at %s\n", *addr) log.Fatal(http.ListenAndServe(*addr, mux))