110 lines
2.5 KiB
Go
110 lines
2.5 KiB
Go
package server
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"os"
|
|
"path"
|
|
"path/filepath"
|
|
"sort"
|
|
"strings"
|
|
"text/template"
|
|
"time"
|
|
)
|
|
|
|
/* this indexes and generate the page for viewing the archive directory */
|
|
func generateArchiveIndex(fsPath string, urlPath string) (string, error) {
|
|
info, err := os.Stat(fsPath)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if !info.IsDir() {
|
|
return "", fmt.Errorf("not a directory")
|
|
}
|
|
ents, err := os.ReadDir(fsPath)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
type entryInfo struct {
|
|
name string
|
|
isDir bool
|
|
href string
|
|
size int64
|
|
mod time.Time
|
|
}
|
|
var list []entryInfo
|
|
for _, e := range ents {
|
|
n := e.Name()
|
|
full := filepath.Join(fsPath, n)
|
|
st, err := os.Stat(full)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
isd := st.IsDir()
|
|
displayName := n
|
|
if isd {
|
|
displayName = n + "/"
|
|
}
|
|
href := path.Join(urlPath, n)
|
|
if isd && !strings.HasSuffix(href, "/") {
|
|
href = href + "/"
|
|
}
|
|
size := int64(-1)
|
|
if !isd {
|
|
size = st.Size()
|
|
}
|
|
list = append(list, entryInfo{name: displayName, isDir: isd, href: href, size: size, mod: st.ModTime()})
|
|
}
|
|
sort.Slice(list, func(i, j int) bool {
|
|
if list[i].isDir != list[j].isDir {
|
|
return list[i].isDir
|
|
}
|
|
return strings.ToLower(list[i].name) < strings.ToLower(list[j].name)
|
|
})
|
|
|
|
urlPath = strings.TrimPrefix(urlPath, "/archive")
|
|
|
|
var b strings.Builder
|
|
|
|
b.WriteString("<html>\n<head><title>Index of ")
|
|
b.WriteString(template.HTMLEscapeString(urlPath))
|
|
b.WriteString("</title></head>\n<body>\n<h1>Index of ")
|
|
b.WriteString(template.HTMLEscapeString(urlPath))
|
|
b.WriteString("</h1><hr><pre>")
|
|
b.WriteString("<a href=\"../\">../</a>\n")
|
|
|
|
nameCol := 50
|
|
for _, ei := range list {
|
|
escapedName := template.HTMLEscapeString(ei.name)
|
|
dateStr := ei.mod.Local().Format("02-Jan-2006 15:04")
|
|
var sizeStr string
|
|
if ei.isDir {
|
|
sizeStr = "-"
|
|
} else {
|
|
sizeStr = fmt.Sprintf("%d", ei.size)
|
|
}
|
|
spaces := 1
|
|
if len(escapedName) < nameCol {
|
|
spaces = nameCol - len(escapedName)
|
|
}
|
|
line := `<a href="` + template.HTMLEscapeString(ei.href) + `">` + escapedName + `</a>` + strings.Repeat(" ", spaces) + dateStr + strings.Repeat(" ", 19-len(sizeStr)) + sizeStr + "\n"
|
|
b.WriteString(line)
|
|
}
|
|
b.WriteString("</pre><hr></body>\n</html>")
|
|
return b.String(), nil
|
|
}
|
|
|
|
/* helper to read the archive files */
|
|
func readArchive(w http.ResponseWriter, route string) error {
|
|
fsPath := "." + route
|
|
if info, err := os.Stat(fsPath); err == nil && info.IsDir() {
|
|
if page, err := generateArchiveIndex(fsPath, route); err == nil {
|
|
w.Write([]byte(page))
|
|
return nil
|
|
} else {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|