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
M
http.go
→
http.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.go
→
main.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.go
→
utils.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)