diff --git a/internal/magic/binary.go b/internal/magic/binary.go index 6bb4a939..38ef64f8 100644 --- a/internal/magic/binary.go +++ b/internal/magic/binary.go @@ -142,3 +142,117 @@ func Marc(raw []byte, limit uint32) bool { // Field terminator is present. return bytes.Contains(raw, []byte{0x1E}) } + +func Cbor(raw []byte, limit uint32) bool { + if len(raw) == 0 { + return false + } + var ok bool = true + for ok { + ok = cborHelper(&raw) + } + if len(raw) == 0 { + return true + } else { + return false + } +} + +func cborHelper(raw *[]byte) bool { + if len(*raw) == 0 { + return false + } + t := uint8((*raw)[0] & 0xe0) + ai := (*raw)[0] & 0x1f + uval := uint64(ai) + *raw = (*raw)[1:] + val, ok := cborHead(raw, t, ai, uval) + if ok == false { + return ok + } + switch t { + case 0x40, 0x60: + if val < 0 { + return false + } + if len(*raw) < val { + return false + } + *raw = (*raw)[val:] + case 0x80, 0xa0: + if val < 0 { + return false + } + count := 1 + if t == 0xa0 { + count = 2 + } + for i := 0; i < val*count; i++ { + if ok = cborHelper(raw); ok == false { + return ok + } + } + case 0xc0: + for { + if len(*raw) == 0 { + return false + } + if uint8((*raw)[0]&0xe0) != 0xc0 { + break + } + } + return cborHelper(raw) + default: + return false + } + return true +} + +func cborHead(raw *[]byte, t uint8, ai byte, val uint64) (int, bool) { + dataLen := len(*raw) + if dataLen == 0 { + return 0, false + } + if ai < 24 { + return int(val), true + } + switch ai { + case 24: + if dataLen < 2 { + return 0, false + } + val = uint64((*raw)[0]) + *raw = (*raw)[1:] + if t == 0xe0 && val < 32 { + return 0, false + } + case 25: + if dataLen < 3 { + return 0, false + } + val = uint64(binary.BigEndian.Uint16((*raw)[0 : 2])) + *raw = (*raw)[2:] + case 26: + if dataLen < 5 { + return 0, false + } + val = uint64(binary.BigEndian.Uint32((*raw)[0 : 4])) + *raw = (*raw)[4:] + case 27: + if dataLen < 9 { + return 0, false + } + val = binary.BigEndian.Uint64((*raw)[0 : 8]) + *raw = (*raw)[8:] + case 31: + switch t { + case 0x00, 0x20, 0xc0: + return 0, false + case 0xe0: + return 0, false + } + default: // ai == 28, 29, 30 + return 0, false + } + return int(val), true +} diff --git a/mimetype_test.go b/mimetype_test.go index 1e33ccde..d6e5c088 100644 --- a/mimetype_test.go +++ b/mimetype_test.go @@ -38,6 +38,7 @@ var files = map[string]string{ "bpg.bpg": "image/bpg", "bz2.bz2": "application/x-bzip2", "cab.cab": "application/vnd.ms-cab-compressed", + "cbor": "application/cbor-seq", "class.class": "application/x-java-applet", "crx.crx": "application/x-chrome-extension", "csv.csv": "text/csv", diff --git a/supported_mimes.md b/supported_mimes.md index f67f475b..6b66cd3d 100644 --- a/supported_mimes.md +++ b/supported_mimes.md @@ -1,4 +1,4 @@ -## 165 Supported MIME types +## 166 Supported MIME types This file is automatically generated when running tests. Do not edit manually. Extension | MIME type | Aliases @@ -135,6 +135,7 @@ Extension | MIME type | Aliases **.pat** | image/x-gimp-pat | - **.gbr** | image/x-gimp-gbr | - **.glb** | model/gltf-binary | - +**n/a** | application/cbor-seq | - **.txt** | text/plain | - **.html** | text/html | - **.svg** | image/svg+xml | - diff --git a/testdata/cbor b/testdata/cbor new file mode 100644 index 00000000..57abdc46 --- /dev/null +++ b/testdata/cbor @@ -0,0 +1 @@ +Ąt2013-03-21T20:04:00ZĄt2013-03-21T20:04:00Z \ No newline at end of file diff --git a/tree.go b/tree.go index e5466f13..16732de4 100644 --- a/tree.go +++ b/tree.go @@ -24,7 +24,7 @@ var root = newMIME("application/octet-stream", "", gzip, class, swf, crx, ttf, woff, woff2, otf, eot, wasm, shx, dbf, dcm, rar, djvu, mobi, lit, bpg, sqlite3, dwg, nes, lnk, macho, qcp, icns, heic, heicSeq, heif, heifSeq, hdr, mrc, mdb, accdb, zstd, cab, rpm, xz, lzip, - torrent, cpio, tzif, xcf, pat, gbr, glb, + torrent, cpio, tzif, xcf, pat, gbr, glb, cbor, // Keep text last because it is the slowest check text, ) @@ -247,4 +247,5 @@ var ( gbr = newMIME("image/x-gimp-gbr", ".gbr", magic.Gbr) xfdf = newMIME("application/vnd.adobe.xfdf", ".xfdf", magic.Xfdf) glb = newMIME("model/gltf-binary", ".glb", magic.Glb) + cbor = newMIME("application/cbor-seq", "", magic.Cbor) )