summaryrefslogtreecommitdiff
path: root/internal/filetypes.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/filetypes.go')
-rw-r--r--internal/filetypes.go57
1 files changed, 57 insertions, 0 deletions
diff --git a/internal/filetypes.go b/internal/filetypes.go
new file mode 100644
index 0000000..6824ffc
--- /dev/null
+++ b/internal/filetypes.go
@@ -0,0 +1,57 @@
+package internal
+
+import (
+ "mime"
+ "os"
+ "strings"
+ "unicode/utf8"
+)
+
+func MediaType(fpath string) string {
+ if strings.HasSuffix(fpath, ".gmi") {
+ // This may not be present in the listings searched by mime.TypeByExtension,
+ // so provide a dedicated fast path for it here.
+ return "text/gemini"
+ }
+
+ slashIdx := strings.LastIndex(fpath, "/")
+ dotIdx := strings.LastIndex(fpath[slashIdx+1:], ".")
+ if dotIdx == -1 {
+ return "application/octet-stream"
+ }
+ ext := fpath[slashIdx+1+dotIdx:]
+
+ mtype := mime.TypeByExtension(ext)
+ if mtype == "" {
+ if ContentsAreText(fpath) {
+ return "text/plain"
+ }
+ return "application/octet-stream"
+ }
+ return mtype
+}
+
+func ContentsAreText(fpath string) bool {
+ f, err := os.Open(fpath)
+ if err != nil {
+ return false
+ }
+ defer func() { _ = f.Close() }()
+
+ var buf [1024]byte
+ n, err := f.Read(buf[:])
+ if err != nil {
+ return false
+ }
+
+ for i, c := range string(buf[:n]) {
+ if i+utf8.UTFMax > n {
+ // incomplete last char
+ break
+ }
+ if c == 0xFFFD || c < ' ' && c != '\n' && c != '\t' && c != '\f' {
+ return false
+ }
+ }
+ return true
+}