package main import ( "fmt" "io/fs" "html/template" "io" "net/http" "os" "path/filepath" "strings" ) type DirEntry struct { Name string Size string Url string mod int64 } func Si(d int64) string { f := float64(d) i := 0 for f > 1024 { f /= 1024 i++ } s := fmt.Sprintf("%.2f", f) s = strings.TrimRight(s, ".0") return fmt.Sprintf("%s %cB", s, " KMGTPEZY"[i]) } type TemplateData struct { Path string Dirs []DirEntry Items []DirEntry } func (t *TemplateData) add(a DirEntry, size int64, dir bool) { if dir { t.Dirs = append(t.Dirs, a) } else { a.Size = Si(size) t.Items = append(t.Items, a) } } func (t *TemplateData) sortNewest() { for _, tt := range []*[]DirEntry{&t.Items, &t.Dirs} { for i := 0; i < len(*tt); i++ { for j := i + 1; j < len(*tt); j++ { if (*tt)[i].mod < (*tt)[j].mod { (*tt)[i], (*tt)[j] = (*tt)[j], (*tt)[i] } } } } } var Temp *template.Template var HttpCodes = map[int]string{ 404: "Not Found", 500: "Internal Server Error", 403: "Forbidden", 401: "Unauthorized", 400: "Bad Request", 200: "OK", } func FillError(w io.Writer, err error, code int) bool { if err == nil { return false } _ = Temp.ExecuteTemplate(w, "index", map[string]string{ "Error": fmt.Sprintf("%d: %s", code, HttpCodes[code]), }) return true } func customFileServer(root http.Dir) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { upath := r.URL.Path f, err := root.Open(upath) if FillError(w, err, 404) { return } defer f.Close() var fi fs.FileInfo fi, err = f.Stat() if FillError(w, err, 500) { return } if fi.IsDir() { var fi []fs.FileInfo fi, err = f.Readdir(0) if FillError(w, err, 500) { return } t := TemplateData{Path: upath, Dirs: []DirEntry{}, Items: []DirEntry{}} for _, d := range fi { t.add(DirEntry{ Name: d.Name(), Url: filepath.Join(upath, d.Name()), mod: d.ModTime().Unix(), }, d.Size(), d.IsDir()) } t.sortNewest() Temp.ExecuteTemplate(w, "index", t) return } http.FileServer(root).ServeHTTP(w, r) }) } func main() { // Fs := os.DirFS(Config.HTTPDir) http.Handle("/", customFileServer(http.Dir(Config.HTTPDir))) // http.Handle("/", http.StripPrefix("/", FileServer(http.Dir(Config.HTTPDir)))) http.ListenAndServe(Config.Listen, nil) } var Config struct { HTTPDir string Listen string } func init() { Temp, _ = template.New("index").Parse(embedHtml) httpdir := os.Getenv("HTTP_DIR") if httpdir == "" { httpdir = "." } Config.HTTPDir, _ = filepath.Abs(httpdir) Config.Listen = os.Getenv("ADDR") if Config.Listen == "" { Config.Listen = "127.0.0.1" } Config.Listen += ":" n := len(Config.Listen) Config.Listen += os.Getenv("PORT") if len(Config.Listen) == n { Config.Listen += "8844" } } var embedHtml = `{{ define "index" }} {{ if .Path }} {{ .Path }} {{ else }} {{ if .Upload }} Upload {{ else }} Error {{ end }} {{ end }} {{ if .Path }}

Index of: {{ .Path }}

F ..
{{ range .Dirs }}
f {{ .Name }}
{{ end }} {{ range .Items }}
f {{ .Name }}{{ .Size }}
{{ end }}
{{ else }} {{ if .Error }}

{{ .Error }}

{{ else }} {{ if .Upload }}

Upload

Path:
File:
Username:
Password:
OTP:
{{ end }} {{ end }} {{ end }} {{ end }}`