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("\nIndex of ") b.WriteString(template.HTMLEscapeString(urlPath)) b.WriteString("\n\n

Index of ") b.WriteString(template.HTMLEscapeString(urlPath)) b.WriteString("


")

	if urlPath != "/" {
		b.WriteString(
			`../` + "\n",
		)
	} else {
		b.WriteString(
			`../` + "\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 := `` + escapedName + `` + strings.Repeat(" ", spaces) + dateStr + strings.Repeat(" ", 19-len(sizeStr)) + sizeStr + "\n"
		b.WriteString(line)
	}
	b.WriteString("

\n") 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 }