build(deps): bump github.com/gabriel-vasile/mimetype (#1775)

Bumps [github.com/gabriel-vasile/mimetype](https://github.com/gabriel-vasile/mimetype) from 1.4.10 to 1.4.11.
- [Release notes](https://github.com/gabriel-vasile/mimetype/releases)
- [Commits](https://github.com/gabriel-vasile/mimetype/compare/v1.4.10...v1.4.11)

---
updated-dependencies:
- dependency-name: github.com/gabriel-vasile/mimetype
  dependency-version: 1.4.11
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This commit is contained in:
dependabot[bot]
2025-11-04 16:02:02 +01:00
committed by GitHub
co-authored by dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
parent fcff855e16
commit 2da203613a
26 changed files with 1138 additions and 677 deletions
+1 -1
View File
@@ -18,7 +18,7 @@ require (
github.com/davidbyttow/govips/v2 v2.16.0
github.com/dhowden/tag v0.0.0-20240417053706-3d75831295e8
github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e
github.com/gabriel-vasile/mimetype v1.4.10
github.com/gabriel-vasile/mimetype v1.4.11
github.com/ggwhite/go-masker v1.1.0
github.com/go-chi/chi/v5 v5.2.3
github.com/go-chi/render v1.0.3
+2 -2
View File
@@ -349,8 +349,8 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/gabriel-vasile/mimetype v1.4.10 h1:zyueNbySn/z8mJZHLt6IPw0KoZsiQNszIpU+bX4+ZK0=
github.com/gabriel-vasile/mimetype v1.4.10/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
github.com/gabriel-vasile/mimetype v1.4.11 h1:AQvxbp830wPhHTqc1u7nzoLT+ZFxGY7emj5DR5DYFik=
github.com/gabriel-vasile/mimetype v1.4.11/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
github.com/gdexlab/go-render v1.0.1 h1:rxqB3vo5s4n1kF0ySmoNeSPRYkEsyHgln4jFIQY7v0U=
github.com/gdexlab/go-render v1.0.1/go.mod h1:wRi5nW2qfjiGj4mPukH4UV0IknS1cHD4VgFTmJX5JzM=
github.com/getkin/kin-openapi v0.13.0/go.mod h1:WGRs2ZMM1Q8LR1QBEwUxC6RJEfaBcD0s+pcEVXFuAjw=
+9
View File
@@ -0,0 +1,9 @@
# Github is obeying this ignore file by default.
# Run this command on local to ignore formatting commits in `git blame`
# git config blame.ignoreRevsFile .git-blame-ignore-revs
# Added a new column to supported_mimes.md
# The supported_mimes.md file was a nice way to find when a file format was
# introduced. However, when I changed to add a new column in the table, the
# whole git blame got poisoned for the file.
eb497f9bc5d31c6eab2929a112051218670137ba
+6 -4
View File
@@ -97,7 +97,9 @@ or from a [file](https://pkg.go.dev/github.com/gabriel-vasile/mimetype#DetectFil
</div>
## Contributing
Contributions are unexpected but welcome. When submitting a PR for detection of
a new file format, please make sure to add a record to the list of testcases
from [mimetype_test.go](mimetype_test.go). For complex files a record can be added
in the [testdata](testdata) directory.
Contributions are never expected but very much welcome.
[mimetype_tests](https://github.com/gabriel-vasile/mimetype_tests/actions/workflows/test.yml)
shows which file formats are most often misidentified and can help prioritise.
When submitting a PR for detection of a new file format, please make sure to
add a record to the list of testcases in [mimetype_test.go](mimetype_test.go).
For complex files a record can be added in the [testdata](testdata) directory.
+28 -24
View File
@@ -2,6 +2,7 @@ package charset
import (
"bytes"
"strings"
"unicode/utf8"
"github.com/gabriel-vasile/mimetype/internal/markup"
@@ -141,27 +142,25 @@ func FromXML(content []byte) string {
return FromPlain(content)
}
func fromXML(s scan.Bytes) string {
xml := []byte("<?XML")
xml := []byte("<?xml")
lxml := len(xml)
for {
if len(s) == 0 {
return ""
}
for scan.ByteIsWS(s.Peek()) {
s.Advance(1)
}
s.TrimLWS()
if len(s) <= lxml {
return ""
}
if !s.Match(xml, scan.IgnoreCase) {
s = s[1:] // safe to slice instead of s.Advance(1) because bounds are checked
continue
i, k := s.Search(xml, 0)
if i == -1 {
return ""
}
aName, aVal, hasMore := "", "", true
s.Advance(i + k)
var aName, aVal []byte
hasMore := true
for hasMore {
aName, aVal, hasMore = markup.GetAnAttribute(&s)
if aName == "encoding" && aVal != "" {
return aVal
if scan.Bytes(aName).Match([]byte("encoding"), 0) != -1 && len(aVal) != 0 {
return string(aVal)
}
}
}
@@ -198,10 +197,10 @@ func fromHTML(s scan.Bytes) string {
return ""
}
// Abort when <body is reached.
if s.Match(body, scan.IgnoreCase) {
if s.Match(body, scan.IgnoreCase) != -1 {
return ""
}
if !s.Match(meta, scan.IgnoreCase) {
if s.Match(meta, scan.IgnoreCase) == -1 {
s = s[1:] // safe to slice instead of s.Advance(1) because bounds are checked
continue
}
@@ -215,14 +214,16 @@ func fromHTML(s scan.Bytes) string {
needPragma := dontKnow
charset := ""
aName, aVal, hasMore := "", "", true
var aNameB, aValB []byte
hasMore := true
for hasMore {
aName, aVal, hasMore = markup.GetAnAttribute(&s)
aNameB, aValB, hasMore = markup.GetAnAttribute(&s)
aName := strings.ToLower(string(aNameB))
if attrList[aName] {
continue
}
// processing step
if len(aName) == 0 && len(aVal) == 0 {
if len(aName) == 0 && len(aValB) == 0 {
if needPragma == dontKnow {
continue
}
@@ -231,15 +232,18 @@ func fromHTML(s scan.Bytes) string {
}
}
attrList[aName] = true
if aName == "http-equiv" && scan.Bytes(aVal).Match([]byte("CONTENT-TYPE"), scan.IgnoreCase) {
gotPragma = true
} else if aName == "content" {
charset = string(extractCharsetFromMeta(scan.Bytes(aVal)))
switch aName {
case "http-equiv":
if scan.Bytes(aValB).Match([]byte("CONTENT-TYPE"), scan.IgnoreCase) != -1 {
gotPragma = true
}
case "content":
charset = string(extractCharsetFromMeta(scan.Bytes(aValB)))
if len(charset) != 0 {
needPragma = doNeedPragma
}
} else if aName == "charset" {
charset = aVal
case "charset":
charset = string(aValB)
needPragma = doNotNeedPragma
}
}
+4 -1
View File
@@ -257,8 +257,11 @@ out:
return 0
}
// openArray is used instead of an inline []byte{'['} to avoid mem alllocs.
var openArray = []byte{'['}
func (p *parserState) consumeArray(b []byte, qs []query, lvl int) (n int) {
p.appendPath([]byte{'['}, qs)
p.appendPath(openArray, qs)
if len(b) == 0 {
return 0
}
+78 -30
View File
@@ -5,43 +5,80 @@ import (
"encoding/binary"
)
var (
// SevenZ matches a 7z archive.
SevenZ = prefix([]byte{0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C})
// Gzip matches gzip files based on http://www.zlib.org/rfc-gzip.html#header-trailer.
Gzip = prefix([]byte{0x1f, 0x8b})
// Fits matches an Flexible Image Transport System file.
Fits = prefix([]byte{
// SevenZ matches a 7z archive.
func SevenZ(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte{0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C})
}
// Gzip matches gzip files based on http://www.zlib.org/rfc-gzip.html#header-trailer.
func Gzip(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte{0x1f, 0x8b})
}
// Fits matches an Flexible Image Transport System file.
func Fits(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte{
0x53, 0x49, 0x4D, 0x50, 0x4C, 0x45, 0x20, 0x20, 0x3D, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x54,
})
// Xar matches an eXtensible ARchive format file.
Xar = prefix([]byte{0x78, 0x61, 0x72, 0x21})
// Bz2 matches a bzip2 file.
Bz2 = prefix([]byte{0x42, 0x5A, 0x68})
// Ar matches an ar (Unix) archive file.
Ar = prefix([]byte{0x21, 0x3C, 0x61, 0x72, 0x63, 0x68, 0x3E})
// Deb matches a Debian package file.
Deb = offset([]byte{
}
// Xar matches an eXtensible ARchive format file.
func Xar(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte{0x78, 0x61, 0x72, 0x21})
}
// Bz2 matches a bzip2 file.
func Bz2(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte{0x42, 0x5A, 0x68})
}
// Ar matches an ar (Unix) archive file.
func Ar(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte{0x21, 0x3C, 0x61, 0x72, 0x63, 0x68, 0x3E})
}
// Deb matches a Debian package file.
func Deb(raw []byte, _ uint32) bool {
return offset(raw, []byte{
0x64, 0x65, 0x62, 0x69, 0x61, 0x6E, 0x2D,
0x62, 0x69, 0x6E, 0x61, 0x72, 0x79,
}, 8)
// Warc matches a Web ARChive file.
Warc = prefix([]byte("WARC/1.0"), []byte("WARC/1.1"))
// Cab matches a Microsoft Cabinet archive file.
Cab = prefix([]byte("MSCF\x00\x00\x00\x00"))
// Xz matches an xz compressed stream based on https://tukaani.org/xz/xz-file-format.txt.
Xz = prefix([]byte{0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00})
// Lzip matches an Lzip compressed file.
Lzip = prefix([]byte{0x4c, 0x5a, 0x49, 0x50})
// RPM matches an RPM or Delta RPM package file.
RPM = prefix([]byte{0xed, 0xab, 0xee, 0xdb}, []byte("drpm"))
// Cpio matches a cpio archive file.
Cpio = prefix([]byte("070707"), []byte("070701"), []byte("070702"))
// RAR matches a RAR archive file.
RAR = prefix([]byte("Rar!\x1A\x07\x00"), []byte("Rar!\x1A\x07\x01\x00"))
)
}
// Warc matches a Web ARChive file.
func Warc(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte("WARC/1.0")) ||
bytes.HasPrefix(raw, []byte("WARC/1.1"))
}
// Cab matches a Microsoft Cabinet archive file.
func Cab(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte("MSCF\x00\x00\x00\x00"))
}
// Xz matches an xz compressed stream based on https://tukaani.org/xz/xz-file-format.txt.
func Xz(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte{0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00})
}
// Lzip matches an Lzip compressed file.
func Lzip(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte{0x4c, 0x5a, 0x49, 0x50})
}
// RPM matches an RPM or Delta RPM package file.
func RPM(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte{0xed, 0xab, 0xee, 0xdb}) ||
bytes.HasPrefix(raw, []byte("drpm"))
}
// RAR matches a RAR archive file.
func RAR(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte("Rar!\x1A\x07\x00")) ||
bytes.HasPrefix(raw, []byte("Rar!\x1A\x07\x01\x00"))
}
// InstallShieldCab matches an InstallShield Cabinet archive file.
func InstallShieldCab(raw []byte, _ uint32) bool {
@@ -78,6 +115,17 @@ func CRX(raw []byte, limit uint32) bool {
return Zip(raw[zipOffset:], limit)
}
// Cpio matches a cpio archive file.
func Cpio(raw []byte, _ uint32) bool {
if len(raw) < 6 {
return false
}
return binary.LittleEndian.Uint16(raw) == 070707 || // binary cpio
bytes.HasPrefix(raw, []byte("070707")) || // portable ASCII cpios
bytes.HasPrefix(raw, []byte("070701")) ||
bytes.HasPrefix(raw, []byte("070702"))
}
// Tar matches a (t)ape (ar)chive file.
// Tar files are divided into 512 bytes records. First record contains a 257
// bytes header padded with NUL.
+44 -20
View File
@@ -5,26 +5,50 @@ import (
"encoding/binary"
)
var (
// Flac matches a Free Lossless Audio Codec file.
Flac = prefix([]byte("\x66\x4C\x61\x43\x00\x00\x00\x22"))
// Midi matches a Musical Instrument Digital Interface file.
Midi = prefix([]byte("\x4D\x54\x68\x64"))
// Ape matches a Monkey's Audio file.
Ape = prefix([]byte("\x4D\x41\x43\x20\x96\x0F\x00\x00\x34\x00\x00\x00\x18\x00\x00\x00\x90\xE3"))
// MusePack matches a Musepack file.
MusePack = prefix([]byte("MPCK"))
// Au matches a Sun Microsystems au file.
Au = prefix([]byte("\x2E\x73\x6E\x64"))
// Amr matches an Adaptive Multi-Rate file.
Amr = prefix([]byte("\x23\x21\x41\x4D\x52"))
// Voc matches a Creative Voice file.
Voc = prefix([]byte("Creative Voice File"))
// M3u matches a Playlist file.
M3u = prefix([]byte("#EXTM3U"))
// AAC matches an Advanced Audio Coding file.
AAC = prefix([]byte{0xFF, 0xF1}, []byte{0xFF, 0xF9})
)
// Flac matches a Free Lossless Audio Codec file.
func Flac(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte("\x66\x4C\x61\x43\x00\x00\x00\x22"))
}
// Midi matches a Musical Instrument Digital Interface file.
func Midi(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte("\x4D\x54\x68\x64"))
}
// Ape matches a Monkey's Audio file.
func Ape(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte("\x4D\x41\x43\x20\x96\x0F\x00\x00\x34\x00\x00\x00\x18\x00\x00\x00\x90\xE3"))
}
// MusePack matches a Musepack file.
func MusePack(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte("MPCK"))
}
// Au matches a Sun Microsystems au file.
func Au(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte("\x2E\x73\x6E\x64"))
}
// Amr matches an Adaptive Multi-Rate file.
func Amr(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte("\x23\x21\x41\x4D\x52"))
}
// Voc matches a Creative Voice file.
func Voc(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte("Creative Voice File"))
}
// M3u matches a Playlist file.
func M3u(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte("#EXTM3U"))
}
// AAC matches an Advanced Audio Coding file.
func AAC(raw []byte, _ uint32) bool {
return len(raw) > 1 && ((raw[0] == 0xFF && raw[1] == 0xF1) || (raw[0] == 0xFF && raw[1] == 0xF9))
}
// Mp3 matches an mp3 file.
func Mp3(raw []byte, limit uint32) bool {
+50 -22
View File
@@ -6,26 +6,52 @@ import (
"encoding/binary"
)
var (
// Lnk matches Microsoft lnk binary format.
Lnk = prefix([]byte{0x4C, 0x00, 0x00, 0x00, 0x01, 0x14, 0x02, 0x00})
// Wasm matches a web assembly File Format file.
Wasm = prefix([]byte{0x00, 0x61, 0x73, 0x6D})
// Exe matches a Windows/DOS executable file.
Exe = prefix([]byte{0x4D, 0x5A})
// Elf matches an Executable and Linkable Format file.
Elf = prefix([]byte{0x7F, 0x45, 0x4C, 0x46})
// Nes matches a Nintendo Entertainment system ROM file.
Nes = prefix([]byte{0x4E, 0x45, 0x53, 0x1A})
// SWF matches an Adobe Flash swf file.
SWF = prefix([]byte("CWS"), []byte("FWS"), []byte("ZWS"))
// Torrent has bencoded text in the beginning.
Torrent = prefix([]byte("d8:announce"))
// PAR1 matches a parquet file.
Par1 = prefix([]byte{0x50, 0x41, 0x52, 0x31})
// CBOR matches a Concise Binary Object Representation https://cbor.io/
CBOR = prefix([]byte{0xD9, 0xD9, 0xF7})
)
// Lnk matches Microsoft lnk binary format.
func Lnk(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte{0x4C, 0x00, 0x00, 0x00, 0x01, 0x14, 0x02, 0x00})
}
// Wasm matches a web assembly File Format file.
func Wasm(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte{0x00, 0x61, 0x73, 0x6D})
}
// Exe matches a Windows/DOS executable file.
func Exe(raw []byte, _ uint32) bool {
return len(raw) > 1 && raw[0] == 0x4D && raw[1] == 0x5A
}
// Elf matches an Executable and Linkable Format file.
func Elf(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte{0x7F, 0x45, 0x4C, 0x46})
}
// Nes matches a Nintendo Entertainment system ROM file.
func Nes(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte{0x4E, 0x45, 0x53, 0x1A})
}
// SWF matches an Adobe Flash swf file.
func SWF(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte("CWS")) ||
bytes.HasPrefix(raw, []byte("FWS")) ||
bytes.HasPrefix(raw, []byte("ZWS"))
}
// Torrent has bencoded text in the beginning.
func Torrent(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte("d8:announce"))
}
// PAR1 matches a parquet file.
func Par1(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte{0x50, 0x41, 0x52, 0x31})
}
// CBOR matches a Concise Binary Object Representation https://cbor.io/
func CBOR(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte{0xD9, 0xD9, 0xF7})
}
// Java bytecode and Mach-O binaries share the same magic number.
// More info here https://github.com/threatstack/libmagic/blob/master/magic/Magdir/cafebabe
@@ -168,8 +194,10 @@ func Marc(raw []byte, limit uint32) bool {
//
// [glTF specification]: https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html
// [IANA glTF entry]: https://www.iana.org/assignments/media-types/model/gltf-binary
var GLB = prefix([]byte("\x67\x6C\x54\x46\x02\x00\x00\x00"),
[]byte("\x67\x6C\x54\x46\x01\x00\x00\x00"))
func GLB(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte("\x67\x6C\x54\x46\x02\x00\x00\x00")) ||
bytes.HasPrefix(raw, []byte("\x67\x6C\x54\x46\x01\x00\x00\x00"))
}
// TzIf matches a Time Zone Information Format (TZif) file.
// See more: https://tools.ietf.org/id/draft-murchison-tzdist-tzif-00.html#rfc.section.3
+16 -8
View File
@@ -1,13 +1,21 @@
package magic
var (
// Sqlite matches an SQLite database file.
Sqlite = prefix([]byte{
import "bytes"
// Sqlite matches an SQLite database file.
func Sqlite(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte{
0x53, 0x51, 0x4c, 0x69, 0x74, 0x65, 0x20, 0x66,
0x6f, 0x72, 0x6d, 0x61, 0x74, 0x20, 0x33, 0x00,
})
// MsAccessAce matches Microsoft Access dababase file.
MsAccessAce = offset([]byte("Standard ACE DB"), 4)
// MsAccessMdb matches legacy Microsoft Access database file (JET, 2003 and earlier).
MsAccessMdb = offset([]byte("Standard Jet DB"), 4)
)
}
// MsAccessAce matches Microsoft Access dababase file.
func MsAccessAce(raw []byte, _ uint32) bool {
return offset(raw, []byte("Standard ACE DB"), 4)
}
// MsAccessMdb matches legacy Microsoft Access database file (JET, 2003 and earlier).
func MsAccessMdb(raw []byte, _ uint32) bool {
return offset(raw, []byte("Standard Jet DB"), 4)
}
+25 -8
View File
@@ -5,14 +5,31 @@ import (
"encoding/binary"
)
var (
// Fdf matches a Forms Data Format file.
Fdf = prefix([]byte("%FDF"))
// Mobi matches a Mobi file.
Mobi = offset([]byte("BOOKMOBI"), 60)
// Lit matches a Microsoft Lit file.
Lit = prefix([]byte("ITOLITLS"))
)
// Pdf matches a Portable Document Format file.
// https://github.com/file/file/blob/11010cc805546a3e35597e67e1129a481aed40e8/magic/Magdir/pdf
func Pdf(raw []byte, _ uint32) bool {
// usual pdf signature
return bytes.HasPrefix(raw, []byte("%PDF-")) ||
// new-line prefixed signature
bytes.HasPrefix(raw, []byte("\012%PDF-")) ||
// UTF-8 BOM prefixed signature
bytes.HasPrefix(raw, []byte("\xef\xbb\xbf%PDF-"))
}
// Fdf matches a Forms Data Format file.
func Fdf(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte("%FDF"))
}
// Mobi matches a Mobi file.
func Mobi(raw []byte, _ uint32) bool {
return offset(raw, []byte("BOOKMOBI"), 60)
}
// Lit matches a Microsoft Lit file.
func Lit(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte("ITOLITLS"))
}
// PDF matches a Portable Document Format file.
// The %PDF- header should be the first thing inside the file but many
+14 -8
View File
@@ -4,14 +4,20 @@ import (
"bytes"
)
var (
// Woff matches a Web Open Font Format file.
Woff = prefix([]byte("wOFF"))
// Woff2 matches a Web Open Font Format version 2 file.
Woff2 = prefix([]byte("wOF2"))
// Otf matches an OpenType font file.
Otf = prefix([]byte{0x4F, 0x54, 0x54, 0x4F, 0x00})
)
// Woff matches a Web Open Font Format file.
func Woff(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte("wOFF"))
}
// Woff2 matches a Web Open Font Format version 2 file.
func Woff2(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte("wOF2"))
}
// Otf matches an OpenType font file.
func Otf(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte{0x4F, 0x54, 0x54, 0x4F, 0x00})
}
// Ttf matches a TrueType font file.
func Ttf(raw []byte, limit uint32) bool {
+70 -33
View File
@@ -4,24 +4,33 @@ import (
"bytes"
)
var (
// AVIF matches an AV1 Image File Format still or animated.
// Wikipedia page seems outdated listing image/avif-sequence for animations.
// https://github.com/AOMediaCodec/av1-avif/issues/59
AVIF = ftyp([]byte("avif"), []byte("avis"))
// ThreeGP matches a 3GPP file.
ThreeGP = ftyp(
// AVIF matches an AV1 Image File Format still or animated.
// Wikipedia page seems outdated listing image/avif-sequence for animations.
// https://github.com/AOMediaCodec/av1-avif/issues/59
func AVIF(raw []byte, _ uint32) bool {
return ftyp(raw, []byte("avif"), []byte("avis"))
}
// ThreeGP matches a 3GPP file.
func ThreeGP(raw []byte, _ uint32) bool {
return ftyp(raw,
[]byte("3gp1"), []byte("3gp2"), []byte("3gp3"), []byte("3gp4"),
[]byte("3gp5"), []byte("3gp6"), []byte("3gp7"), []byte("3gs7"),
[]byte("3ge6"), []byte("3ge7"), []byte("3gg6"),
)
// ThreeG2 matches a 3GPP2 file.
ThreeG2 = ftyp(
}
// ThreeG2 matches a 3GPP2 file.
func ThreeG2(raw []byte, _ uint32) bool {
return ftyp(raw,
[]byte("3g24"), []byte("3g25"), []byte("3g26"), []byte("3g2a"),
[]byte("3g2b"), []byte("3g2c"), []byte("KDDI"),
)
// AMp4 matches an audio MP4 file.
AMp4 = ftyp(
}
// AMp4 matches an audio MP4 file.
func AMp4(raw []byte, _ uint32) bool {
return ftyp(raw,
// audio for Adobe Flash Player 9+
[]byte("F4A "), []byte("F4B "),
// Apple iTunes AAC-LC (.M4A) Audio
@@ -31,33 +40,61 @@ var (
// Nero Digital AAC Audio
[]byte("NDAS"),
)
// Mqv matches a Sony / Mobile QuickTime file.
Mqv = ftyp([]byte("mqt "))
// M4a matches an audio M4A file.
M4a = ftyp([]byte("M4A "))
// M4v matches an Appl4 M4V video file.
M4v = ftyp([]byte("M4V "), []byte("M4VH"), []byte("M4VP"))
// Heic matches a High Efficiency Image Coding (HEIC) file.
Heic = ftyp([]byte("heic"), []byte("heix"))
// HeicSequence matches a High Efficiency Image Coding (HEIC) file sequence.
HeicSequence = ftyp([]byte("hevc"), []byte("hevx"))
// Heif matches a High Efficiency Image File Format (HEIF) file.
Heif = ftyp([]byte("mif1"), []byte("heim"), []byte("heis"), []byte("avic"))
// HeifSequence matches a High Efficiency Image File Format (HEIF) file sequence.
HeifSequence = ftyp([]byte("msf1"), []byte("hevm"), []byte("hevs"), []byte("avcs"))
// Mj2 matches a Motion JPEG 2000 file: https://en.wikipedia.org/wiki/Motion_JPEG_2000.
Mj2 = ftyp([]byte("mj2s"), []byte("mjp2"), []byte("MFSM"), []byte("MGSV"))
// Dvb matches a Digital Video Broadcasting file: https://dvb.org.
// https://cconcolato.github.io/mp4ra/filetype.html
// https://github.com/file/file/blob/512840337ead1076519332d24fefcaa8fac36e06/magic/Magdir/animation#L135-L154
Dvb = ftyp(
}
// Mqv matches a Sony / Mobile QuickTime file.
func Mqv(raw []byte, _ uint32) bool {
return ftyp(raw, []byte("mqt "))
}
// M4a matches an audio M4A file.
func M4a(raw []byte, _ uint32) bool {
return ftyp(raw, []byte("M4A "))
}
// M4v matches an Appl4 M4V video file.
func M4v(raw []byte, _ uint32) bool {
return ftyp(raw, []byte("M4V "), []byte("M4VH"), []byte("M4VP"))
}
// Heic matches a High Efficiency Image Coding (HEIC) file.
func Heic(raw []byte, _ uint32) bool {
return ftyp(raw, []byte("heic"), []byte("heix"))
}
// HeicSequence matches a High Efficiency Image Coding (HEIC) file sequence.
func HeicSequence(raw []byte, _ uint32) bool {
return ftyp(raw, []byte("hevc"), []byte("hevx"))
}
// Heif matches a High Efficiency Image File Format (HEIF) file.
func Heif(raw []byte, _ uint32) bool {
return ftyp(raw, []byte("mif1"), []byte("heim"), []byte("heis"), []byte("avic"))
}
// HeifSequence matches a High Efficiency Image File Format (HEIF) file sequence.
func HeifSequence(raw []byte, _ uint32) bool {
return ftyp(raw, []byte("msf1"), []byte("hevm"), []byte("hevs"), []byte("avcs"))
}
// Mj2 matches a Motion JPEG 2000 file: https://en.wikipedia.org/wiki/Motion_JPEG_2000.
func Mj2(raw []byte, _ uint32) bool {
return ftyp(raw, []byte("mj2s"), []byte("mjp2"), []byte("MFSM"), []byte("MGSV"))
}
// Dvb matches a Digital Video Broadcasting file: https://dvb.org.
// https://cconcolato.github.io/mp4ra/filetype.html
// https://github.com/file/file/blob/512840337ead1076519332d24fefcaa8fac36e06/magic/Magdir/animation#L135-L154
func Dvb(raw []byte, _ uint32) bool {
return ftyp(raw,
[]byte("dby1"), []byte("dsms"), []byte("dts1"), []byte("dts2"),
[]byte("dts3"), []byte("dxo "), []byte("dmb1"), []byte("dmpf"),
[]byte("drc1"), []byte("dv1a"), []byte("dv1b"), []byte("dv2a"),
[]byte("dv2b"), []byte("dv3a"), []byte("dv3b"), []byte("dvr1"),
[]byte("dvt1"), []byte("emsg"))
// TODO: add support for remaining video formats at ftyps.com.
)
}
// TODO: add support for remaining video formats at ftyps.com.
// QuickTime matches a QuickTime File Format file.
// https://www.loc.gov/preservation/digital/formats/fdd/fdd000052.shtml
+135 -57
View File
@@ -2,66 +2,127 @@ package magic
import "bytes"
var (
// Png matches a Portable Network Graphics file.
// https://www.w3.org/TR/PNG/
Png = prefix([]byte{0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A})
// Apng matches an Animated Portable Network Graphics file.
// https://wiki.mozilla.org/APNG_Specification
Apng = offset([]byte("acTL"), 37)
// Jpg matches a Joint Photographic Experts Group file.
Jpg = prefix([]byte{0xFF, 0xD8, 0xFF})
// Jp2 matches a JPEG 2000 Image file (ISO 15444-1).
Jp2 = jpeg2k([]byte{0x6a, 0x70, 0x32, 0x20})
// Jpx matches a JPEG 2000 Image file (ISO 15444-2).
Jpx = jpeg2k([]byte{0x6a, 0x70, 0x78, 0x20})
// Jpm matches a JPEG 2000 Image file (ISO 15444-6).
Jpm = jpeg2k([]byte{0x6a, 0x70, 0x6D, 0x20})
// Gif matches a Graphics Interchange Format file.
Gif = prefix([]byte("GIF87a"), []byte("GIF89a"))
// Bmp matches a bitmap image file.
Bmp = prefix([]byte{0x42, 0x4D})
// Ps matches a PostScript file.
Ps = prefix([]byte("%!PS-Adobe-"))
// Psd matches a Photoshop Document file.
Psd = prefix([]byte("8BPS"))
// Ico matches an ICO file.
Ico = prefix([]byte{0x00, 0x00, 0x01, 0x00}, []byte{0x00, 0x00, 0x02, 0x00})
// Icns matches an ICNS (Apple Icon Image format) file.
Icns = prefix([]byte("icns"))
// Tiff matches a Tagged Image File Format file.
Tiff = prefix([]byte{0x49, 0x49, 0x2A, 0x00}, []byte{0x4D, 0x4D, 0x00, 0x2A})
// Bpg matches a Better Portable Graphics file.
Bpg = prefix([]byte{0x42, 0x50, 0x47, 0xFB})
// Xcf matches GIMP image data.
Xcf = prefix([]byte("gimp xcf"))
// Pat matches GIMP pattern data.
Pat = offset([]byte("GPAT"), 20)
// Gbr matches GIMP brush data.
Gbr = offset([]byte("GIMP"), 20)
// Hdr matches Radiance HDR image.
// https://web.archive.org/web/20060913152809/http://local.wasp.uwa.edu.au/~pbourke/dataformats/pic/
Hdr = prefix([]byte("#?RADIANCE\n"))
// Xpm matches X PixMap image data.
Xpm = prefix([]byte{0x2F, 0x2A, 0x20, 0x58, 0x50, 0x4D, 0x20, 0x2A, 0x2F})
// Jxs matches a JPEG XS coded image file (ISO/IEC 21122-3).
Jxs = prefix([]byte{0x00, 0x00, 0x00, 0x0C, 0x4A, 0x58, 0x53, 0x20, 0x0D, 0x0A, 0x87, 0x0A})
// Jxr matches Microsoft HD JXR photo file.
Jxr = prefix([]byte{0x49, 0x49, 0xBC, 0x01})
)
// Png matches a Portable Network Graphics file.
// https://www.w3.org/TR/PNG/
func Png(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte{0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A})
}
func jpeg2k(sig []byte) Detector {
return func(raw []byte, _ uint32) bool {
if len(raw) < 24 {
return false
}
// Apng matches an Animated Portable Network Graphics file.
// https://wiki.mozilla.org/APNG_Specification
func Apng(raw []byte, _ uint32) bool {
return offset(raw, []byte("acTL"), 37)
}
if !bytes.Equal(raw[4:8], []byte{0x6A, 0x50, 0x20, 0x20}) &&
!bytes.Equal(raw[4:8], []byte{0x6A, 0x50, 0x32, 0x20}) {
return false
}
return bytes.Equal(raw[20:24], sig)
// Jpg matches a Joint Photographic Experts Group file.
func Jpg(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte{0xFF, 0xD8, 0xFF})
}
// Jp2 matches a JPEG 2000 Image file (ISO 15444-1).
func Jp2(raw []byte, _ uint32) bool {
return jpeg2k(raw, []byte{0x6a, 0x70, 0x32, 0x20})
}
// Jpx matches a JPEG 2000 Image file (ISO 15444-2).
func Jpx(raw []byte, _ uint32) bool {
return jpeg2k(raw, []byte{0x6a, 0x70, 0x78, 0x20})
}
// Jpm matches a JPEG 2000 Image file (ISO 15444-6).
func Jpm(raw []byte, _ uint32) bool {
return jpeg2k(raw, []byte{0x6a, 0x70, 0x6D, 0x20})
}
// Gif matches a Graphics Interchange Format file.
func Gif(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte("GIF87a")) ||
bytes.HasPrefix(raw, []byte("GIF89a"))
}
// Bmp matches a bitmap image file.
func Bmp(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte{0x42, 0x4D})
}
// Ps matches a PostScript file.
func Ps(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte("%!PS-Adobe-"))
}
// Psd matches a Photoshop Document file.
func Psd(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte("8BPS"))
}
// Ico matches an ICO file.
func Ico(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte{0x00, 0x00, 0x01, 0x00}) ||
bytes.HasPrefix(raw, []byte{0x00, 0x00, 0x02, 0x00})
}
// Icns matches an ICNS (Apple Icon Image format) file.
func Icns(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte("icns"))
}
// Tiff matches a Tagged Image File Format file.
func Tiff(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte{0x49, 0x49, 0x2A, 0x00}) ||
bytes.HasPrefix(raw, []byte{0x4D, 0x4D, 0x00, 0x2A})
}
// Bpg matches a Better Portable Graphics file.
func Bpg(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte{0x42, 0x50, 0x47, 0xFB})
}
// Xcf matches GIMP image data.
func Xcf(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte("gimp xcf"))
}
// Pat matches GIMP pattern data.
func Pat(raw []byte, _ uint32) bool {
return offset(raw, []byte("GPAT"), 20)
}
// Gbr matches GIMP brush data.
func Gbr(raw []byte, _ uint32) bool {
return offset(raw, []byte("GIMP"), 20)
}
// Hdr matches Radiance HDR image.
// https://web.archive.org/web/20060913152809/http://local.wasp.uwa.edu.au/~pbourke/dataformats/pic/
func Hdr(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte("#?RADIANCE\n"))
}
// Xpm matches X PixMap image data.
func Xpm(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte{0x2F, 0x2A, 0x20, 0x58, 0x50, 0x4D, 0x20, 0x2A, 0x2F})
}
// Jxs matches a JPEG XS coded image file (ISO/IEC 21122-3).
func Jxs(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte{0x00, 0x00, 0x00, 0x0C, 0x4A, 0x58, 0x53, 0x20, 0x0D, 0x0A, 0x87, 0x0A})
}
// Jxr matches Microsoft HD JXR photo file.
func Jxr(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte{0x49, 0x49, 0xBC, 0x01})
}
func jpeg2k(raw []byte, sig []byte) bool {
if len(raw) < 24 {
return false
}
if !bytes.Equal(raw[4:8], []byte{0x6A, 0x50, 0x20, 0x20}) &&
!bytes.Equal(raw[4:8], []byte{0x6A, 0x50, 0x32, 0x20}) {
return false
}
return bytes.Equal(raw[20:24], sig)
}
// Webp matches a WebP file.
@@ -108,3 +169,20 @@ func Jxl(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte{0xFF, 0x0A}) ||
bytes.HasPrefix(raw, []byte("\x00\x00\x00\x0cJXL\x20\x0d\x0a\x87\x0a"))
}
// DXF matches Drawing Exchange Format AutoCAD file.
// There does not seem to be a clear specification and the files in the wild
// differ wildly.
// https://images.autodesk.com/adsk/files/autocad_2012_pdf_dxf-reference_enu.pdf
//
// I collected these signatures by downloading a few dozen files from
// http://cd.textfiles.com/amigaenv/DXF/OBJEKTE/ and
// https://sembiance.com/fileFormatSamples/poly/dxf/ and then
// xxd -l 16 {} | sort | uniq.
// These signatures are only for the ASCII version of DXF. There is a binary version too.
func DXF(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte(" 0\x0ASECTION\x0A")) ||
bytes.HasPrefix(raw, []byte(" 0\x0D\x0ASECTION\x0D\x0A")) ||
bytes.HasPrefix(raw, []byte("0\x0ASECTION\x0A")) ||
bytes.HasPrefix(raw, []byte("0\x0D\x0ASECTION\x0D\x0A"))
}
+53 -103
View File
@@ -3,7 +3,6 @@ package magic
import (
"bytes"
"fmt"
"github.com/gabriel-vasile/mimetype/internal/scan"
)
@@ -22,37 +21,20 @@ type (
}
)
// prefix creates a Detector which returns true if any of the provided signatures
// is the prefix of the raw input.
func prefix(sigs ...[]byte) Detector {
return func(raw []byte, limit uint32) bool {
for _, s := range sigs {
if bytes.HasPrefix(raw, s) {
return true
}
}
return false
}
}
// offset creates a Detector which returns true if the provided signature can be
// offset returns true if the provided signature can be
// found at offset in the raw input.
func offset(sig []byte, offset int) Detector {
return func(raw []byte, limit uint32) bool {
return len(raw) > offset && bytes.HasPrefix(raw[offset:], sig)
}
func offset(raw []byte, sig []byte, offset int) bool {
return len(raw) > offset && bytes.HasPrefix(raw[offset:], sig)
}
// ciPrefix is like prefix but the check is case insensitive.
func ciPrefix(sigs ...[]byte) Detector {
return func(raw []byte, limit uint32) bool {
for _, s := range sigs {
if ciCheck(s, raw) {
return true
}
func ciPrefix(raw []byte, sigs ...[]byte) bool {
for _, s := range sigs {
if ciCheck(s, raw) {
return true
}
return false
}
return false
}
func ciCheck(sig, raw []byte) bool {
if len(raw) < len(sig)+1 {
@@ -72,22 +54,18 @@ func ciCheck(sig, raw []byte) bool {
return true
}
// xml creates a Detector which returns true if any of the provided XML signatures
// matches the raw input.
func xml(sigs ...xmlSig) Detector {
return func(raw []byte, limit uint32) bool {
b := scan.Bytes(raw)
b.TrimLWS()
if len(b) == 0 {
return false
}
for _, s := range sigs {
if xmlCheck(s, b) {
return true
}
}
// xml returns true if any of the provided XML signatures matches the raw input.
func xml(b scan.Bytes, sigs ...xmlSig) bool {
b.TrimLWS()
if len(b) == 0 {
return false
}
for _, s := range sigs {
if xmlCheck(s, b) {
return true
}
}
return false
}
func xmlCheck(sig xmlSig, raw []byte) bool {
raw = raw[:min(len(raw), 512)]
@@ -103,28 +81,24 @@ func xmlCheck(sig xmlSig, raw []byte) bool {
return localNameIndex != -1 && localNameIndex < bytes.Index(raw, sig.xmlns)
}
// markup creates a Detector which returns true is any of the HTML signatures
// matches the raw input.
func markup(sigs ...[]byte) Detector {
return func(raw []byte, limit uint32) bool {
b := scan.Bytes(raw)
if bytes.HasPrefix(b, []byte{0xEF, 0xBB, 0xBF}) {
// We skip the UTF-8 BOM if present to ensure we correctly
// process any leading whitespace. The presence of the BOM
// is taken into account during charset detection in charset.go.
b.Advance(3)
}
b.TrimLWS()
if len(b) == 0 {
return false
}
for _, s := range sigs {
if markupCheck(s, b) {
return true
}
}
// markup returns true is any of the HTML signatures matches the raw input.
func markup(b scan.Bytes, sigs ...[]byte) bool {
if bytes.HasPrefix(b, []byte{0xEF, 0xBB, 0xBF}) {
// We skip the UTF-8 BOM if present to ensure we correctly
// process any leading whitespace. The presence of the BOM
// is taken into account during charset detection in charset.go.
b.Advance(3)
}
b.TrimLWS()
if len(b) == 0 {
return false
}
for _, s := range sigs {
if markupCheck(s, b) {
return true
}
}
return false
}
func markupCheck(sig, raw []byte) bool {
if len(raw) < len(sig)+1 {
@@ -149,29 +123,17 @@ func markupCheck(sig, raw []byte) bool {
return true
}
// ftyp creates a Detector which returns true if any of the FTYP signatures
// matches the raw input.
func ftyp(sigs ...[]byte) Detector {
return func(raw []byte, limit uint32) bool {
if len(raw) < 12 {
return false
}
for _, s := range sigs {
if bytes.Equal(raw[8:12], s) {
return true
}
}
// ftyp returns true if any of the FTYP signatures matches the raw input.
func ftyp(raw []byte, sigs ...[]byte) bool {
if len(raw) < 12 {
return false
}
}
func newXMLSig(localName, xmlns string) xmlSig {
ret := xmlSig{xmlns: []byte(xmlns)}
if localName != "" {
ret.localName = []byte(fmt.Sprintf("<%s", localName))
for _, s := range sigs {
if bytes.Equal(raw[8:12], s) {
return true
}
}
return ret
return false
}
// A valid shebang starts with the "#!" characters,
@@ -184,29 +146,17 @@ func newXMLSig(localName, xmlns string) xmlSig {
// #! /usr/bin/env php
//
// /usr/bin/env is the interpreter, php is the first and only argument.
func shebang(sigs ...[]byte) Detector {
return func(raw []byte, limit uint32) bool {
b := scan.Bytes(raw)
line := b.Line()
for _, s := range sigs {
if shebangCheck(s, line) {
return true
}
func shebang(b scan.Bytes, matchFlags scan.Flags, sigs ...[]byte) bool {
line := b.Line()
if len(line) < 2 || line[0] != '#' || line[1] != '!' {
return false
}
line = line[2:]
line.TrimLWS()
for _, s := range sigs {
if line.Match(s, matchFlags) != -1 {
return true
}
return false
}
}
func shebangCheck(sig []byte, raw scan.Bytes) bool {
if len(raw) < len(sig)+2 {
return false
}
if raw[0] != '#' || raw[1] != '!' {
return false
}
raw.Advance(2) // skip #! we checked above
raw.TrimLWS()
raw.TrimRWS()
return bytes.Equal(raw, sig)
return false
}
+11 -11
View File
@@ -44,17 +44,6 @@ func Ole(raw []byte, limit uint32) bool {
return bytes.HasPrefix(raw, []byte{0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1})
}
// Aaf matches an Advanced Authoring Format file.
// See: https://pyaaf.readthedocs.io/en/latest/about.html
// See: https://en.wikipedia.org/wiki/Advanced_Authoring_Format
func Aaf(raw []byte, limit uint32) bool {
if len(raw) < 31 {
return false
}
return bytes.HasPrefix(raw[8:], []byte{0x41, 0x41, 0x46, 0x42, 0x0D, 0x00, 0x4F, 0x4D}) &&
(raw[30] == 0x09 || raw[30] == 0x0C)
}
// Doc matches a Microsoft Word 97-2003 file.
// See: https://github.com/decalage2/oletools/blob/412ee36ae45e70f42123e835871bac956d958461/oletools/common/clsid.py
func Doc(raw []byte, _ uint32) bool {
@@ -209,3 +198,14 @@ func matchOleClsid(in []byte, clsid []byte) bool {
return bytes.HasPrefix(in[clsidOffset:], clsid)
}
// WPD matches a WordPerfect document.
func WPD(raw []byte, _ uint32) bool {
if len(raw) < 10 {
return false
}
if !bytes.HasPrefix(raw, []byte("\xffWPC")) {
return false
}
return raw[8] == 1 && raw[9] == 10
}
+196 -69
View File
@@ -10,9 +10,9 @@ import (
"github.com/gabriel-vasile/mimetype/internal/scan"
)
var (
// HTML matches a Hypertext Markup Language file.
HTML = markup(
// HTML matches a Hypertext Markup Language file.
func HTML(raw []byte, _ uint32) bool {
return markup(raw,
[]byte("<!DOCTYPE HTML"),
[]byte("<HTML"),
[]byte("<HEAD"),
@@ -31,133 +31,254 @@ var (
[]byte("<P"),
[]byte("<!--"),
)
// XML matches an Extensible Markup Language file.
XML = markup([]byte("<?XML"))
// Owl2 matches an Owl ontology file.
Owl2 = xml(newXMLSig("Ontology", `xmlns="http://www.w3.org/2002/07/owl#"`))
// Rss matches a Rich Site Summary file.
Rss = xml(newXMLSig("rss", ""))
// Atom matches an Atom Syndication Format file.
Atom = xml(newXMLSig("feed", `xmlns="http://www.w3.org/2005/Atom"`))
// Kml matches a Keyhole Markup Language file.
Kml = xml(
newXMLSig("kml", `xmlns="http://www.opengis.net/kml/2.2"`),
newXMLSig("kml", `xmlns="http://earth.google.com/kml/2.0"`),
newXMLSig("kml", `xmlns="http://earth.google.com/kml/2.1"`),
newXMLSig("kml", `xmlns="http://earth.google.com/kml/2.2"`),
}
// XML matches an Extensible Markup Language file.
func XML(raw []byte, _ uint32) bool {
return markup(raw, []byte("<?XML"))
}
// Owl2 matches an Owl ontology file.
func Owl2(raw []byte, _ uint32) bool {
return xml(raw,
xmlSig{[]byte("<Ontology"), []byte(`xmlns="http://www.w3.org/2002/07/owl#"`)},
)
// Xliff matches a XML Localization Interchange File Format file.
Xliff = xml(newXMLSig("xliff", `xmlns="urn:oasis:names:tc:xliff:document:1.2"`))
// Collada matches a COLLAborative Design Activity file.
Collada = xml(newXMLSig("COLLADA", `xmlns="http://www.collada.org/2005/11/COLLADASchema"`))
// Gml matches a Geography Markup Language file.
Gml = xml(
newXMLSig("", `xmlns:gml="http://www.opengis.net/gml"`),
newXMLSig("", `xmlns:gml="http://www.opengis.net/gml/3.2"`),
newXMLSig("", `xmlns:gml="http://www.opengis.net/gml/3.3/exr"`),
}
// Rss matches a Rich Site Summary file.
func Rss(raw []byte, _ uint32) bool {
return xml(raw,
xmlSig{[]byte("<rss"), []byte{}},
)
// Gpx matches a GPS Exchange Format file.
Gpx = xml(newXMLSig("gpx", `xmlns="http://www.topografix.com/GPX/1/1"`))
// Tcx matches a Training Center XML file.
Tcx = xml(newXMLSig("TrainingCenterDatabase", `xmlns="http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2"`))
// X3d matches an Extensible 3D Graphics file.
X3d = xml(newXMLSig("X3D", `xmlns:xsd="http://www.w3.org/2001/XMLSchema-instance"`))
// Amf matches an Additive Manufacturing XML file.
Amf = xml(newXMLSig("amf", ""))
// Threemf matches a 3D Manufacturing Format file.
Threemf = xml(newXMLSig("model", `xmlns="http://schemas.microsoft.com/3dmanufacturing/core/2015/02"`))
// Xfdf matches a XML Forms Data Format file.
Xfdf = xml(newXMLSig("xfdf", `xmlns="http://ns.adobe.com/xfdf/"`))
// VCard matches a Virtual Contact File.
VCard = ciPrefix([]byte("BEGIN:VCARD\n"), []byte("BEGIN:VCARD\r\n"))
// ICalendar matches a iCalendar file.
ICalendar = ciPrefix([]byte("BEGIN:VCALENDAR\n"), []byte("BEGIN:VCALENDAR\r\n"))
phpPageF = ciPrefix(
}
// Atom matches an Atom Syndication Format file.
func Atom(raw []byte, _ uint32) bool {
return xml(raw,
xmlSig{[]byte("<feed"), []byte(`xmlns="http://www.w3.org/2005/Atom"`)},
)
}
// Kml matches a Keyhole Markup Language file.
func Kml(raw []byte, _ uint32) bool {
return xml(raw,
xmlSig{[]byte("<kml"), []byte(`xmlns="http://www.opengis.net/kml/2.2"`)},
xmlSig{[]byte("<kml"), []byte(`xmlns="http://earth.google.com/kml/2.0"`)},
xmlSig{[]byte("<kml"), []byte(`xmlns="http://earth.google.com/kml/2.1"`)},
xmlSig{[]byte("<kml"), []byte(`xmlns="http://earth.google.com/kml/2.2"`)},
)
}
// Xliff matches a XML Localization Interchange File Format file.
func Xliff(raw []byte, _ uint32) bool {
return xml(raw,
xmlSig{[]byte("<xliff"), []byte(`xmlns="urn:oasis:names:tc:xliff:document:1.2"`)},
)
}
// Collada matches a COLLAborative Design Activity file.
func Collada(raw []byte, _ uint32) bool {
return xml(raw,
xmlSig{[]byte("<COLLADA"), []byte(`xmlns="http://www.collada.org/2005/11/COLLADASchema"`)},
)
}
// Gml matches a Geography Markup Language file.
func Gml(raw []byte, _ uint32) bool {
return xml(raw,
xmlSig{[]byte{}, []byte(`xmlns:gml="http://www.opengis.net/gml"`)},
xmlSig{[]byte{}, []byte(`xmlns:gml="http://www.opengis.net/gml/3.2"`)},
xmlSig{[]byte{}, []byte(`xmlns:gml="http://www.opengis.net/gml/3.3/exr"`)},
)
}
// Gpx matches a GPS Exchange Format file.
func Gpx(raw []byte, _ uint32) bool {
return xml(raw,
xmlSig{[]byte("<gpx"), []byte(`xmlns="http://www.topografix.com/GPX/1/1"`)},
)
}
// Tcx matches a Training Center XML file.
func Tcx(raw []byte, _ uint32) bool {
return xml(raw,
xmlSig{[]byte("<TrainingCenterDatabase"), []byte(`xmlns="http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2"`)},
)
}
// X3d matches an Extensible 3D Graphics file.
func X3d(raw []byte, _ uint32) bool {
return xml(raw,
xmlSig{[]byte("<X3D"), []byte(`xmlns:xsd="http://www.w3.org/2001/XMLSchema-instance"`)},
)
}
// Amf matches an Additive Manufacturing XML file.
func Amf(raw []byte, _ uint32) bool {
return xml(raw, xmlSig{[]byte("<amf"), []byte{}})
}
// Threemf matches a 3D Manufacturing Format file.
func Threemf(raw []byte, _ uint32) bool {
return xml(raw,
xmlSig{[]byte("<model"), []byte(`xmlns="http://schemas.microsoft.com/3dmanufacturing/core/2015/02"`)},
)
}
// Xfdf matches a XML Forms Data Format file.
func Xfdf(raw []byte, _ uint32) bool {
return xml(raw, xmlSig{[]byte("<xfdf"), []byte(`xmlns="http://ns.adobe.com/xfdf/"`)})
}
// VCard matches a Virtual Contact File.
func VCard(raw []byte, _ uint32) bool {
return ciPrefix(raw, []byte("BEGIN:VCARD\n"), []byte("BEGIN:VCARD\r\n"))
}
// ICalendar matches a iCalendar file.
func ICalendar(raw []byte, _ uint32) bool {
return ciPrefix(raw, []byte("BEGIN:VCALENDAR\n"), []byte("BEGIN:VCALENDAR\r\n"))
}
func phpPageF(raw []byte, _ uint32) bool {
return ciPrefix(raw,
[]byte("<?PHP"),
[]byte("<?\n"),
[]byte("<?\r"),
[]byte("<? "),
)
phpScriptF = shebang(
}
func phpScriptF(raw []byte, _ uint32) bool {
return shebang(raw,
scan.CompactWS,
[]byte("/usr/local/bin/php"),
[]byte("/usr/bin/php"),
[]byte("/usr/bin/env php"),
[]byte("/usr/bin/env -S php"),
)
// Js matches a Javascript file.
Js = shebang(
}
// Js matches a Javascript file.
func Js(raw []byte, _ uint32) bool {
return shebang(raw,
scan.CompactWS,
[]byte("/bin/node"),
[]byte("/usr/bin/node"),
[]byte("/bin/nodejs"),
[]byte("/usr/bin/nodejs"),
[]byte("/usr/bin/env node"),
[]byte("/usr/bin/env -S node"),
[]byte("/usr/bin/env nodejs"),
[]byte("/usr/bin/env -S nodejs"),
)
// Lua matches a Lua programming language file.
Lua = shebang(
}
// Lua matches a Lua programming language file.
func Lua(raw []byte, _ uint32) bool {
return shebang(raw,
scan.CompactWS|scan.FullWord,
[]byte("/usr/bin/lua"),
[]byte("/usr/local/bin/lua"),
[]byte("/usr/bin/env lua"),
[]byte("/usr/bin/env -S lua"),
)
// Perl matches a Perl programming language file.
Perl = shebang(
}
// Perl matches a Perl programming language file.
func Perl(raw []byte, _ uint32) bool {
return shebang(raw,
scan.CompactWS|scan.FullWord,
[]byte("/usr/bin/perl"),
[]byte("/usr/bin/env perl"),
[]byte("/usr/bin/env -S perl"),
)
// Python matches a Python programming language file.
Python = shebang(
}
// Python matches a Python programming language file.
func Python(raw []byte, _ uint32) bool {
return shebang(raw,
scan.CompactWS,
[]byte("/usr/bin/python"),
[]byte("/usr/local/bin/python"),
[]byte("/usr/bin/env python"),
[]byte("/usr/bin/env -S python"),
[]byte("/usr/bin/python2"),
[]byte("/usr/local/bin/python2"),
[]byte("/usr/bin/env python2"),
[]byte("/usr/bin/env -S python2"),
[]byte("/usr/bin/python3"),
[]byte("/usr/local/bin/python3"),
[]byte("/usr/bin/env python3"),
[]byte("/usr/bin/env -S python3"),
)
// Ruby matches a Ruby programming language file.
Ruby = shebang(
}
// Ruby matches a Ruby programming language file.
func Ruby(raw []byte, _ uint32) bool {
return shebang(raw,
scan.CompactWS,
[]byte("/usr/bin/ruby"),
[]byte("/usr/local/bin/ruby"),
[]byte("/usr/bin/env ruby"),
[]byte("/usr/bin/env -S ruby"),
)
// Tcl matches a Tcl programming language file.
Tcl = shebang(
}
// Tcl matches a Tcl programming language file.
func Tcl(raw []byte, _ uint32) bool {
return shebang(raw,
scan.CompactWS,
[]byte("/usr/bin/tcl"),
[]byte("/usr/local/bin/tcl"),
[]byte("/usr/bin/env tcl"),
[]byte("/usr/bin/env -S tcl"),
[]byte("/usr/bin/tclsh"),
[]byte("/usr/local/bin/tclsh"),
[]byte("/usr/bin/env tclsh"),
[]byte("/usr/bin/env -S tclsh"),
[]byte("/usr/bin/wish"),
[]byte("/usr/local/bin/wish"),
[]byte("/usr/bin/env wish"),
[]byte("/usr/bin/env -S wish"),
)
// Rtf matches a Rich Text Format file.
Rtf = prefix([]byte("{\\rtf"))
// Shell matches a shell script file.
Shell = shebang(
}
// Rtf matches a Rich Text Format file.
func Rtf(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte("{\\rtf"))
}
// Shell matches a shell script file.
func Shell(raw []byte, _ uint32) bool {
return shebang(raw,
scan.CompactWS|scan.FullWord,
[]byte("/bin/sh"),
[]byte("/bin/bash"),
[]byte("/usr/local/bin/bash"),
[]byte("/usr/bin/env bash"),
[]byte("/usr/bin/env -S bash"),
[]byte("/bin/csh"),
[]byte("/usr/local/bin/csh"),
[]byte("/usr/bin/env csh"),
[]byte("/usr/bin/env -S csh"),
[]byte("/bin/dash"),
[]byte("/usr/local/bin/dash"),
[]byte("/usr/bin/env dash"),
[]byte("/usr/bin/env -S dash"),
[]byte("/bin/ksh"),
[]byte("/usr/local/bin/ksh"),
[]byte("/usr/bin/env ksh"),
[]byte("/usr/bin/env -S ksh"),
[]byte("/bin/tcsh"),
[]byte("/usr/local/bin/tcsh"),
[]byte("/usr/bin/env tcsh"),
[]byte("/usr/bin/env -S tcsh"),
[]byte("/bin/zsh"),
[]byte("/usr/local/bin/zsh"),
[]byte("/usr/bin/env zsh"),
[]byte("/usr/bin/env -S zsh"),
)
)
}
// Text matches a plain text file.
//
@@ -183,10 +304,14 @@ func Text(raw []byte, _ uint32) bool {
// XHTML matches an XHTML file. This check depends on the XML check to have passed.
func XHTML(raw []byte, limit uint32) bool {
raw = raw[:min(len(raw), 4096)]
raw = raw[:min(len(raw), 1024)]
b := scan.Bytes(raw)
return b.Search([]byte("<!DOCTYPE HTML"), scan.CompactWS|scan.IgnoreCase) != -1 ||
b.Search([]byte("<HTML XMLNS="), scan.CompactWS|scan.IgnoreCase) != -1
i, _ := b.Search([]byte("<!DOCTYPE HTML"), scan.CompactWS|scan.IgnoreCase)
if i != -1 {
return true
}
i, _ = b.Search([]byte("<HTML XMLNS="), scan.CompactWS|scan.IgnoreCase)
return i != -1
}
// Php matches a PHP: Hypertext Preprocessor file.
@@ -294,11 +419,12 @@ func svgWithoutXMLDeclaration(s scan.Bytes) bool {
return false
}
targetName, targetVal := "xmlns", "http://www.w3.org/2000/svg"
aName, aVal, hasMore := "", "", true
targetName, targetVal := []byte("xmlns"), []byte("http://www.w3.org/2000/svg")
var aName, aVal []byte
hasMore := true
for hasMore {
aName, aVal, hasMore = mkup.GetAnAttribute(&s)
if aName == targetName && aVal == targetVal {
if bytes.Equal(aName, targetName) && bytes.Equal(aVal, targetVal) {
return true
}
if !hasMore {
@@ -325,10 +451,11 @@ func svgWithXMLDeclaration(s scan.Bytes) bool {
// version is a required attribute for XML.
hasVersion := false
aName, hasMore := "", true
var aName []byte
hasMore := true
for hasMore {
aName, _, hasMore = mkup.GetAnAttribute(&s)
if aName == "version" {
if bytes.Equal(aName, []byte("version")) {
hasVersion = true
break
}
+14 -8
View File
@@ -4,17 +4,23 @@ import (
"bytes"
)
var (
// Flv matches a Flash video file.
Flv = prefix([]byte("\x46\x4C\x56\x01"))
// Asf matches an Advanced Systems Format file.
Asf = prefix([]byte{
// Flv matches a Flash video file.
func Flv(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte("\x46\x4C\x56\x01"))
}
// Asf matches an Advanced Systems Format file.
func Asf(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte{
0x30, 0x26, 0xB2, 0x75, 0x8E, 0x66, 0xCF, 0x11,
0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C,
})
// Rmvb matches a RealMedia Variable Bitrate file.
Rmvb = prefix([]byte{0x2E, 0x52, 0x4D, 0x46})
)
}
// Rmvb matches a RealMedia Variable Bitrate file.
func Rmvb(raw []byte, _ uint32) bool {
return bytes.HasPrefix(raw, []byte{0x2E, 0x52, 0x4D, 0x46})
}
// WebM matches a WebM file.
func WebM(raw []byte, limit uint32) bool {
+64 -31
View File
@@ -6,32 +6,65 @@ import (
"github.com/gabriel-vasile/mimetype/internal/scan"
)
var (
// Odt matches an OpenDocument Text file.
Odt = offset([]byte("mimetypeapplication/vnd.oasis.opendocument.text"), 30)
// Ott matches an OpenDocument Text Template file.
Ott = offset([]byte("mimetypeapplication/vnd.oasis.opendocument.text-template"), 30)
// Ods matches an OpenDocument Spreadsheet file.
Ods = offset([]byte("mimetypeapplication/vnd.oasis.opendocument.spreadsheet"), 30)
// Ots matches an OpenDocument Spreadsheet Template file.
Ots = offset([]byte("mimetypeapplication/vnd.oasis.opendocument.spreadsheet-template"), 30)
// Odp matches an OpenDocument Presentation file.
Odp = offset([]byte("mimetypeapplication/vnd.oasis.opendocument.presentation"), 30)
// Otp matches an OpenDocument Presentation Template file.
Otp = offset([]byte("mimetypeapplication/vnd.oasis.opendocument.presentation-template"), 30)
// Odg matches an OpenDocument Drawing file.
Odg = offset([]byte("mimetypeapplication/vnd.oasis.opendocument.graphics"), 30)
// Otg matches an OpenDocument Drawing Template file.
Otg = offset([]byte("mimetypeapplication/vnd.oasis.opendocument.graphics-template"), 30)
// Odf matches an OpenDocument Formula file.
Odf = offset([]byte("mimetypeapplication/vnd.oasis.opendocument.formula"), 30)
// Odc matches an OpenDocument Chart file.
Odc = offset([]byte("mimetypeapplication/vnd.oasis.opendocument.chart"), 30)
// Epub matches an EPUB file.
Epub = offset([]byte("mimetypeapplication/epub+zip"), 30)
// Sxc matches an OpenOffice Spreadsheet file.
Sxc = offset([]byte("mimetypeapplication/vnd.sun.xml.calc"), 30)
)
// Odt matches an OpenDocument Text file.
func Odt(raw []byte, _ uint32) bool {
return offset(raw, []byte("mimetypeapplication/vnd.oasis.opendocument.text"), 30)
}
// Ott matches an OpenDocument Text Template file.
func Ott(raw []byte, _ uint32) bool {
return offset(raw, []byte("mimetypeapplication/vnd.oasis.opendocument.text-template"), 30)
}
// Ods matches an OpenDocument Spreadsheet file.
func Ods(raw []byte, _ uint32) bool {
return offset(raw, []byte("mimetypeapplication/vnd.oasis.opendocument.spreadsheet"), 30)
}
// Ots matches an OpenDocument Spreadsheet Template file.
func Ots(raw []byte, _ uint32) bool {
return offset(raw, []byte("mimetypeapplication/vnd.oasis.opendocument.spreadsheet-template"), 30)
}
// Odp matches an OpenDocument Presentation file.
func Odp(raw []byte, _ uint32) bool {
return offset(raw, []byte("mimetypeapplication/vnd.oasis.opendocument.presentation"), 30)
}
// Otp matches an OpenDocument Presentation Template file.
func Otp(raw []byte, _ uint32) bool {
return offset(raw, []byte("mimetypeapplication/vnd.oasis.opendocument.presentation-template"), 30)
}
// Odg matches an OpenDocument Drawing file.
func Odg(raw []byte, _ uint32) bool {
return offset(raw, []byte("mimetypeapplication/vnd.oasis.opendocument.graphics"), 30)
}
// Otg matches an OpenDocument Drawing Template file.
func Otg(raw []byte, _ uint32) bool {
return offset(raw, []byte("mimetypeapplication/vnd.oasis.opendocument.graphics-template"), 30)
}
// Odf matches an OpenDocument Formula file.
func Odf(raw []byte, _ uint32) bool {
return offset(raw, []byte("mimetypeapplication/vnd.oasis.opendocument.formula"), 30)
}
// Odc matches an OpenDocument Chart file.
func Odc(raw []byte, _ uint32) bool {
return offset(raw, []byte("mimetypeapplication/vnd.oasis.opendocument.chart"), 30)
}
// Epub matches an EPUB file.
func Epub(raw []byte, _ uint32) bool {
return offset(raw, []byte("mimetypeapplication/epub+zip"), 30)
}
// Sxc matches an OpenOffice Spreadsheet file.
func Sxc(raw []byte, _ uint32) bool {
return offset(raw, []byte("mimetypeapplication/vnd.sun.xml.calc"), 30)
}
// Zip matches a zip archive.
func Zip(raw []byte, limit uint32) bool {
@@ -134,11 +167,11 @@ func msoxml(raw scan.Bytes, searchFor zipEntries, stopAfter int) bool {
// If the first is not one of the next usually expected entries,
// then abort this check.
if i == 0 {
if !bytes.Equal(f, []byte("[Content_Types].xml")) &&
!bytes.Equal(f, []byte("_rels/.rels")) &&
!bytes.Equal(f, []byte("docProps")) &&
!bytes.Equal(f, []byte("customXml")) &&
!bytes.Equal(f, []byte("[trash]")) {
if !bytes.Equal(f, []byte("[Content_Types].xml")) && // this is a file
!bytes.HasPrefix(f, []byte("_rels/")) && // these are directories
!bytes.HasPrefix(f, []byte("docProps/")) &&
!bytes.HasPrefix(f, []byte("customXml/")) &&
!bytes.HasPrefix(f, []byte("[trash]/")) {
return false
}
}
+18 -16
View File
@@ -8,46 +8,48 @@ import (
"github.com/gabriel-vasile/mimetype/internal/scan"
)
func GetAnAttribute(s *scan.Bytes) (name, val string, hasMore bool) {
// GetAnAttribute assumes we passed over an SGML tag and extracts first
// attribute and its value.
//
// Initially, this code existed inside charset/charset.go, because it was part of
// implementing the https://html.spec.whatwg.org/multipage/parsing.html#prescan-a-byte-stream-to-determine-its-encoding
// algorithm. But because extracting an attribute from a tag is the same for
// both HTML and XML, then the code was moved here.
func GetAnAttribute(s *scan.Bytes) (name, val []byte, hasMore bool) {
for scan.ByteIsWS(s.Peek()) || s.Peek() == '/' {
s.Advance(1)
}
if s.Peek() == '>' {
return "", "", false
return nil, nil, false
}
// Allocate 10 to avoid resizes.
// Attribute names and values are continuous slices of bytes in input,
// so we could do without allocating and returning slices of input.
nameB := make([]byte, 0, 10)
origS, end := *s, 0
// step 4 and 5
for {
// bap means byte at position in the specification.
bap := s.Pop()
if bap == 0 {
return "", "", false
return nil, nil, false
}
if bap == '=' && len(nameB) > 0 {
if bap == '=' && end > 0 {
val, hasMore := getAValue(s)
return string(nameB), string(val), hasMore
return origS[:end], val, hasMore
} else if scan.ByteIsWS(bap) {
for scan.ByteIsWS(s.Peek()) {
s.Advance(1)
}
if s.Peek() != '=' {
return string(nameB), "", true
return origS[:end], nil, true
}
s.Advance(1)
for scan.ByteIsWS(s.Peek()) {
s.Advance(1)
}
val, hasMore := getAValue(s)
return string(nameB), string(val), hasMore
return origS[:end], val, hasMore
} else if bap == '/' || bap == '>' {
return string(nameB), "", false
} else if bap >= 'A' && bap <= 'Z' {
nameB = append(nameB, bap+0x20)
} else {
nameB = append(nameB, bap)
return origS[:end], nil, false
} else { // for any ASCII, non-ASCII, just advance
end++
}
}
}
+65 -16
View File
@@ -138,46 +138,85 @@ func (b *Bytes) Uint16() (uint16, bool) {
return v, true
}
type Flags int
const (
CompactWS = 1 << iota
// CompactWS will make one whitespace from pattern to match one or more spaces from input.
CompactWS Flags = 1 << iota
// IgnoreCase will match lower case from pattern with lower case from input.
// IgnoreCase will match upper case from pattern with both lower and upper case from input.
// This flag is not really well named,
IgnoreCase
// FullWord ensures the input ends with a full word (it's followed by spaces.)
FullWord
)
// Search for occurences of pattern p inside b at any index.
func (b Bytes) Search(p []byte, flags int) int {
// It returns the index where p was found in b and how many bytes were needed
// for matching the pattern.
func (b Bytes) Search(p []byte, flags Flags) (i int, l int) {
lb, lp := len(b), len(p)
if lp == 0 {
return 0, 0
}
if lb == 0 {
return -1, 0
}
if flags == 0 {
return bytes.Index(b, p)
if i = bytes.Index(b, p); i == -1 {
return -1, 0
} else {
return i, lp
}
}
lb, lp := len(b), len(p)
for i := range b {
if lb-i < lp {
return -1
return -1, 0
}
if b[i:].Match(p, flags) {
return i
if l = b[i:].Match(p, flags); l != -1 {
return i, l
}
}
return 0
return -1, 0
}
// Match pattern p at index 0 of b.
func (b Bytes) Match(p []byte, flags int) bool {
// Match returns how many bytes were needed to match pattern p.
// It returns -1 if p does not match b.
func (b Bytes) Match(p []byte, flags Flags) int {
l := len(b)
if len(p) == 0 {
return 0
}
if l == 0 {
return -1
}
// If no flags, or scanning for full word at the end of pattern then
// do a fast HasPrefix check.
// For other flags it's not possible to use HasPrefix.
if flags == 0 || flags&FullWord > 0 {
if bytes.HasPrefix(b, p) {
b = b[len(p):]
p = p[len(p):]
goto out
}
return -1
}
for len(b) > 0 {
// If we finished all we we're looking for from p.
// If we finished all we were looking for from p.
if len(p) == 0 {
return true
goto out
}
if flags&IgnoreCase > 0 && isUpper(p[0]) {
if upper(b[0]) != p[0] {
return false
return -1
}
b, p = b[1:], p[1:]
} else if flags&CompactWS > 0 && ByteIsWS(p[0]) {
p = p[1:]
if !ByteIsWS(b[0]) {
return false
return -1
}
b = b[1:]
if !ByteIsWS(p[0]) {
@@ -185,12 +224,22 @@ func (b Bytes) Match(p []byte, flags int) bool {
}
} else {
if b[0] != p[0] {
return false
return -1
}
b, p = b[1:], p[1:]
}
}
return true
out:
// If p still has leftover characters, it means it didn't fully match b.
if len(p) > 0 {
return -1
}
if flags&FullWord > 0 {
if len(b) > 0 && !ByteIsWS(b[0]) {
return -1
}
}
return l - len(b)
}
func isUpper(c byte) bool {
+27 -2
View File
@@ -2,6 +2,7 @@ package mimetype
import (
"mime"
"strings"
"github.com/gabriel-vasile/mimetype/internal/charset"
"github.com/gabriel-vasile/mimetype/internal/magic"
@@ -109,7 +110,7 @@ func (m *MIME) match(in []byte, readLimit uint32) *MIME {
// Limit the number of bytes searched for to 1024.
charset = f(in[:min(len(in), 1024)])
}
if m == root {
if m == root || charset == "" {
return m
}
@@ -126,6 +127,27 @@ func (m *MIME) flatten() []*MIME {
return out
}
// hierarchy returns an easy to read list of ancestors for m.
// For example, application/json would return json>txt>root.
func (m *MIME) hierarchy() string {
h := ""
for m := m; m != nil; m = m.Parent() {
e := strings.TrimPrefix(m.Extension(), ".")
if e == "" {
// There are some MIME without extensions. When generating the hierarchy,
// it would be confusing to use empty string as extension.
// Use the subtype instead; ex: application/x-executable -> x-executable.
e = strings.Split(m.String(), "/")[1]
if m.Is("application/octet-stream") {
// for octet-stream use root, because it's short and used in many places
e = "root"
}
}
h += ">" + e
}
return strings.TrimPrefix(h, ">")
}
// clone creates a new MIME with the provided optional MIME parameters.
func (m *MIME) clone(charset string) *MIME {
clonedMIME := m.mime
@@ -155,7 +177,10 @@ func (m *MIME) cloneHierarchy(charset string) *MIME {
}
func (m *MIME) lookup(mime string) *MIME {
for _, n := range append(m.aliases, m.mime) {
if mime == m.mime {
return m
}
for _, n := range m.aliases {
if n == mime {
return m
}
+8 -5
View File
@@ -12,7 +12,7 @@ import (
"sync/atomic"
)
var defaultLimit uint32 = 3072
const defaultLimit uint32 = 3072
// readLimit is the maximum number of bytes from the input used when detecting.
var readLimit uint32 = defaultLimit
@@ -112,15 +112,18 @@ func SetLimit(limit uint32) {
}
// Extend adds detection for other file formats.
// It is equivalent to calling Extend() on the root mime type "application/octet-stream".
// It is equivalent to calling Extend() on the root MIME type "application/octet-stream".
func Extend(detector func(raw []byte, limit uint32) bool, mime, extension string, aliases ...string) {
root.Extend(detector, mime, extension, aliases...)
}
// Lookup finds a MIME object by its string representation.
// The representation can be the main mime type, or any of its aliases.
func Lookup(mime string) *MIME {
// The representation can be the main MIME type, or any of its aliases.
func Lookup(m string) *MIME {
// We store the MIME types without optional params, so
// perform parsing to extract the target MIME type without optional params.
m, _, _ = mime.ParseMediaType(m)
mu.RLock()
defer mu.RUnlock()
return root.lookup(mime)
return root.lookup(m)
}
+195 -194
View File
@@ -1,196 +1,197 @@
## 191 Supported MIME types
## 192 Supported MIME types
This file is automatically generated when running tests. Do not edit manually.
Extension | MIME type | Aliases
--------- | --------- | -------
**n/a** | application/octet-stream | -
**.xpm** | image/x-xpixmap | -
**.7z** | application/x-7z-compressed | -
**.zip** | application/zip | application/x-zip, application/x-zip-compressed
**.docx** | application/vnd.openxmlformats-officedocument.wordprocessingml.document | -
**.pptx** | application/vnd.openxmlformats-officedocument.presentationml.presentation | -
**.xlsx** | application/vnd.openxmlformats-officedocument.spreadsheetml.sheet | -
**.epub** | application/epub+zip | -
**.apk** | application/vnd.android.package-archive | -
**.jar** | application/java-archive | application/jar, application/jar-archive, application/x-java-archive
**.odt** | application/vnd.oasis.opendocument.text | application/x-vnd.oasis.opendocument.text
**.ott** | application/vnd.oasis.opendocument.text-template | application/x-vnd.oasis.opendocument.text-template
**.ods** | application/vnd.oasis.opendocument.spreadsheet | application/x-vnd.oasis.opendocument.spreadsheet
**.ots** | application/vnd.oasis.opendocument.spreadsheet-template | application/x-vnd.oasis.opendocument.spreadsheet-template
**.odp** | application/vnd.oasis.opendocument.presentation | application/x-vnd.oasis.opendocument.presentation
**.otp** | application/vnd.oasis.opendocument.presentation-template | application/x-vnd.oasis.opendocument.presentation-template
**.odg** | application/vnd.oasis.opendocument.graphics | application/x-vnd.oasis.opendocument.graphics
**.otg** | application/vnd.oasis.opendocument.graphics-template | application/x-vnd.oasis.opendocument.graphics-template
**.odf** | application/vnd.oasis.opendocument.formula | application/x-vnd.oasis.opendocument.formula
**.odc** | application/vnd.oasis.opendocument.chart | application/x-vnd.oasis.opendocument.chart
**.sxc** | application/vnd.sun.xml.calc | -
**.kmz** | application/vnd.google-earth.kmz | -
**.vsdx** | application/vnd.ms-visio.drawing.main+xml | -
**.pdf** | application/pdf | application/x-pdf
**.fdf** | application/vnd.fdf | -
**n/a** | application/x-ole-storage | -
**.msi** | application/x-ms-installer | application/x-windows-installer, application/x-msi
**.aaf** | application/octet-stream | -
**.msg** | application/vnd.ms-outlook | -
**.xls** | application/vnd.ms-excel | application/msexcel
**.pub** | application/vnd.ms-publisher | -
**.ppt** | application/vnd.ms-powerpoint | application/mspowerpoint
**.doc** | application/msword | application/vnd.ms-word
**.ps** | application/postscript | -
**.psd** | image/vnd.adobe.photoshop | image/x-psd, application/photoshop
**.p7s** | application/pkcs7-signature | -
**.ogg** | application/ogg | application/x-ogg
**.oga** | audio/ogg | -
**.ogv** | video/ogg | -
**.png** | image/png | -
**.png** | image/vnd.mozilla.apng | -
**.jpg** | image/jpeg | -
**.jxl** | image/jxl | -
**.jp2** | image/jp2 | -
**.jpf** | image/jpx | -
**.jpm** | image/jpm | video/jpm
**.jxs** | image/jxs | -
**.gif** | image/gif | -
**.webp** | image/webp | -
**.exe** | application/vnd.microsoft.portable-executable | -
**n/a** | application/x-elf | -
**n/a** | application/x-object | -
**n/a** | application/x-executable | -
**.so** | application/x-sharedlib | -
**n/a** | application/x-coredump | -
**.a** | application/x-archive | application/x-unix-archive
**.deb** | application/vnd.debian.binary-package | -
**.tar** | application/x-tar | -
**.xar** | application/x-xar | -
**.bz2** | application/x-bzip2 | -
**.fits** | application/fits | image/fits
**.tiff** | image/tiff | -
**.bmp** | image/bmp | image/x-bmp, image/x-ms-bmp
**.123** | application/vnd.lotus-1-2-3 | -
**.ico** | image/x-icon | -
**.mp3** | audio/mpeg | audio/x-mpeg, audio/mp3
**.flac** | audio/flac | -
**.midi** | audio/midi | audio/mid, audio/sp-midi, audio/x-mid, audio/x-midi
**.ape** | audio/ape | -
**.mpc** | audio/musepack | -
**.amr** | audio/amr | audio/amr-nb
**.wav** | audio/wav | audio/x-wav, audio/vnd.wave, audio/wave
**.aiff** | audio/aiff | audio/x-aiff
**.au** | audio/basic | -
**.mpeg** | video/mpeg | -
**.mov** | video/quicktime | -
**.mp4** | video/mp4 | -
**.avif** | image/avif | -
**.3gp** | video/3gpp | video/3gp, audio/3gpp
**.3g2** | video/3gpp2 | video/3g2, audio/3gpp2
**.mp4** | audio/mp4 | audio/x-mp4a
**.mqv** | video/quicktime | -
**.m4a** | audio/x-m4a | -
**.m4v** | video/x-m4v | -
**.heic** | image/heic | -
**.heic** | image/heic-sequence | -
**.heif** | image/heif | -
**.heif** | image/heif-sequence | -
**.mj2** | video/mj2 | -
**.dvb** | video/vnd.dvb.file | -
**.webm** | video/webm | audio/webm
**.avi** | video/x-msvideo | video/avi, video/msvideo
**.flv** | video/x-flv | -
**.mkv** | video/x-matroska | -
**.asf** | video/x-ms-asf | video/asf, video/x-ms-wmv
**.aac** | audio/aac | -
**.voc** | audio/x-unknown | -
**.m3u** | application/vnd.apple.mpegurl | audio/mpegurl
**.rmvb** | application/vnd.rn-realmedia-vbr | -
**.gz** | application/gzip | application/x-gzip, application/x-gunzip, application/gzipped, application/gzip-compressed, application/x-gzip-compressed, gzip/document
**.class** | application/x-java-applet | -
**.swf** | application/x-shockwave-flash | -
**.crx** | application/x-chrome-extension | -
**.ttf** | font/ttf | font/sfnt, application/x-font-ttf, application/font-sfnt
**.woff** | font/woff | -
**.woff2** | font/woff2 | -
**.otf** | font/otf | -
**.ttc** | font/collection | -
**.eot** | application/vnd.ms-fontobject | -
**.wasm** | application/wasm | -
**.shx** | application/vnd.shx | -
**.shp** | application/vnd.shp | -
**.dbf** | application/x-dbf | -
**.dcm** | application/dicom | -
**.rar** | application/x-rar-compressed | application/x-rar
**.djvu** | image/vnd.djvu | -
**.mobi** | application/x-mobipocket-ebook | -
**.lit** | application/x-ms-reader | -
**.bpg** | image/bpg | -
**.cbor** | application/cbor | -
**.sqlite** | application/vnd.sqlite3 | application/x-sqlite3
**.dwg** | image/vnd.dwg | image/x-dwg, application/acad, application/x-acad, application/autocad_dwg, application/dwg, application/x-dwg, application/x-autocad, drawing/dwg
**.nes** | application/vnd.nintendo.snes.rom | -
**.lnk** | application/x-ms-shortcut | -
**.macho** | application/x-mach-binary | -
**.qcp** | audio/qcelp | -
**.icns** | image/x-icns | -
**.hdr** | image/vnd.radiance | -
**.mrc** | application/marc | -
**.mdb** | application/x-msaccess | -
**.accdb** | application/x-msaccess | -
**.zst** | application/zstd | -
**.cab** | application/vnd.ms-cab-compressed | -
**.rpm** | application/x-rpm | -
**.xz** | application/x-xz | -
**.lz** | application/lzip | application/x-lzip
**.torrent** | application/x-bittorrent | -
**.cpio** | application/x-cpio | -
**n/a** | application/tzif | -
**.xcf** | image/x-xcf | -
**.pat** | image/x-gimp-pat | -
**.gbr** | image/x-gimp-gbr | -
**.glb** | model/gltf-binary | -
**.cab** | application/x-installshield | -
**.jxr** | image/jxr | image/vnd.ms-photo
**.parquet** | application/vnd.apache.parquet | application/x-parquet
**.one** | application/onenote | -
**.chm** | application/vnd.ms-htmlhelp | -
**.txt** | text/plain | -
**.svg** | image/svg+xml | -
**.html** | text/html | -
**.xml** | text/xml | application/xml
**.rss** | application/rss+xml | text/rss
**.atom** | application/atom+xml | -
**.x3d** | model/x3d+xml | -
**.kml** | application/vnd.google-earth.kml+xml | -
**.xlf** | application/x-xliff+xml | -
**.dae** | model/vnd.collada+xml | -
**.gml** | application/gml+xml | -
**.gpx** | application/gpx+xml | -
**.tcx** | application/vnd.garmin.tcx+xml | -
**.amf** | application/x-amf | -
**.3mf** | application/vnd.ms-package.3dmanufacturing-3dmodel+xml | -
**.xfdf** | application/vnd.adobe.xfdf | -
**.owl** | application/owl+xml | -
**.html** | application/xhtml+xml | -
**.php** | text/x-php | -
**.js** | text/javascript | application/x-javascript, application/javascript
**.lua** | text/x-lua | -
**.pl** | text/x-perl | -
**.py** | text/x-python | text/x-script.python, application/x-python
**.rb** | text/x-ruby | application/x-ruby
**.json** | application/json | -
**.geojson** | application/geo+json | -
**.har** | application/json | -
**.gltf** | model/gltf+json | -
**.ndjson** | application/x-ndjson | -
**.rtf** | text/rtf | application/rtf
**.srt** | application/x-subrip | application/x-srt, text/x-srt
**.tcl** | text/x-tcl | application/x-tcl
**.csv** | text/csv | -
**.tsv** | text/tab-separated-values | -
**.vcf** | text/vcard | -
**.ics** | text/calendar | -
**.warc** | application/warc | -
**.vtt** | text/vtt | -
**.sh** | text/x-shellscript | text/x-sh, application/x-shellscript, application/x-sh
**.pbm** | image/x-portable-bitmap | -
**.pgm** | image/x-portable-graymap | -
**.ppm** | image/x-portable-pixmap | -
**.pam** | image/x-portable-arbitrarymap | -
Extension | MIME type <br> Aliases | Hierarchy
--------- | ---------------------- | ---------
**n/a** | **application/octet-stream** | root
**.xpm** | **image/x-xpixmap** | xpm>root
**.7z** | **application/x-7z-compressed** | 7z>root
**.zip** | **application/zip** <br> application/x-zip, application/x-zip-compressed | zip>root
**.docx** | **application/vnd.openxmlformats-officedocument.wordprocessingml.document** | docx>zip>root
**.pptx** | **application/vnd.openxmlformats-officedocument.presentationml.presentation** | pptx>zip>root
**.xlsx** | **application/vnd.openxmlformats-officedocument.spreadsheetml.sheet** | xlsx>zip>root
**.epub** | **application/epub+zip** | epub>zip>root
**.apk** | **application/vnd.android.package-archive** | apk>zip>root
**.jar** | **application/java-archive** <br> application/jar, application/jar-archive, application/x-java-archive | jar>zip>root
**.odt** | **application/vnd.oasis.opendocument.text** <br> application/x-vnd.oasis.opendocument.text | odt>zip>root
**.ott** | **application/vnd.oasis.opendocument.text-template** <br> application/x-vnd.oasis.opendocument.text-template | ott>odt>zip>root
**.ods** | **application/vnd.oasis.opendocument.spreadsheet** <br> application/x-vnd.oasis.opendocument.spreadsheet | ods>zip>root
**.ots** | **application/vnd.oasis.opendocument.spreadsheet-template** <br> application/x-vnd.oasis.opendocument.spreadsheet-template | ots>ods>zip>root
**.odp** | **application/vnd.oasis.opendocument.presentation** <br> application/x-vnd.oasis.opendocument.presentation | odp>zip>root
**.otp** | **application/vnd.oasis.opendocument.presentation-template** <br> application/x-vnd.oasis.opendocument.presentation-template | otp>odp>zip>root
**.odg** | **application/vnd.oasis.opendocument.graphics** <br> application/x-vnd.oasis.opendocument.graphics | odg>zip>root
**.otg** | **application/vnd.oasis.opendocument.graphics-template** <br> application/x-vnd.oasis.opendocument.graphics-template | otg>odg>zip>root
**.odf** | **application/vnd.oasis.opendocument.formula** <br> application/x-vnd.oasis.opendocument.formula | odf>zip>root
**.odc** | **application/vnd.oasis.opendocument.chart** <br> application/x-vnd.oasis.opendocument.chart | odc>zip>root
**.sxc** | **application/vnd.sun.xml.calc** | sxc>zip>root
**.kmz** | **application/vnd.google-earth.kmz** | kmz>zip>root
**.vsdx** | **application/vnd.ms-visio.drawing.main+xml** | vsdx>zip>root
**.pdf** | **application/pdf** <br> application/x-pdf | pdf>root
**.fdf** | **application/vnd.fdf** | fdf>root
**n/a** | **application/x-ole-storage** | x-ole-storage>root
**.msi** | **application/x-ms-installer** <br> application/x-windows-installer, application/x-msi | msi>x-ole-storage>root
**.msg** | **application/vnd.ms-outlook** | msg>x-ole-storage>root
**.xls** | **application/vnd.ms-excel** <br> application/msexcel | xls>x-ole-storage>root
**.pub** | **application/vnd.ms-publisher** | pub>x-ole-storage>root
**.ppt** | **application/vnd.ms-powerpoint** <br> application/mspowerpoint | ppt>x-ole-storage>root
**.doc** | **application/msword** <br> application/vnd.ms-word | doc>x-ole-storage>root
**.ps** | **application/postscript** | ps>root
**.psd** | **image/vnd.adobe.photoshop** <br> image/x-psd, application/photoshop | psd>root
**.p7s** | **application/pkcs7-signature** | p7s>root
**.ogg** | **application/ogg** <br> application/x-ogg | ogg>root
**.oga** | **audio/ogg** | oga>ogg>root
**.ogv** | **video/ogg** | ogv>ogg>root
**.png** | **image/png** | png>root
**.png** | **image/vnd.mozilla.apng** | png>png>root
**.jpg** | **image/jpeg** | jpg>root
**.jxl** | **image/jxl** | jxl>root
**.jp2** | **image/jp2** | jp2>root
**.jpf** | **image/jpx** | jpf>root
**.jpm** | **image/jpm** <br> video/jpm | jpm>root
**.jxs** | **image/jxs** | jxs>root
**.gif** | **image/gif** | gif>root
**.webp** | **image/webp** | webp>root
**.exe** | **application/vnd.microsoft.portable-executable** | exe>root
**n/a** | **application/x-elf** | x-elf>root
**n/a** | **application/x-object** | x-object>x-elf>root
**n/a** | **application/x-executable** | x-executable>x-elf>root
**.so** | **application/x-sharedlib** | so>x-elf>root
**n/a** | **application/x-coredump** | x-coredump>x-elf>root
**.a** | **application/x-archive** <br> application/x-unix-archive | a>root
**.deb** | **application/vnd.debian.binary-package** | deb>a>root
**.tar** | **application/x-tar** | tar>root
**.xar** | **application/x-xar** | xar>root
**.bz2** | **application/x-bzip2** | bz2>root
**.fits** | **application/fits** <br> image/fits | fits>root
**.tiff** | **image/tiff** | tiff>root
**.bmp** | **image/bmp** <br> image/x-bmp, image/x-ms-bmp | bmp>root
**.123** | **application/vnd.lotus-1-2-3** | 123>root
**.ico** | **image/x-icon** | ico>root
**.mp3** | **audio/mpeg** <br> audio/x-mpeg, audio/mp3 | mp3>root
**.flac** | **audio/flac** | flac>root
**.midi** | **audio/midi** <br> audio/mid, audio/sp-midi, audio/x-mid, audio/x-midi | midi>root
**.ape** | **audio/ape** | ape>root
**.mpc** | **audio/musepack** | mpc>root
**.amr** | **audio/amr** <br> audio/amr-nb | amr>root
**.wav** | **audio/wav** <br> audio/x-wav, audio/vnd.wave, audio/wave | wav>root
**.aiff** | **audio/aiff** <br> audio/x-aiff | aiff>root
**.au** | **audio/basic** | au>root
**.mpeg** | **video/mpeg** | mpeg>root
**.mov** | **video/quicktime** | mov>root
**.mp4** | **video/mp4** | mp4>root
**.avif** | **image/avif** | avif>mp4>root
**.3gp** | **video/3gpp** <br> video/3gp, audio/3gpp | 3gp>mp4>root
**.3g2** | **video/3gpp2** <br> video/3g2, audio/3gpp2 | 3g2>mp4>root
**.mp4** | **audio/mp4** <br> audio/x-mp4a | mp4>mp4>root
**.mqv** | **video/quicktime** | mqv>mp4>root
**.m4a** | **audio/x-m4a** | m4a>mp4>root
**.m4v** | **video/x-m4v** | m4v>mp4>root
**.heic** | **image/heic** | heic>mp4>root
**.heic** | **image/heic-sequence** | heic>mp4>root
**.heif** | **image/heif** | heif>mp4>root
**.heif** | **image/heif-sequence** | heif>mp4>root
**.mj2** | **video/mj2** | mj2>mp4>root
**.dvb** | **video/vnd.dvb.file** | dvb>mp4>root
**.webm** | **video/webm** <br> audio/webm | webm>root
**.avi** | **video/x-msvideo** <br> video/avi, video/msvideo | avi>root
**.flv** | **video/x-flv** | flv>root
**.mkv** | **video/x-matroska** | mkv>root
**.asf** | **video/x-ms-asf** <br> video/asf, video/x-ms-wmv | asf>root
**.aac** | **audio/aac** | aac>root
**.voc** | **audio/x-unknown** | voc>root
**.m3u** | **application/vnd.apple.mpegurl** <br> audio/mpegurl | m3u>root
**.rmvb** | **application/vnd.rn-realmedia-vbr** | rmvb>root
**.gz** | **application/gzip** <br> application/x-gzip, application/x-gunzip, application/gzipped, application/gzip-compressed, application/x-gzip-compressed, gzip/document | gz>root
**.class** | **application/x-java-applet** | class>root
**.swf** | **application/x-shockwave-flash** | swf>root
**.crx** | **application/x-chrome-extension** | crx>root
**.ttf** | **font/ttf** <br> font/sfnt, application/x-font-ttf, application/font-sfnt | ttf>root
**.woff** | **font/woff** | woff>root
**.woff2** | **font/woff2** | woff2>root
**.otf** | **font/otf** | otf>root
**.ttc** | **font/collection** | ttc>root
**.eot** | **application/vnd.ms-fontobject** | eot>root
**.wasm** | **application/wasm** | wasm>root
**.shx** | **application/vnd.shx** | shx>root
**.shp** | **application/vnd.shp** | shp>shx>root
**.dbf** | **application/x-dbf** | dbf>root
**.dcm** | **application/dicom** | dcm>root
**.rar** | **application/x-rar-compressed** <br> application/x-rar | rar>root
**.djvu** | **image/vnd.djvu** | djvu>root
**.mobi** | **application/x-mobipocket-ebook** | mobi>root
**.lit** | **application/x-ms-reader** | lit>root
**.bpg** | **image/bpg** | bpg>root
**.cbor** | **application/cbor** | cbor>root
**.sqlite** | **application/vnd.sqlite3** <br> application/x-sqlite3 | sqlite>root
**.dwg** | **image/vnd.dwg** <br> image/x-dwg, application/acad, application/x-acad, application/autocad_dwg, application/dwg, application/x-dwg, application/x-autocad, drawing/dwg | dwg>root
**.nes** | **application/vnd.nintendo.snes.rom** | nes>root
**.lnk** | **application/x-ms-shortcut** | lnk>root
**.macho** | **application/x-mach-binary** | macho>root
**.qcp** | **audio/qcelp** | qcp>root
**.icns** | **image/x-icns** | icns>root
**.hdr** | **image/vnd.radiance** | hdr>root
**.mrc** | **application/marc** | mrc>root
**.mdb** | **application/x-msaccess** | mdb>root
**.accdb** | **application/x-msaccess** | accdb>root
**.zst** | **application/zstd** | zst>root
**.cab** | **application/vnd.ms-cab-compressed** | cab>root
**.rpm** | **application/x-rpm** | rpm>root
**.xz** | **application/x-xz** | xz>root
**.lz** | **application/lzip** <br> application/x-lzip | lz>root
**.torrent** | **application/x-bittorrent** | torrent>root
**.cpio** | **application/x-cpio** | cpio>root
**n/a** | **application/tzif** | tzif>root
**.xcf** | **image/x-xcf** | xcf>root
**.pat** | **image/x-gimp-pat** | pat>root
**.gbr** | **image/x-gimp-gbr** | gbr>root
**.glb** | **model/gltf-binary** | glb>root
**.cab** | **application/x-installshield** | cab>root
**.jxr** | **image/jxr** <br> image/vnd.ms-photo | jxr>root
**.parquet** | **application/vnd.apache.parquet** <br> application/x-parquet | parquet>root
**.one** | **application/onenote** | one>root
**.chm** | **application/vnd.ms-htmlhelp** | chm>root
**.wpd** | **application/vnd.wordperfect** | wpd>root
**.dxf** | **image/vnd.dxf** | dxf>root
**.txt** | **text/plain** | txt>root
**.svg** | **image/svg+xml** | svg>txt>root
**.html** | **text/html** | html>txt>root
**.xml** | **text/xml** <br> application/xml | xml>txt>root
**.rss** | **application/rss+xml** <br> text/rss | rss>xml>txt>root
**.atom** | **application/atom+xml** | atom>xml>txt>root
**.x3d** | **model/x3d+xml** | x3d>xml>txt>root
**.kml** | **application/vnd.google-earth.kml+xml** | kml>xml>txt>root
**.xlf** | **application/x-xliff+xml** | xlf>xml>txt>root
**.dae** | **model/vnd.collada+xml** | dae>xml>txt>root
**.gml** | **application/gml+xml** | gml>xml>txt>root
**.gpx** | **application/gpx+xml** | gpx>xml>txt>root
**.tcx** | **application/vnd.garmin.tcx+xml** | tcx>xml>txt>root
**.amf** | **application/x-amf** | amf>xml>txt>root
**.3mf** | **application/vnd.ms-package.3dmanufacturing-3dmodel+xml** | 3mf>xml>txt>root
**.xfdf** | **application/vnd.adobe.xfdf** | xfdf>xml>txt>root
**.owl** | **application/owl+xml** | owl>xml>txt>root
**.html** | **application/xhtml+xml** | html>xml>txt>root
**.php** | **text/x-php** | php>txt>root
**.js** | **text/javascript** <br> application/x-javascript, application/javascript | js>txt>root
**.lua** | **text/x-lua** | lua>txt>root
**.pl** | **text/x-perl** | pl>txt>root
**.py** | **text/x-python** <br> text/x-script.python, application/x-python | py>txt>root
**.rb** | **text/x-ruby** <br> application/x-ruby | rb>txt>root
**.json** | **application/json** | json>txt>root
**.geojson** | **application/geo+json** | geojson>json>txt>root
**.har** | **application/json** | har>json>txt>root
**.gltf** | **model/gltf+json** | gltf>json>txt>root
**.ndjson** | **application/x-ndjson** | ndjson>txt>root
**.rtf** | **text/rtf** <br> application/rtf | rtf>txt>root
**.srt** | **application/x-subrip** <br> application/x-srt, text/x-srt | srt>txt>root
**.tcl** | **text/x-tcl** <br> application/x-tcl | tcl>txt>root
**.csv** | **text/csv** | csv>txt>root
**.tsv** | **text/tab-separated-values** | tsv>txt>root
**.vcf** | **text/vcard** | vcf>txt>root
**.ics** | **text/calendar** | ics>txt>root
**.warc** | **application/warc** | warc>txt>root
**.vtt** | **text/vtt** | vtt>txt>root
**.sh** | **text/x-shellscript** <br> text/x-sh, application/x-shellscript, application/x-sh | sh>txt>root
**.pbm** | **image/x-portable-bitmap** | pbm>txt>root
**.pgm** | **image/x-portable-graymap** | pgm>txt>root
**.ppm** | **image/x-portable-pixmap** | ppm>txt>root
**.pam** | **image/x-portable-arbitrarymap** | pam>txt>root
+4 -3
View File
@@ -24,7 +24,7 @@ var root = newMIME("application/octet-stream", "",
woff2, otf, ttc, eot, wasm, shx, dbf, dcm, rar, djvu, mobi, lit, bpg, cbor,
sqlite3, dwg, nes, lnk, macho, qcp, icns, hdr, mrc, mdb, accdb, zstd, cab,
rpm, xz, lzip, torrent, cpio, tzif, xcf, pat, gbr, glb, cabIS, jxr, parquet,
oneNote, chm,
oneNote, chm, wpd, dxf,
// Keep text last because it is the slowest check.
text,
)
@@ -65,10 +65,9 @@ var (
jar = newMIME("application/java-archive", ".jar", magic.Jar).
alias("application/jar", "application/jar-archive", "application/x-java-archive")
apk = newMIME("application/vnd.android.package-archive", ".apk", magic.APK)
ole = newMIME("application/x-ole-storage", "", magic.Ole, msi, aaf, msg, xls, pub, ppt, doc)
ole = newMIME("application/x-ole-storage", "", magic.Ole, msi, msg, xls, pub, ppt, doc)
msi = newMIME("application/x-ms-installer", ".msi", magic.Msi).
alias("application/x-windows-installer", "application/x-msi")
aaf = newMIME("application/octet-stream", ".aaf", magic.Aaf)
doc = newMIME("application/msword", ".doc", magic.Doc).
alias("application/vnd.ms-word")
ppt = newMIME("application/vnd.ms-powerpoint", ".ppt", magic.Ppt).
@@ -286,4 +285,6 @@ var (
cbor = newMIME("application/cbor", ".cbor", magic.CBOR)
oneNote = newMIME("application/onenote", ".one", magic.One)
chm = newMIME("application/vnd.ms-htmlhelp", ".chm", magic.CHM)
wpd = newMIME("application/vnd.wordperfect", ".wpd", magic.WPD)
dxf = newMIME("image/vnd.dxf", ".dxf", magic.DXF)
)
+1 -1
View File
@@ -444,7 +444,7 @@ github.com/felixge/httpsnoop
## explicit; go 1.17
github.com/fsnotify/fsnotify
github.com/fsnotify/fsnotify/internal
# github.com/gabriel-vasile/mimetype v1.4.10
# github.com/gabriel-vasile/mimetype v1.4.11
## explicit; go 1.21
github.com/gabriel-vasile/mimetype
github.com/gabriel-vasile/mimetype/internal/charset