Switch to a more comprehensive mimetype detection library (#231)

This commit is contained in:
Infinoid 2020-08-03 01:16:47 -04:00 committed by GitHub
parent 6ce2bd6b9f
commit 5eb6f32ff0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 56 additions and 21 deletions

View file

@ -7,8 +7,8 @@ import (
"unicode"
"github.com/andreimarcu/linx-server/backends"
"github.com/gabriel-vasile/mimetype"
"github.com/minio/sha256-simd"
"gopkg.in/h2non/filetype.v1"
)
func GenerateMetadata(r io.Reader) (m backends.Metadata, err error) {
@ -21,7 +21,7 @@ func GenerateMetadata(r io.Reader) (m backends.Metadata, err error) {
// Get first 512 bytes for mimetype detection
header := make([]byte, 512)
_, err = teeReader.Read(header)
headerlen, err := teeReader.Read(header)
if err != nil {
return
}
@ -47,17 +47,8 @@ func GenerateMetadata(r io.Reader) (m backends.Metadata, err error) {
// Use the bytes we extracted earlier and attempt to determine the file
// type
kind, err := filetype.Match(header)
if err != nil {
m.Mimetype = "application/octet-stream"
return m, err
} else if kind.MIME.Value != "" {
m.Mimetype = kind.MIME.Value
} else if printable(header) {
m.Mimetype = "text/plain"
} else {
m.Mimetype = "application/octet-stream"
}
kind := mimetype.Detect(header[:headerlen])
m.Mimetype = kind.String()
return
}

View file

@ -1,8 +1,10 @@
package helpers
import (
"bytes"
"strings"
"testing"
"unicode/utf16"
)
func TestGenerateMetadata(t *testing.T) {
@ -17,7 +19,7 @@ func TestGenerateMetadata(t *testing.T) {
t.Fatalf("Sha256sum was %q instead of expected value of %q", m.Sha256sum, expectedSha256sum)
}
expectedMimetype := "text/plain"
expectedMimetype := "text/plain; charset=utf-8"
if m.Mimetype != expectedMimetype {
t.Fatalf("Mimetype was %q instead of expected value of %q", m.Mimetype, expectedMimetype)
}
@ -27,3 +29,45 @@ func TestGenerateMetadata(t *testing.T) {
t.Fatalf("Size was %d instead of expected value of %d", m.Size, expectedSize)
}
}
func TestTextCharsets(t *testing.T) {
// verify that different text encodings are detected and passed through
orig := "This is a text string"
utf16 := utf16.Encode([]rune(orig))
utf16LE := make([]byte, len(utf16)*2+2)
utf16BE := make([]byte, len(utf16)*2+2)
utf8 := []byte(orig)
utf16LE[0] = 0xff
utf16LE[1] = 0xfe
utf16BE[0] = 0xfe
utf16BE[1] = 0xff
for i := 0; i < len(utf16); i++ {
lsb := utf16[i] & 0xff
msb := utf16[i] >> 8
utf16LE[i*2+2] = byte(lsb)
utf16LE[i*2+3] = byte(msb)
utf16BE[i*2+2] = byte(msb)
utf16BE[i*2+3] = byte(lsb)
}
testcases := []struct {
data []byte
extension string
mimetype string
}{
{mimetype: "text/plain; charset=utf-8", data: utf8},
{mimetype: "text/plain; charset=utf-16le", data: utf16LE},
{mimetype: "text/plain; charset=utf-16be", data: utf16BE},
}
for i, testcase := range testcases {
r := bytes.NewReader(testcase.data)
m, err := GenerateMetadata(r)
if err != nil {
t.Fatalf("[%d] unexpected error return %v\n", i, err)
}
if m.Mimetype != testcase.mimetype {
t.Errorf("[%d] Expected mimetype '%s', got mimetype '%s'\n", i, testcase.mimetype, m.Mimetype)
}
}
}