all repos — flounder @ 0fdda65d16572274c9045ea127794d9be2ccf66b

A small site builder for the Gemini protocol

Improve istext detection

Now reads bytes in addition to mimetype -- allows xml, etc files to be
edited
alex wennerberg alex@alexwennerberg.com
Sun, 27 Dec 2020 21:51:19 -0800
commit

0fdda65d16572274c9045ea127794d9be2ccf66b

parent

de84128d6a9cc08765098317fba37afad12177ef

3 files changed, 38 insertions(+), 4 deletions(-)

jump to
M http.gohttp.go

@@ -13,7 +13,6 @@ "html/template"

"io" "io/ioutil" "log" - "mime" "net/http" "os" "path"

@@ -104,8 +103,8 @@ renderDefaultError(w, http.StatusForbidden)

return } fileName := filepath.Clean(r.URL.Path[len("/edit/"):]) - isText := strings.HasPrefix(mime.TypeByExtension(path.Ext(fileName)), "text") filePath := path.Join(c.FilesDirectory, user.Username, fileName) + isText := isTextFile(filePath) if r.Method == "GET" { err := checkIfValidFile(filePath, nil)
M main.gomain.go

@@ -10,7 +10,6 @@ "io"

"io/ioutil" "log" mathrand "math/rand" - "mime" "os" "path" "path/filepath"

@@ -37,7 +36,7 @@

func fileFromPath(fullPath string) File { info, _ := os.Stat(fullPath) creatorFolder := getCreator(fullPath) - isText := strings.HasPrefix(mime.TypeByExtension(path.Ext(fullPath)), "text") // Not perfect + isText := isTextFile(fullPath) updatedTime := info.ModTime() return File{ Name: getLocalPath(fullPath),
M utils.goutils.go

@@ -4,12 +4,48 @@ import (

"archive/zip" "fmt" "io" + "mime" "os" "path" "path/filepath" "strings" "time" + "unicode/utf8" ) + +// Check if it is a text file, first by checking mimetype, then by reading bytes +// Stolen from https://github.com/golang/tools/blob/master/godoc/util/util.go +func isTextFile(fullPath string) bool { + isText := strings.HasPrefix(mime.TypeByExtension(path.Ext(fullPath)), "text") + if isText { + return true + } + const max = 1024 // at least utf8.UTFMax + s := make([]byte, 1024) + f, err := os.Open(fullPath) + if os.IsNotExist(err) { + return true // for the purposes of editing, we return true + } + n, err := f.Read(s) + s = s[0:n] + if err != nil { + return false + } + f.Close() + + for i, c := range string(s) { + if i+utf8.UTFMax > len(s) { + // last char may be incomplete - ignore + break + } + if c == 0xFFFD || c < ' ' && c != '\n' && c != '\t' && c != '\f' { + fmt.Println("a") + // decoding error or control character - not a text file + return false + } + } + return true +} func isGemini(filename string) bool { extension := path.Ext(filename)