From d908678b16ec8b741cda6c0e54b1df0847380dc3 Mon Sep 17 00:00:00 2001 From: Evgeniy Kosov Date: Sat, 19 Oct 2019 19:42:44 +0200 Subject: [PATCH] Add support for MARC file format Magic number: First five octets: ASCII digits Octets 20-23: 4500 Reference: https://en.wikipedia.org/wiki/MARC_standards https://www.loc.gov/marc/specifications/specrecstruc.html --- internal/matchers/binary.go | 27 +++++++++++++++++++++++++++ mime_test.go | 1 + supported_mimes.md | 3 ++- testdata/mrc.mrc | 1 + tree.go | 3 ++- 5 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 testdata/mrc.mrc diff --git a/internal/matchers/binary.go b/internal/matchers/binary.go index 8a4e4e90..0494277d 100644 --- a/internal/matchers/binary.go +++ b/internal/matchers/binary.go @@ -108,3 +108,30 @@ func Dcm(in []byte) bool { func Nes(in []byte) bool { return bytes.HasPrefix(in, []byte{0x4E, 0x45, 0x53, 0x1A}) } + +// Marc matches a MARC21 (MAchine-Readable Cataloging) file. +func Marc(in []byte) bool { + // File is at least 24 bytes ("leader" field size) + if len(in) < 24 { + return false + } + + // Fixed bytes at offset 20 + if !bytes.Equal(in[20:24], []byte("4500")) { + return false + } + + // First 5 bytes are ASCII digits + for i := 0; i < 5; i++ { + if in[i] < '0' || in[i] > '9' { + return false + } + } + + // Field terminator is present + if !bytes.Contains(in, []byte{0x1E}) { + return false + } + + return true +} diff --git a/mime_test.go b/mime_test.go index 00164f3c..cf37a9ae 100644 --- a/mime_test.go +++ b/mime_test.go @@ -132,6 +132,7 @@ var files = map[string]*node{ "o.o": elfObj, "dcm.dcm": dcm, "mach.o": macho, + "mrc.mrc": mrc, // fonts "woff.woff": woff, diff --git a/supported_mimes.md b/supported_mimes.md index 51d96161..2c58f29e 100644 --- a/supported_mimes.md +++ b/supported_mimes.md @@ -1,4 +1,4 @@ -## 125 Supported MIME types +## 126 Supported MIME types This file is automatically generated when running tests. Do not edit manually. Extension | MIME type @@ -128,3 +128,4 @@ Extension | MIME type **nes** | application/vnd.nintendo.snes.rom **macho** | application/x-mach-binary **qcp** | audio/qcelp +**mrc** | application/marc diff --git a/testdata/mrc.mrc b/testdata/mrc.mrc new file mode 100644 index 00000000..6b997df9 --- /dev/null +++ b/testdata/mrc.mrc @@ -0,0 +1 @@ +00057 2200037 450024500190000001aTest MARC file \ No newline at end of file diff --git a/tree.go b/tree.go index 28d63357..ad6f4613 100644 --- a/tree.go +++ b/tree.go @@ -11,7 +11,7 @@ var root = newNode("application/octet-stream", "", matchers.True, wav, aiff, au, mpeg, quickTime, mqv, mp4, webM, threeGP, threeG2, avi, flv, mkv, asf, aac, voc, aMp4, m4a, txt, gzip, class, swf, crx, woff, woff2, otf, eot, wasm, shx, dbf, dcm, rar, djvu, mobi, lit, bpg, sqlite3, dwg, nes, macho, - qcp, + qcp, mrc, ) // The list of nodes appended to the root node @@ -140,4 +140,5 @@ var ( nes = newNode("application/vnd.nintendo.snes.rom", "nes", matchers.Nes) macho = newNode("application/x-mach-binary", "macho", matchers.MachO) qcp = newNode("audio/qcelp", "qcp", matchers.Qcp) + mrc = newNode("application/marc", "mrc", matchers.Marc) )