86 lines
1.7 KiB
Go
86 lines
1.7 KiB
Go
// Copyright (C) 2021 Marius Schellenberger
|
|
|
|
package scan
|
|
|
|
import (
|
|
"bytes"
|
|
"net/http"
|
|
"os"
|
|
)
|
|
|
|
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"
|
|
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 "application/octet-stream"
|
|
}
|
|
|
|
func isPDF(path string) bool {
|
|
f, err := os.Open(path)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
defer f.Close()
|
|
buf := make([]byte, maxSniffSize)
|
|
_, err = f.Read(buf)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
return http.DetectContentType(buf) == pdfT
|
|
}
|
|
|
|
func isImage(path string) bool {
|
|
f, err := os.Open(path)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
defer f.Close()
|
|
buf := make([]byte, maxSniffSize)
|
|
_, err = f.Read(buf)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
switch http.DetectContentType(buf) {
|
|
case jpegT, pngT, bmpT, gifT, webpT:
|
|
return true
|
|
default:
|
|
switch extendedContentType(buf) {
|
|
case pnmT, jp2T, tiffT:
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|