Compare commits

..

5 Commits

Author SHA1 Message Date
bakonpancakz 0bc8fcb633 bug: proper background colors
never noticed ig
2026-07-18 04:35:56 -07:00
bakonpancakz 2f78a9d80b feat: natural sorting
so like numbers are in order and stuff idk black magic
2026-07-18 04:22:03 -07:00
bakonpancakz 75140f716d bug: trailing slash issue
manually writing a dir caused path traversal issues in the html so we force a trailing slash to prevent this
2026-07-18 04:03:57 -07:00
bakonpancakz 5ae998f383 bug: actually hide dotfiles
disappointed in myself
2026-07-18 03:37:20 -07:00
bakonpancakz 26e2a4e0e3 feature: Hide Dotfiles
And Dotdirs if thats a thing. Enabled by default, use envvars to disable this feature.
2026-06-18 20:51:42 -07:00
5 changed files with 74 additions and 5 deletions
+4 -3
View File
@@ -10,9 +10,10 @@ A Miku flavored file browser inspired by THE FLAVOR FOLEY FILES (https://flavorf
Configure the service using environment variables: Configure the service using environment variables:
| Name | Default | Description | Name | Default | Description
| HTTP_ADDRESS | 127.0.0.1:9000 | Address and Port to use for requests | HTTP_ADDRESS | 127.0.0.1:9000 | Address and Port to use for requests
| HTTP_DIRECTORY | <empty> | Starting directory to list and serve files from | HTTP_DIRECTORY | <empty> | Starting directory to list and serve files from
| HTTP_SHOW_DOTFILES | <empty> | Set this variable to list directories and files prefixed with a dot (e.g. .DS_Store)
[ Credits ] [ Credits ]
+66 -2
View File
@@ -2,6 +2,7 @@ package main
import ( import (
"bytes" "bytes"
"cmp"
"embed" "embed"
"fmt" "fmt"
"io" "io"
@@ -16,6 +17,8 @@ import (
"strings" "strings"
"text/template" "text/template"
"time" "time"
"unicode"
"unicode/utf8"
) )
var ( var (
@@ -23,6 +26,7 @@ var (
privateDirectory embed.FS privateDirectory embed.FS
serveHash = fmt.Sprintf("%X", time.Now().Unix()) serveHash = fmt.Sprintf("%X", time.Now().Unix())
serveDirectory = os.Getenv("HTTP_DIRECTORY") serveDirectory = os.Getenv("HTTP_DIRECTORY")
serveDotfiles = os.Getenv("HTTP_SHOW_DOTFILES")
serveAddress = os.Getenv("HTTP_ADDRESS") serveAddress = os.Getenv("HTTP_ADDRESS")
tmpl = template.Must( tmpl = template.Must(
template. template.
@@ -113,6 +117,54 @@ func getEntryIcon(name string, isDir bool) string {
} }
} }
func parseNumber(s string) (num int, chars int) {
for chars < len(s) && s[chars] >= '0' && s[chars] <= '9' {
num = num*10 + int(s[chars]-'0')
chars++
}
return
}
func naturalCompare(a, b string) int {
for len(a) > 0 && len(b) > 0 {
if unicode.IsDigit(rune(a[0])) && unicode.IsDigit(rune(b[0])) {
aValue, aSize := parseNumber(a)
bValue, bSize := parseNumber(b)
if aValue != bValue {
if aValue < bValue {
return -1
}
return 1
}
a = a[aSize:]
b = b[bSize:]
continue
}
aRune, aSize := utf8.DecodeRuneInString(a)
bRune, bSize := utf8.DecodeRuneInString(b)
aRuneLower := unicode.ToLower(aRune)
bRuneLower := unicode.ToLower(bRune)
if aRuneLower != bRuneLower {
if aRuneLower < bRuneLower {
return -1
}
return 1
}
a = a[aSize:]
b = b[bSize:]
}
return cmp.Compare(len(a), len(b))
}
func init() { func init() {
if serveAddress == "" { if serveAddress == "" {
serveAddress = "127.0.0.1:8080" serveAddress = "127.0.0.1:8080"
@@ -151,6 +203,13 @@ func main() {
return return
} }
// Append trailing slash to directories so rendered HTML has proper paths
if filestat.IsDir() && !strings.HasSuffix(r.URL.Path, "/") {
r.URL.Path += "/"
http.Redirect(w, r, r.URL.String(), http.StatusMovedPermanently)
return
}
// Use Browser Cache (if possible) // Use Browser Cache (if possible)
modtime := filestat.ModTime().UTC() modtime := filestat.ModTime().UTC()
modhash := fmt.Sprint(modtime.Unix()) modhash := fmt.Sprint(modtime.Unix())
@@ -194,6 +253,11 @@ func main() {
continue continue
} }
// Ignore Dotfiles
if serveDotfiles == "" && strings.HasPrefix(entry.Name(), ".") {
continue
}
// Check Symbolic Link // Check Symbolic Link
isDir := entry.IsDir() isDir := entry.IsDir()
if entry.Type()&os.ModeSymlink != 0 { if entry.Type()&os.ModeSymlink != 0 {
@@ -227,14 +291,14 @@ func main() {
// Use // Use
if sortOrder == "modified" { if sortOrder == "modified" {
if a.ModTime.Equal(b.ModTime) { if a.ModTime.Equal(b.ModTime) {
return strings.Compare(a.Name, b.Name) return naturalCompare(a.Name, b.Name)
} }
if a.ModTime.After(b.ModTime) { if a.ModTime.After(b.ModTime) {
return -1 return -1
} }
return 1 return 1
} }
return strings.Compare(a.Name, b.Name) return naturalCompare(a.Name, b.Name)
}) })
// Directory Listing // Directory Listing
Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 12 KiB

+1
View File
@@ -2,6 +2,7 @@
body { body {
margin: 0; margin: 0;
background-color: #f0faf9;
} }
::-webkit-scrollbar { ::-webkit-scrollbar {
+3
View File
@@ -0,0 +1,3 @@
I'M CALLING OUT YOUR NAME RECEIVING NO REPLY
[ REFLECTED OFF THE SIDE OF THE SKYLINE ]
CALLING OUT IN VAIN, LIKE YOU WOULD EVEN TRY