91 lines
1.7 KiB
Go
91 lines
1.7 KiB
Go
// Copyright (C) 2021 Marius Schellenberger
|
|
|
|
package scan
|
|
|
|
import (
|
|
"bytes"
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
const (
|
|
pdfT = "application/pdf"
|
|
jpegT = "image/jpeg"
|
|
pngT = "image/png"
|
|
bmpT = "image/bmp"
|
|
gifT = "image/gif"
|
|
webpT = "image/webp"
|
|
pnmT = "image/x-portable-anymap"
|
|
jp2T = "image/jp2"
|
|
tiffT = "image/tiff"
|
|
textT = "text/"
|
|
rawT = "application/octet-stream"
|
|
maxSniffSize = 512
|
|
)
|
|
|
|
type extendedSig struct {
|
|
sig []byte
|
|
ct string
|
|
}
|
|
|
|
var extendedSigs = []extendedSig{
|
|
{[]byte("P1\x0A"), pnmT},
|
|
{[]byte("P2\x0A"), pnmT},
|
|
{[]byte("P3\x0A"), pnmT},
|
|
{[]byte("P4\x0A"), pnmT},
|
|
{[]byte("P5\x0A"), pnmT},
|
|
{[]byte("P6\x0A"), pnmT},
|
|
{[]byte("P7\x0A"), pnmT},
|
|
{[]byte("\x00\x00\x00\x0C\x6A\x50\x20\x20\x0D\x0A\x87\x0A\x00\x00\x00\x14\x66\x74\x79\x70\x6A\x70\x32"), jp2T},
|
|
{[]byte("\x4d\x4d\x00\x2a"), tiffT},
|
|
{[]byte("\x49\x49\x2a\x00"), tiffT},
|
|
}
|
|
|
|
func extendedContentType(buf []byte) string {
|
|
for _, sig := range extendedSigs {
|
|
if bytes.HasPrefix(buf, sig.sig) {
|
|
return sig.ct
|
|
}
|
|
}
|
|
return rawT
|
|
}
|
|
|
|
func isImage(ct string, buf []byte) bool {
|
|
switch ct {
|
|
case jpegT, pngT, bmpT, gifT, webpT:
|
|
return true
|
|
default:
|
|
switch extendedContentType(buf) {
|
|
case pnmT, jp2T, tiffT:
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
type filetype struct {
|
|
text bool
|
|
pdf bool
|
|
image bool
|
|
}
|
|
|
|
func (s *Scanner) newFileType(path string) (ft *filetype) {
|
|
ft = new(filetype)
|
|
f, err := os.Open(path)
|
|
if err != nil {
|
|
return
|
|
}
|
|
defer f.Close()
|
|
buf := make([]byte, maxSniffSize)
|
|
n, err := f.Read(buf)
|
|
if err != nil {
|
|
return
|
|
}
|
|
buf = buf[:n]
|
|
ct := http.DetectContentType(buf)
|
|
ft.text = strings.HasPrefix(ct, textT)
|
|
ft.pdf = ct == pdfT
|
|
ft.image = isImage(ct, buf)
|
|
return
|
|
}
|