// godlighty -- highly-customizable HTTP, HTTP/2, HTTPS server // Copyright (C) 2021-2024 Sergey Matveev // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, version 3 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . package godlighty import ( _ "embed" "html/template" "io/fs" "os" "path" "sort" "time" "github.com/dustin/go-humanize" ) const MTimeFmt = "2006-01-02 15:04:05Z" var ( //go:embed dirlist.tmpl DirListTmplRaw string DirListTmpl = template.Must(template.New("dirlist").Parse(DirListTmplRaw)) ) type ByName []fs.DirEntry func (a ByName) Len() int { return len(a) } func (a ByName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } func (a ByName) Less(i, j int) bool { return a[i].Name() < a[j].Name() } type DirListFile struct { Idx int Name string Size string IsDir bool Type string ModTime string Symlink string } func dirList( cfg *HostCfg, dir, pth string, entries []os.DirEntry, readme string, ) (*os.File, error) { sort.Sort(ByName(entries)) files := make([]DirListFile, 0, len(entries)) for i, entry := range entries { fi, err := entry.Info() if err != nil { return nil, err } file := DirListFile{ Idx: i, Name: fi.Name(), Size: humanize.IBytes(uint64(fi.Size())), ModTime: fi.ModTime().UTC().Truncate(time.Second).Format(MTimeFmt), } if fi.IsDir() { file.IsDir = true } else { file.Type = mediaType(file.Name, cfg.MIMEs) } if (entry.Type() & fs.ModeSymlink) > 0 { file.Symlink, _ = os.Readlink(path.Join(pth, fi.Name())) } files = append(files, file) } fd, err := os.CreateTemp("", "godlist-dirlist-") if err != nil { return nil, err } os.Remove(fd.Name()) var root string if dir == "/" { dir = "" root = "/" } err = DirListTmpl.Execute(fd, struct { Root string Dir string Files []DirListFile Readme string }{ Root: root, Dir: dir, Files: files, Readme: readme, }) if err != nil { fd.Close() return nil, err } return fd, err }