idk i forgot honestly
sophuwu sophie@skisiel.com
Sun, 23 Mar 2025 14:07:09 +0100
6 files changed,
375 insertions(+),
18 deletions(-)
M
dir/dirent.go
→
dir/dirent.go
@@ -53,7 +53,7 @@ })
} return } - if fi.Mode().IsRegular() { + if fi.Mode().IsRegular() || fi.Mode().Type() == fs.ModeSymlink { data, err = io.ReadAll(f) return }
M
fileserver/fileserver.go
→
fileserver/fileserver.go
@@ -13,6 +13,7 @@ "os"
"path/filepath" "sophuwu.site/cdn/config" "strings" + "time" ) type DirEntry struct {@@ -144,27 +145,88 @@ </html>
{{ end }}`) } +type readseek struct { + bb []byte + i int +} + +func (r *readseek) Read(p []byte) (n int, err error) { + if len(p) > len(r.bb)-r.i { + n = len(r.bb) - r.i + } else { + n = len(p) + } + for i := 0; i < n; i++ { + p[i] = r.bb[r.i+i] + } + r.i += n + if r.i >= len(r.bb) { + err = io.EOF + } + return +} +func (r *readseek) Seek(offset int64, whence int) (int64, error) { + var n int + switch whence { + case io.SeekStart: + n = int(offset) + case io.SeekCurrent: + n = r.i + int(offset) + case io.SeekEnd: + n = len(r.bb) + int(offset) + } + if n < 0 || n > len(r.bb) { + return 0, fmt.Errorf("invalid offset") + } + r.i = n + return int64(r.i), nil +} + +func (r *readseek) nullify() { + r.bb = []byte{} +} +func newReadSeek(b []byte) *readseek { + return &readseek{b, 0} +} + +type writer struct { + bb []byte +} + +func (r *writer) Write(p []byte) (n int, err error) { + r.bb = append(r.bb, p...) + return len(p), nil +} +func (r *writer) nullify() { + r.bb = []byte{} +} +func (r *writer) convert() *readseek { + return newReadSeek(r.bb) +} +func newWriter() *writer { + return &writer{bb: []byte{}} +} + func Handler(prefix string, dir func(string) ([]byte, []DirEntry, error)) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ww := newWriter() data, items, err := dir(strings.TrimPrefix(r.URL.Path, prefix)) - if FillError(w, err, 404) { - return + if !FillError(ww, err, 404) && data != nil { + ww.Write(data) + } else { + err = FillTemp(ww, r.URL.Path, append([]DirEntry{{ + Name: "../", + FullName: filepath.Dir(strings.TrimSuffix(r.URL.Path, "/")), + Size: 0, + IsDir: true, + }}, items...)) + FillError(ww, err, 500) } - w.WriteHeader(http.StatusOK) - if data != nil { - w.Write(data) - return - } - items = append([]DirEntry{{ - Name: "../", - FullName: filepath.Dir(strings.TrimSuffix(r.URL.Path, "/")), - Size: 0, - IsDir: true, - }}, items...) - err = FillTemp(w, r.URL.Path, items) - if FillError(w, err, 500) { - return - } + rs := ww.convert() + ww.nullify() + w.WriteHeader(http.StatusNotModified) + http.ServeContent(w, r, filepath.Base(r.URL.Path), time.Time{}, rs) + rs.nullify() }) }
M
go.sum
→
go.sum
@@ -1,3 +1,5 @@
+github.com/blang/vfs v1.0.0 h1:AUZUgulCDzbaNjTRWEP45X7m/J10brAptZpSRKRZBZc= +github.com/blang/vfs v1.0.0/go.mod h1:jjuNUc/IKcRNNWC9NUCvz4fR9PZLPIKxEygtPs/4tSI= github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI= github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
A
test/index.html
@@ -0,0 +1,71 @@
+{{ define "index" }} +<!DOCTYPE html> +<html> +<head> +{{ if .Path }} +<title>{{ .Path }}</title> +{{ else }} +{{ if .Upload }} +<title>Upload</title> +{{ else }} +<title>Error</title> +{{ end }} +{{ end }} +<style> +:root {--bord: #ccc;--fg: #fff;} +body {width: calc(100% - 2ch);margin: auto auto auto auto ;max-width: 800px;background: #262833;color: var(--fg);font-family: sans-serif;} +.trees {width: 100%;display: flex;flex-direction: column;padding: 0;margin: auto auto;border: 1px solid var(--bord);border-radius: 1ch;overflow: hidden;} +.trees a {display: contents;text-decoration: none;} +.filelabel {padding: 8px;font-size: 1rem;width: auto;margin: 0;display: grid;grid-template-columns: auto auto;grid-gap: 1ch;justify-content: space-between;align-items: center;border-radius: 0;background: transparent;} +.trees > a > * {border-bottom: 1px solid var(--bord);background: #1c1e26;} +.trees > a > *:hover {background: #2c2e46;} +.trees > a:last-child > * {border-bottom: none;} +a {color: var(--fg);text-decoration: none;} +.filelabel > :last-child {text-align: right;} +@font-face { + font-family: "sophuwuicons"; + /*src: url("/static/icons.woff2") format("woff2"),*/ + src: url("http://soph/font/sophicons/sophuwuicons.woff2") format("woff2"), + /*url("/static/icons.ttf") format("truetype")*/ + url("http://soph/font/sophicons/sophuwuicons.ttf") format("truetype") +} +.icon { + font-family: "sophuwuicons"; + font-size: inherit; + font-weight: normal !important; + font-style: normal; + height: 1em; +} +</style> +</head> +<body> +{{ if .Path }} +<h1>Index of: {{ .Path }}</h1> +<div class="trees"> +{{ range .Dirs }} +<a href="{{ .Name }}"><div class="filelabel"><span class="icon"></span><span>{{ .Name }}</span><span></span></div></a> +{{ end }} +{{ range .Items }} +<a href="{{ .Name }}"><div class="filelabel"><span class="icon"></span><span>{{ .Name }}</span><span>{{ .Size }}</span></div></a> +{{ end }} +</div> +{{ else }} +{{ if .Error }} +<h1>{{ .Error }}</h1> +{{ else }} +{{ if .Upload }} +<h1>Upload</h1> +<form class="trees" enctype="multipart/form-data" action="{{ .Upload }}" method="post"> + <div class="filelabel"><span>Path:</span><input type="text" name="path" /></div> + <div class="filelabel"><span>File:</span><input type="file" name="myFile" /></div> + <div class="filelabel"><span>Username:</span><input type="text" name="username" /></div> + <div class="filelabel"><span>Password:</span><input type="password" name="password" /></div> + <div class="filelabel"><span>OTP:</span><input type="text" name="otp" /></div> + <div class="filelabel"><span></span><input type="submit" value="Upload" /></div> +</form> +{{ end }} +{{ end }} +{{ end }} +</body> +</html> +{{ end }}
A
test/test.go
@@ -0,0 +1,221 @@
+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" }} +<!DOCTYPE html> +<html> +<head> +{{ if .Path }} +<title>{{ .Path }}</title> +{{ else }} +{{ if .Upload }} +<title>Upload</title> +{{ else }} +<title>Error</title> +{{ end }} +{{ end }} +<style> +:root {--bord: #ccc;--fg: #fff;} +body {width: calc(100% - 2ch);margin: auto auto auto auto ;max-width: 800px;background: #262833;color: var(--fg);font-family: sans-serif;} +.trees {width: 100%;display: flex;flex-direction: column;padding: 0;margin: auto auto;border: 1px solid var(--bord);border-radius: 1ch;overflow: hidden;} +.trees a {display: contents;text-decoration: none;} +.filelabel {padding: 8px;font-size: 1rem;width: auto;margin: 0;display: grid;grid-template-columns: auto auto;grid-gap: 1ch;justify-content: space-between;align-items: center;border-radius: 0;background: transparent;} +.trees > a > * {border-bottom: 1px solid var(--bord);background: #1c1e26;} +.trees > a > *:hover {background: #2c2e46;} +.trees > a:last-child > * {border-bottom: none;} +a {color: var(--fg);text-decoration: none;} +.filelabel > :last-child {text-align: right;} +@font-face { + font-family: "sophuwuicons"; + src: url("data:font/ttf;base64,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AH4AgACBAOwA7gC6B3VuaTAwMDAHdW5pMDAwMQd1bmkwMDAyB3VuaTAwMDMHdW5pMDAwNAd1bmkwMDA1B3VuaTAwMDYHdW5pMDAwNwd1bmkwMDA4B3VuaTAwMDkHdW5pMDAwQQd1bmkwMDBCB3VuaTAwMEMHdW5pMDAwRAd1bmkwMDBFB3VuaTAwMEYHdW5pMDAxMAd1bmkwMDExB3VuaTAwMTIHdW5pMDAxMwd1bmkwMDE0B3VuaTAwMTUHdW5pMDAxNgd1bmkwMDE3B3VuaTAwMTgHdW5pMDAxOQd1bmkwMDFBB3VuaTAwMUIHdW5pMDAxQwd1bmkwMDFEB3VuaTAwMUUHdW5pMDAxRgd1bmkwMDdGB3VuaTAwODAHdW5pMDA4MQd1bmkwMDgyB3VuaTAwODMHdW5pMDA4NAd1bmkwMDg1B3VuaTAwODYHdW5pMDA4Nwd1bmkwMDg4B3VuaTAwODkHdW5pMDA4QQd1bmkwMDhCB3VuaTAwOEMHdW5pMDA4RAd1bmkwMDhFB3VuaTAwOEYHdW5pMDA5MAd1bmkwMDkxB3VuaTAwOTIHdW5pMDA5Mwd1bmkwMDk0B3VuaTAwOTUHdW5pMDA5Ngd1bmkwMDk3B3VuaTAwOTgHdW5pMDA5OQd1bmkwMDlBB3VuaTAwOUIHdW5pMDA5Qwd1bmkwMDlEB3VuaTAwOUUHdW5pMDA5Rgd1bmkwMEEwB3VuaTAwQUQHdW5pMDBCMgd1bmkwMEIzB3VuaTAwQjkAAAAB//8AAgAAAAEAAAAA4p8rRgAAAADjXf2mAAAAAOQFcDk=") format("truetype"); +} +.icon { + font-family: "sophuwuicons"; + font-size: inherit; + font-weight: normal !important; + font-style: normal; +} +</style> +</head> +<body> +{{ if .Path }} +<h1>Index of: {{ .Path }}</h1> +<div class="trees"> +<a href=".."><div class="filelabel"><span><b class="icon">F</b> ..</span><span></span></div></a> +{{ range .Dirs }} +<a href="{{ .Url }}"><div class="filelabel"><span><b class="icon">f</b> {{ .Name }}</span><span></span></div></a> +{{ end }} +{{ range .Items }} +<a href="{{ .Url }}"><div class="filelabel"><span><b class="icon">f</b> {{ .Name }}</span><span>{{ .Size }}</span></div></a> +{{ end }} +</div> +{{ else }} +{{ if .Error }} +<h1>{{ .Error }}</h1> +{{ else }} +{{ if .Upload }} +<h1>Upload</h1> +<form class="trees" enctype="multipart/form-data" action="{{ .Upload }}" method="post"> + <div class="filelabel"><span>Path:</span><input type="text" name="path" /></div> + <div class="filelabel"><span>File:</span><input type="file" name="myFile" /></div> + <div class="filelabel"><span>Username:</span><input type="text" name="username" /></div> + <div class="filelabel"><span>Password:</span><input type="password" name="password" /></div> + <div class="filelabel"><span>OTP:</span><input type="text" name="otp" /></div> + <div class="filelabel"><span></span><input type="submit" value="Upload" /></div> +</form> +{{ end }} +{{ end }} +{{ end }} +</body> +</html> +{{ end }}`