From 7dfea92749c509baa644d6ad933e9b95a07cfa0a Mon Sep 17 00:00:00 2001 From: mappu Date: Sat, 9 Jun 2018 12:18:00 +1200 Subject: [PATCH] vendor: track h2non/filetype (MIT license) --- Gopkg.lock | 8 +- Gopkg.toml | 4 + .../gopkg.in/h2non/filetype.v1/.editorconfig | 12 + vendor/gopkg.in/h2non/filetype.v1/.gitignore | 2 + vendor/gopkg.in/h2non/filetype.v1/.travis.yml | 17 ++ vendor/gopkg.in/h2non/filetype.v1/History.md | 47 +++ vendor/gopkg.in/h2non/filetype.v1/LICENSE | 24 ++ vendor/gopkg.in/h2non/filetype.v1/README.md | 275 ++++++++++++++++++ vendor/gopkg.in/h2non/filetype.v1/filetype.go | 87 ++++++ .../h2non/filetype.v1/filetype_test.go | 123 ++++++++ vendor/gopkg.in/h2non/filetype.v1/kind.go | 69 +++++ .../gopkg.in/h2non/filetype.v1/kind_test.go | 40 +++ vendor/gopkg.in/h2non/filetype.v1/match.go | 86 ++++++ .../gopkg.in/h2non/filetype.v1/match_test.go | 187 ++++++++++++ .../h2non/filetype.v1/matchers/archive.go | 217 ++++++++++++++ .../h2non/filetype.v1/matchers/audio.go | 67 +++++ .../h2non/filetype.v1/matchers/document.go | 66 +++++ .../h2non/filetype.v1/matchers/font.go | 45 +++ .../h2non/filetype.v1/matchers/image.go | 89 ++++++ .../h2non/filetype.v1/matchers/matchers.go | 44 +++ .../h2non/filetype.v1/matchers/video.go | 120 ++++++++ .../h2non/filetype.v1/types/defaults.go | 4 + .../gopkg.in/h2non/filetype.v1/types/mime.go | 14 + .../gopkg.in/h2non/filetype.v1/types/split.go | 11 + .../h2non/filetype.v1/types/split_test.go | 27 ++ .../gopkg.in/h2non/filetype.v1/types/type.go | 16 + .../gopkg.in/h2non/filetype.v1/types/types.go | 18 ++ vendor/gopkg.in/h2non/filetype.v1/version.go | 4 + 28 files changed, 1722 insertions(+), 1 deletion(-) create mode 100644 vendor/gopkg.in/h2non/filetype.v1/.editorconfig create mode 100644 vendor/gopkg.in/h2non/filetype.v1/.gitignore create mode 100644 vendor/gopkg.in/h2non/filetype.v1/.travis.yml create mode 100644 vendor/gopkg.in/h2non/filetype.v1/History.md create mode 100644 vendor/gopkg.in/h2non/filetype.v1/LICENSE create mode 100644 vendor/gopkg.in/h2non/filetype.v1/README.md create mode 100644 vendor/gopkg.in/h2non/filetype.v1/filetype.go create mode 100644 vendor/gopkg.in/h2non/filetype.v1/filetype_test.go create mode 100644 vendor/gopkg.in/h2non/filetype.v1/kind.go create mode 100644 vendor/gopkg.in/h2non/filetype.v1/kind_test.go create mode 100644 vendor/gopkg.in/h2non/filetype.v1/match.go create mode 100644 vendor/gopkg.in/h2non/filetype.v1/match_test.go create mode 100644 vendor/gopkg.in/h2non/filetype.v1/matchers/archive.go create mode 100644 vendor/gopkg.in/h2non/filetype.v1/matchers/audio.go create mode 100644 vendor/gopkg.in/h2non/filetype.v1/matchers/document.go create mode 100644 vendor/gopkg.in/h2non/filetype.v1/matchers/font.go create mode 100644 vendor/gopkg.in/h2non/filetype.v1/matchers/image.go create mode 100644 vendor/gopkg.in/h2non/filetype.v1/matchers/matchers.go create mode 100644 vendor/gopkg.in/h2non/filetype.v1/matchers/video.go create mode 100644 vendor/gopkg.in/h2non/filetype.v1/types/defaults.go create mode 100644 vendor/gopkg.in/h2non/filetype.v1/types/mime.go create mode 100644 vendor/gopkg.in/h2non/filetype.v1/types/split.go create mode 100644 vendor/gopkg.in/h2non/filetype.v1/types/split_test.go create mode 100644 vendor/gopkg.in/h2non/filetype.v1/types/type.go create mode 100644 vendor/gopkg.in/h2non/filetype.v1/types/types.go create mode 100644 vendor/gopkg.in/h2non/filetype.v1/version.go diff --git a/Gopkg.lock b/Gopkg.lock index 949c9f9..1d8917d 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -25,9 +25,15 @@ revision = "a90a01d73ae432e2611d178c18367fbaa13e0154" version = "v1.0.1" +[[projects]] + name = "gopkg.in/h2non/filetype.v1" + packages = [".","matchers","types"] + revision = "cc14fdc9ca0e4c2bafad7458f6ff79fd3947cfbb" + version = "v1.0.5" + [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "f42caa97e6521c92eb941027b3691e537030b092fbbb8712c220c6edd92e16b3" + inputs-digest = "7607d6cc9aef0b2e3b855ecf48dbbfc6efa20a4e8efee3e9cbd5e8d1e1f0c68a" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index d4c612d..cfd1da1 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -28,3 +28,7 @@ [[constraint]] name = "code.ivysaur.me/libnmdc" branch = "master" + +[[constraint]] + name = "gopkg.in/h2non/filetype.v1" + version = "1.0.5" diff --git a/vendor/gopkg.in/h2non/filetype.v1/.editorconfig b/vendor/gopkg.in/h2non/filetype.v1/.editorconfig new file mode 100644 index 0000000..000dc0a --- /dev/null +++ b/vendor/gopkg.in/h2non/filetype.v1/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +indent_style = tabs +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false diff --git a/vendor/gopkg.in/h2non/filetype.v1/.gitignore b/vendor/gopkg.in/h2non/filetype.v1/.gitignore new file mode 100644 index 0000000..6fefe6c --- /dev/null +++ b/vendor/gopkg.in/h2non/filetype.v1/.gitignore @@ -0,0 +1,2 @@ +bin +.DS_Store diff --git a/vendor/gopkg.in/h2non/filetype.v1/.travis.yml b/vendor/gopkg.in/h2non/filetype.v1/.travis.yml new file mode 100644 index 0000000..739e14e --- /dev/null +++ b/vendor/gopkg.in/h2non/filetype.v1/.travis.yml @@ -0,0 +1,17 @@ +language: go + +go: + - 1.9 + - 1.8 + - 1.7 + - 1.6 + - tip + +before_install: + - go get -u -v github.com/golang/lint/golint + +script: + - diff -u <(echo -n) <(gofmt -s -d ./) + - diff -u <(echo -n) <(go vet ./...) + - diff -u <(echo -n) <(golint) + - go test -v -race ./... diff --git a/vendor/gopkg.in/h2non/filetype.v1/History.md b/vendor/gopkg.in/h2non/filetype.v1/History.md new file mode 100644 index 0000000..a33f4e7 --- /dev/null +++ b/vendor/gopkg.in/h2non/filetype.v1/History.md @@ -0,0 +1,47 @@ + +v1.0.5 / 2017-12-12 +=================== + + * Merge pull request #30 from RangelReale/fix_mp4 + * Fix duplicated item in mp4 fix + * Fix MP4 matcher, with information from http://www.file-recovery.com/mp4-signature-format.htm + * Merge pull request #28 from ikovic/master + * Updated file header example. + +v1.0.4 / 2017-11-29 +=================== + + * fix: tests and document types matchers + * refactor(docs): remove codesponsor + * Merge pull request #26 from bienkma/master + * Add support check file type: .doc, .docx, .pptx, .ppt, .xls, .xlsx + * feat(docs): add code sponsor banner + * feat(travis): add go 1.9 + * Merge pull request #24 from strazzere/patch-1 + * Fix typo in unknown + +v1.0.3 / 2017-08-03 +=================== + + * Merge pull request #21 from elemeta/master + * Add Elf file as supported matcher archive type + +v1.0.2 / 2017-07-26 +=================== + + * Merge pull request #20 from marshyski/master + * Added RedHat RPM as supported matcher archive type + * Merge pull request #19 from nlamirault/patch-1 + * Fix typo in documentation + +v1.0.1 / 2017-02-24 +=================== + + * Merge pull request #18 from Impyy/enable-webm + * Enable the webm matcher + * feat(docs): add Go version badge + +1.0.0 / 2016-12-11 +================== + +- Initial stable version (v1.0.0). diff --git a/vendor/gopkg.in/h2non/filetype.v1/LICENSE b/vendor/gopkg.in/h2non/filetype.v1/LICENSE new file mode 100644 index 0000000..30ede59 --- /dev/null +++ b/vendor/gopkg.in/h2non/filetype.v1/LICENSE @@ -0,0 +1,24 @@ +The MIT License + +Copyright (c) Tomas Aparicio + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/gopkg.in/h2non/filetype.v1/README.md b/vendor/gopkg.in/h2non/filetype.v1/README.md new file mode 100644 index 0000000..8d45324 --- /dev/null +++ b/vendor/gopkg.in/h2non/filetype.v1/README.md @@ -0,0 +1,275 @@ +# filetype [![Build Status](https://travis-ci.org/h2non/filetype.png)](https://travis-ci.org/h2non/filetype) [![GoDoc](https://godoc.org/github.com/h2non/filetype?status.svg)](https://godoc.org/github.com/h2non/filetype) [![Go Report Card](http://goreportcard.com/badge/h2non/filetype)](http://goreportcard.com/report/h2non/filetype) [![Go Version](https://img.shields.io/badge/go-v1.0+-green.svg?style=flat)](https://github.com/h2non/gentleman) + +Small and dependency free [Go](https://golang.org) package to infer file and MIME type checking the [magic numbers](https://en.wikipedia.org/wiki/Magic_number_(programming)#Magic_numbers_in_files) signature. + +For SVG file type checking, see [go-is-svg](https://github.com/h2non/go-is-svg) package. + +## Features + +- Supports a [wide range](#supported-types) of file types +- Provides file extension and proper MIME type +- File discovery by extension or MIME type +- File discovery by class (image, video, audio...) +- Provides a bunch of helpers and file matching shortcuts +- [Pluggable](#add-additional-file-type-matchers): add custom new types and matchers +- Simple and semantic API +- [Blazing fast](#benchmarks), even processing large files +- Only first 261 bytes representing the max file header is required, so you can just [pass a slice](#file-header) +- Dependency free (just Go code, no C compilation needed) +- Cross-platform file recognition + +## Installation + +```bash +go get gopkg.in/h2non/filetype.v1 +``` + +## API + +See [Godoc](https://godoc.org/github.com/h2non/filetype) reference. + +### Subpackages + +- [`gopkg.in/h2non/filetype.v1/types`](https://godoc.org/github.com/h2non/filetype/types) +- [`gopkg.in/h2non/filetype.v1/matchers`](https://godoc.org/github.com/h2non/filetype/matchers) + +## Examples + +#### Simple file type checking + +```go +package main + +import ( + "fmt" + "gopkg.in/h2non/filetype.v1" + "io/ioutil" +) + +func main() { + buf, _ := ioutil.ReadFile("sample.jpg") + + kind, unknown := filetype.Match(buf) + if unknown != nil { + fmt.Printf("Unknown: %s", unknown) + return + } + + fmt.Printf("File type: %s. MIME: %s\n", kind.Extension, kind.MIME.Value) +} +``` + +#### Check type class + +```go +package main + +import ( + "fmt" + "gopkg.in/h2non/filetype.v1" + "io/ioutil" +) + +func main() { + buf, _ := ioutil.ReadFile("sample.jpg") + + if filetype.IsImage(buf) { + fmt.Println("File is an image") + } else { + fmt.Println("Not an image") + } +} +``` + +#### Supported type + +```go +package main + +import ( + "fmt" + "gopkg.in/h2non/filetype.v1" +) + +func main() { + // Check if file is supported by extension + if filetype.IsSupported("jpg") { + fmt.Println("Extension supported") + } else { + fmt.Println("Extension not supported") + } + + // Check if file is supported by extension + if filetype.IsMIMESupported("image/jpeg") { + fmt.Println("MIME type supported") + } else { + fmt.Println("MIME type not supported") + } +} +``` + +#### File header + +```go +package main + +import ( + "fmt" + "gopkg.in/h2non/filetype.v1" + "io/ioutil" +) + +func main() { + // Open a file descriptor + file, _ := os.Open("movie.mp4") + + // We only have to pass the file header = first 261 bytes + head := make([]byte, 261) + file.Read(head) + + if filetype.IsImage(head) { + fmt.Println("File is an image") + } else { + fmt.Println("Not an image") + } +} +``` + +#### Add additional file type matchers + +```go +package main + +import ( + "fmt" + "gopkg.in/h2non/filetype.v1" +) + +var fooType = filetype.NewType("foo", "foo/foo") + +func fooMatcher(buf []byte) bool { + return len(buf) > 1 && buf[0] == 0x01 && buf[1] == 0x02 +} + +func main() { + // Register the new matcher and its type + filetype.AddMatcher(fooType, fooMatcher) + + // Check if the new type is supported by extension + if filetype.IsSupported("foo") { + fmt.Println("New supported type: foo") + } + + // Check if the new type is supported by MIME + if filetype.IsMIMESupported("foo/foo") { + fmt.Println("New supported MIME type: foo/foo") + } + + // Try to match the file + fooFile := []byte{0x01, 0x02} + kind, _ := filetype.Match(fooFile) + if kind == filetype.Unknown { + fmt.Println("Unknown file type") + } else { + fmt.Printf("File type matched: %s\n", kind.Extension) + } +} +``` + +## Supported types + +#### Image + +- **jpg** - `image/jpeg` +- **png** - `image/png` +- **gif** - `image/gif` +- **webp** - `image/webp` +- **cr2** - `image/x-canon-cr2` +- **tif** - `image/tiff` +- **bmp** - `image/bmp` +- **jxr** - `image/vnd.ms-photo` +- **psd** - `image/vnd.adobe.photoshop` +- **ico** - `image/x-icon` + +#### Video + +- **mp4** - `video/mp4` +- **m4v** - `video/x-m4v` +- **mkv** - `video/x-matroska` +- **webm** - `video/webm` +- **mov** - `video/quicktime` +- **avi** - `video/x-msvideo` +- **wmv** - `video/x-ms-wmv` +- **mpg** - `video/mpeg` +- **flv** - `video/x-flv` + +#### Audio + +- **mid** - `audio/midi` +- **mp3** - `audio/mpeg` +- **m4a** - `audio/m4a` +- **ogg** - `audio/ogg` +- **flac** - `audio/x-flac` +- **wav** - `audio/x-wav` +- **amr** - `audio/amr` + +#### Archive + +- **epub** - `application/epub+zip` +- **zip** - `application/zip` +- **tar** - `application/x-tar` +- **rar** - `application/x-rar-compressed` +- **gz** - `application/gzip` +- **bz2** - `application/x-bzip2` +- **7z** - `application/x-7z-compressed` +- **xz** - `application/x-xz` +- **pdf** - `application/pdf` +- **exe** - `application/x-msdownload` +- **swf** - `application/x-shockwave-flash` +- **rtf** - `application/rtf` +- **eot** - `application/octet-stream` +- **ps** - `application/postscript` +- **sqlite** - `application/x-sqlite3` +- **nes** - `application/x-nintendo-nes-rom` +- **crx** - `application/x-google-chrome-extension` +- **cab** - `application/vnd.ms-cab-compressed` +- **deb** - `application/x-deb` +- **ar** - `application/x-unix-archive` +- **Z** - `application/x-compress` +- **lz** - `application/x-lzip` +- **rpm** - `application/x-rpm` +- **elf** - `application/x-executable` + +#### Documents + +- **doc** - `application/msword` +- **docx** - `application/vnd.openxmlformats-officedocument.wordprocessingml.document` +- **xls** - `application/vnd.ms-excel` +- **xlsx** - `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet` +- **ppt** - `application/vnd.ms-powerpoint` +- **pptx** - `application/vnd.openxmlformats-officedocument.presentationml.presentation` + +#### Font + +- **woff** - `application/font-woff` +- **woff2** - `application/font-woff` +- **ttf** - `application/font-sfnt` +- **otf** - `application/font-sfnt` + +## Benchmarks + +Measured using [real files](https://github.com/h2non/filetype/tree/master/fixtures). + +Environment: OSX x64 i7 2.7 Ghz + +```bash +BenchmarkMatchTar-8 1000000 1083 ns/op +BenchmarkMatchZip-8 1000000 1162 ns/op +BenchmarkMatchJpeg-8 1000000 1280 ns/op +BenchmarkMatchGif-8 1000000 1315 ns/op +BenchmarkMatchPng-8 1000000 1121 ns/op +``` + +## License + +MIT - Tomas Aparicio diff --git a/vendor/gopkg.in/h2non/filetype.v1/filetype.go b/vendor/gopkg.in/h2non/filetype.v1/filetype.go new file mode 100644 index 0000000..3753c03 --- /dev/null +++ b/vendor/gopkg.in/h2non/filetype.v1/filetype.go @@ -0,0 +1,87 @@ +package filetype + +import ( + "errors" + + "gopkg.in/h2non/filetype.v1/matchers" + "gopkg.in/h2non/filetype.v1/types" +) + +// Types stores a map of supported types +var Types = types.Types + +// NewType creates and registers a new type +var NewType = types.NewType + +// Unknown represents an unknown file type +var Unknown = types.Unknown + +// ErrEmptyBuffer represents an empty buffer error +var ErrEmptyBuffer = errors.New("Empty buffer") + +// ErrUnknownBuffer represents a unknown buffer error +var ErrUnknownBuffer = errors.New("Unknown buffer type") + +// AddType registers a new file type +func AddType(ext, mime string) types.Type { + return types.NewType(ext, mime) +} + +// Is checks if a given buffer matches with the given file type extension +func Is(buf []byte, ext string) bool { + kind, ok := types.Types[ext] + if ok { + return IsType(buf, kind) + } + return false +} + +// IsExtension semantic alias to Is() +func IsExtension(buf []byte, ext string) bool { + return Is(buf, ext) +} + +// IsType checks if a given buffer matches with the given file type +func IsType(buf []byte, kind types.Type) bool { + matcher := matchers.Matchers[kind] + if matcher == nil { + return false + } + return matcher(buf) != types.Unknown +} + +// IsMIME checks if a given buffer matches with the given MIME type +func IsMIME(buf []byte, mime string) bool { + for _, kind := range types.Types { + if kind.MIME.Value == mime { + matcher := matchers.Matchers[kind] + return matcher(buf) != types.Unknown + } + } + return false +} + +// IsSupported checks if a given file extension is supported +func IsSupported(ext string) bool { + for name := range Types { + if name == ext { + return true + } + } + return false +} + +// IsMIMESupported checks if a given MIME type is supported +func IsMIMESupported(mime string) bool { + for _, m := range Types { + if m.MIME.Value == mime { + return true + } + } + return false +} + +// GetType retrieves a Type by file extension +func GetType(ext string) types.Type { + return types.Get(ext) +} diff --git a/vendor/gopkg.in/h2non/filetype.v1/filetype_test.go b/vendor/gopkg.in/h2non/filetype.v1/filetype_test.go new file mode 100644 index 0000000..dfa9cce --- /dev/null +++ b/vendor/gopkg.in/h2non/filetype.v1/filetype_test.go @@ -0,0 +1,123 @@ +package filetype + +import ( + "testing" + + "gopkg.in/h2non/filetype.v1/types" +) + +func TestIs(t *testing.T) { + cases := []struct { + buf []byte + ext string + match bool + }{ + {[]byte{0xFF, 0xD8, 0xFF}, "jpg", true}, + {[]byte{0xFF, 0xD8, 0x00}, "jpg", false}, + {[]byte{0x89, 0x50, 0x4E, 0x47}, "png", true}, + } + + for _, test := range cases { + if Is(test.buf, test.ext) != test.match { + t.Fatalf("Invalid match: %s", test.ext) + } + } +} + +func TestIsType(t *testing.T) { + cases := []struct { + buf []byte + kind types.Type + match bool + }{ + {[]byte{0xFF, 0xD8, 0xFF}, types.Get("jpg"), true}, + {[]byte{0xFF, 0xD8, 0x00}, types.Get("jpg"), false}, + {[]byte{0x89, 0x50, 0x4E, 0x47}, types.Get("png"), true}, + } + + for _, test := range cases { + if IsType(test.buf, test.kind) != test.match { + t.Fatalf("Invalid match: %s", test.kind.Extension) + } + } +} + +func TestIsMIME(t *testing.T) { + cases := []struct { + buf []byte + mime string + match bool + }{ + {[]byte{0xFF, 0xD8, 0xFF}, "image/jpeg", true}, + {[]byte{0xFF, 0xD8, 0x00}, "image/jpeg", false}, + {[]byte{0x89, 0x50, 0x4E, 0x47}, "image/png", true}, + } + + for _, test := range cases { + if IsMIME(test.buf, test.mime) != test.match { + t.Fatalf("Invalid match: %s", test.mime) + } + } +} + +func TestIsSupported(t *testing.T) { + cases := []struct { + ext string + match bool + }{ + {"jpg", true}, + {"jpeg", false}, + {"abc", false}, + {"png", true}, + {"mp4", true}, + {"", false}, + } + + for _, test := range cases { + if IsSupported(test.ext) != test.match { + t.Fatalf("Invalid match: %s", test.ext) + } + } +} + +func TestIsMIMESupported(t *testing.T) { + cases := []struct { + mime string + match bool + }{ + {"image/jpeg", true}, + {"foo/bar", false}, + {"image/png", true}, + {"video/mpeg", true}, + } + + for _, test := range cases { + if IsMIMESupported(test.mime) != test.match { + t.Fatalf("Invalid match: %s", test.mime) + } + } +} + +func TestAddType(t *testing.T) { + AddType("foo", "foo/foo") + + if !IsSupported("foo") { + t.Fatalf("Not supported extension") + } + + if !IsMIMESupported("foo/foo") { + t.Fatalf("Not supported MIME type") + } +} + +func TestGetType(t *testing.T) { + jpg := GetType("jpg") + if jpg == types.Unknown { + t.Fatalf("Type should be supported") + } + + invalid := GetType("invalid") + if invalid != Unknown { + t.Fatalf("Type should not be supported") + } +} diff --git a/vendor/gopkg.in/h2non/filetype.v1/kind.go b/vendor/gopkg.in/h2non/filetype.v1/kind.go new file mode 100644 index 0000000..4939725 --- /dev/null +++ b/vendor/gopkg.in/h2non/filetype.v1/kind.go @@ -0,0 +1,69 @@ +package filetype + +import ( + "gopkg.in/h2non/filetype.v1/matchers" + "gopkg.in/h2non/filetype.v1/types" +) + +// Image tries to match a file as image type +func Image(buf []byte) (types.Type, error) { + return doMatchMap(buf, matchers.Image) +} + +// IsImage checks if the given buffer is an image type +func IsImage(buf []byte) bool { + kind, _ := Image(buf) + return kind != types.Unknown +} + +// Audio tries to match a file as audio type +func Audio(buf []byte) (types.Type, error) { + return doMatchMap(buf, matchers.Audio) +} + +// IsAudio checks if the given buffer is an audio type +func IsAudio(buf []byte) bool { + kind, _ := Audio(buf) + return kind != types.Unknown +} + +// Video tries to match a file as video type +func Video(buf []byte) (types.Type, error) { + return doMatchMap(buf, matchers.Video) +} + +// IsVideo checks if the given buffer is a video type +func IsVideo(buf []byte) bool { + kind, _ := Video(buf) + return kind != types.Unknown +} + +// Font tries to match a file as text font type +func Font(buf []byte) (types.Type, error) { + return doMatchMap(buf, matchers.Font) +} + +// IsFont checks if the given buffer is a font type +func IsFont(buf []byte) bool { + kind, _ := Font(buf) + return kind != types.Unknown +} + +// Archive tries to match a file as generic archive type +func Archive(buf []byte) (types.Type, error) { + return doMatchMap(buf, matchers.Archive) +} + +// IsArchive checks if the given buffer is an archive type +func IsArchive(buf []byte) bool { + kind, _ := Archive(buf) + return kind != types.Unknown +} + +func doMatchMap(buf []byte, machers matchers.Map) (types.Type, error) { + kind := MatchMap(buf, machers) + if kind != types.Unknown { + return kind, nil + } + return kind, ErrUnknownBuffer +} diff --git a/vendor/gopkg.in/h2non/filetype.v1/kind_test.go b/vendor/gopkg.in/h2non/filetype.v1/kind_test.go new file mode 100644 index 0000000..7a2478f --- /dev/null +++ b/vendor/gopkg.in/h2non/filetype.v1/kind_test.go @@ -0,0 +1,40 @@ +package filetype + +import ( + "testing" +) + +func TestKind(t *testing.T) { + var cases = []struct { + buf []byte + ext string + }{ + {[]byte{0xFF, 0xD8, 0xFF}, "jpg"}, + {[]byte{0x89, 0x50, 0x4E, 0x47}, "png"}, + {[]byte{0x89, 0x0, 0x0}, "unknown"}, + } + + for _, test := range cases { + kind, _ := Image(test.buf) + if kind.Extension != test.ext { + t.Fatalf("Invalid match: %s != %s", kind.Extension, test.ext) + } + } +} + +func TestIsKind(t *testing.T) { + var cases = []struct { + buf []byte + match bool + }{ + {[]byte{0xFF, 0xD8, 0xFF}, true}, + {[]byte{0x89, 0x50, 0x4E, 0x47}, true}, + {[]byte{0x89, 0x0, 0x0}, false}, + } + + for _, test := range cases { + if IsImage(test.buf) != test.match { + t.Fatalf("Invalid match: %t", test.match) + } + } +} diff --git a/vendor/gopkg.in/h2non/filetype.v1/match.go b/vendor/gopkg.in/h2non/filetype.v1/match.go new file mode 100644 index 0000000..9b6e376 --- /dev/null +++ b/vendor/gopkg.in/h2non/filetype.v1/match.go @@ -0,0 +1,86 @@ +package filetype + +import ( + "io" + "os" + + "gopkg.in/h2non/filetype.v1/matchers" + "gopkg.in/h2non/filetype.v1/types" +) + +// Matchers is an alias to matchers.Matchers +var Matchers = matchers.Matchers + +// NewMatcher is an alias to matchers.NewMatcher +var NewMatcher = matchers.NewMatcher + +// Match infers the file type of a given buffer inspecting its magic numbers signature +func Match(buf []byte) (types.Type, error) { + length := len(buf) + if length == 0 { + return types.Unknown, ErrEmptyBuffer + } + + for _, checker := range Matchers { + match := checker(buf) + if match != types.Unknown && match.Extension != "" { + return match, nil + } + } + + return types.Unknown, nil +} + +// Get is an alias to Match() +func Get(buf []byte) (types.Type, error) { + return Match(buf) +} + +// MatchFile infers a file type for a file +func MatchFile(filepath string) (types.Type, error) { + file, err := os.Open(filepath) + if err != nil { + return types.Unknown, err + } + defer file.Close() + + return MatchReader(file) +} + +// MatchReader is convenient wrapper to Match() any Reader +func MatchReader(reader io.Reader) (types.Type, error) { + buffer := make([]byte, 512) + + _, err := reader.Read(buffer) + if err != nil && err != io.EOF { + return types.Unknown, err + } + + return Match(buffer) +} + +// AddMatcher registers a new matcher type +func AddMatcher(fileType types.Type, matcher matchers.Matcher) matchers.TypeMatcher { + return matchers.NewMatcher(fileType, matcher) +} + +// Matches checks if the given buffer matches with some supported file type +func Matches(buf []byte) bool { + kind, _ := Match(buf) + return kind != types.Unknown +} + +// MatchMap performs a file matching againts a map of match functions +func MatchMap(buf []byte, matchers matchers.Map) types.Type { + for kind, matcher := range matchers { + if matcher(buf) { + return kind + } + } + return types.Unknown +} + +// MatchesMap is an alias to Matches() but using matching againts a map of match functions +func MatchesMap(buf []byte, matchers matchers.Map) bool { + return MatchMap(buf, matchers) != types.Unknown +} diff --git a/vendor/gopkg.in/h2non/filetype.v1/match_test.go b/vendor/gopkg.in/h2non/filetype.v1/match_test.go new file mode 100644 index 0000000..5dcbb5e --- /dev/null +++ b/vendor/gopkg.in/h2non/filetype.v1/match_test.go @@ -0,0 +1,187 @@ +package filetype + +import ( + "bytes" + "io" + "io/ioutil" + "testing" + + "gopkg.in/h2non/filetype.v1/matchers" + "gopkg.in/h2non/filetype.v1/types" +) + +func TestMatch(t *testing.T) { + cases := []struct { + buf []byte + ext string + }{ + {[]byte{0xFF, 0xD8, 0xFF}, "jpg"}, + {[]byte{0xFF, 0xD8, 0x00}, "unknown"}, + {[]byte{0x89, 0x50, 0x4E, 0x47}, "png"}, + } + + for _, test := range cases { + match, err := Match(test.buf) + if err != nil { + t.Fatalf("Error: %s", err) + } + + if match.Extension != test.ext { + t.Fatalf("Invalid image type: %s != %s", match.Extension, test.ext) + } + } +} + +func TestMatchFile(t *testing.T) { + cases := []struct { + ext string + }{ + {"gif"}, + {"jpg"}, + {"png"}, + {"zip"}, + {"tar"}, + {"tif"}, + {"mp4"}, + } + + for _, test := range cases { + kind, _ := MatchFile("./fixtures/sample." + test.ext) + if kind.Extension != test.ext { + t.Fatalf("Invalid image type: %s != %s", kind.Extension, test.ext) + } + } +} + +func TestMatchReader(t *testing.T) { + cases := []struct { + buf io.Reader + ext string + }{ + {bytes.NewBuffer([]byte{0xFF, 0xD8, 0xFF}), "jpg"}, + {bytes.NewBuffer([]byte{0xFF, 0xD8, 0x00}), "unknown"}, + {bytes.NewBuffer([]byte{0x89, 0x50, 0x4E, 0x47}), "png"}, + } + + for _, test := range cases { + match, err := MatchReader(test.buf) + if err != nil { + t.Fatalf("Error: %s", err) + } + + if match.Extension != test.ext { + t.Fatalf("Invalid image type: %s", match.Extension) + } + } +} + +func TestMatches(t *testing.T) { + cases := []struct { + buf []byte + match bool + }{ + {[]byte{0xFF, 0xD8, 0xFF}, true}, + {[]byte{0xFF, 0x0, 0x0}, false}, + {[]byte{0x89, 0x50, 0x4E, 0x47}, true}, + } + + for _, test := range cases { + if Matches(test.buf) != test.match { + t.Fatalf("Do not matches: %#v", test.buf) + } + } +} + +func TestAddMatcher(t *testing.T) { + fileType := AddType("foo", "foo/foo") + + AddMatcher(fileType, func(buf []byte) bool { + return len(buf) == 2 && buf[0] == 0x00 && buf[1] == 0x00 + }) + + if !Is([]byte{0x00, 0x00}, "foo") { + t.Fatalf("Type cannot match") + } + + if !IsSupported("foo") { + t.Fatalf("Not supported extension") + } + + if !IsMIMESupported("foo/foo") { + t.Fatalf("Not supported MIME type") + } +} + +func TestMatchMap(t *testing.T) { + cases := []struct { + buf []byte + kind types.Type + }{ + {[]byte{0xFF, 0xD8, 0xFF}, types.Get("jpg")}, + {[]byte{0x89, 0x50, 0x4E, 0x47}, types.Get("png")}, + {[]byte{0xFF, 0x0, 0x0}, Unknown}, + } + + for _, test := range cases { + if kind := MatchMap(test.buf, matchers.Image); kind != test.kind { + t.Fatalf("Do not matches: %#v", test.buf) + } + } +} + +func TestMatchesMap(t *testing.T) { + cases := []struct { + buf []byte + match bool + }{ + {[]byte{0xFF, 0xD8, 0xFF}, true}, + {[]byte{0x89, 0x50, 0x4E, 0x47}, true}, + {[]byte{0xFF, 0x0, 0x0}, false}, + } + + for _, test := range cases { + if match := MatchesMap(test.buf, matchers.Image); match != test.match { + t.Fatalf("Do not matches: %#v", test.buf) + } + } +} + +// +// Benchmarks +// + +var tarBuffer, _ = ioutil.ReadFile("./fixtures/sample.tar") +var zipBuffer, _ = ioutil.ReadFile("./fixtures/sample.zip") +var jpgBuffer, _ = ioutil.ReadFile("./fixtures/sample.jpg") +var gifBuffer, _ = ioutil.ReadFile("./fixtures/sample.gif") +var pngBuffer, _ = ioutil.ReadFile("./fixtures/sample.png") + +func BenchmarkMatchTar(b *testing.B) { + for n := 0; n < b.N; n++ { + Match(tarBuffer) + } +} + +func BenchmarkMatchZip(b *testing.B) { + for n := 0; n < b.N; n++ { + Match(zipBuffer) + } +} + +func BenchmarkMatchJpeg(b *testing.B) { + for n := 0; n < b.N; n++ { + Match(jpgBuffer) + } +} + +func BenchmarkMatchGif(b *testing.B) { + for n := 0; n < b.N; n++ { + Match(gifBuffer) + } +} + +func BenchmarkMatchPng(b *testing.B) { + for n := 0; n < b.N; n++ { + Match(pngBuffer) + } +} diff --git a/vendor/gopkg.in/h2non/filetype.v1/matchers/archive.go b/vendor/gopkg.in/h2non/filetype.v1/matchers/archive.go new file mode 100644 index 0000000..9c1270f --- /dev/null +++ b/vendor/gopkg.in/h2non/filetype.v1/matchers/archive.go @@ -0,0 +1,217 @@ +package matchers + +var ( + TypeEpub = newType("epub", "application/epub+zip") + TypeZip = newType("zip", "application/zip") + TypeTar = newType("tar", "application/x-tar") + TypeRar = newType("rar", "application/x-rar-compressed") + TypeGz = newType("gz", "application/gzip") + TypeBz2 = newType("bz2", "application/x-bzip2") + Type7z = newType("7z", "application/x-7z-compressed") + TypeXz = newType("xz", "application/x-xz") + TypePdf = newType("pdf", "application/pdf") + TypeExe = newType("exe", "application/x-msdownload") + TypeSwf = newType("swf", "application/x-shockwave-flash") + TypeRtf = newType("rtf", "application/rtf") + TypeEot = newType("eot", "application/octet-stream") + TypePs = newType("ps", "application/postscript") + TypeSqlite = newType("sqlite", "application/x-sqlite3") + TypeNes = newType("nes", "application/x-nintendo-nes-rom") + TypeCrx = newType("crx", "application/x-google-chrome-extension") + TypeCab = newType("cab", "application/vnd.ms-cab-compressed") + TypeDeb = newType("deb", "application/x-deb") + TypeAr = newType("ar", "application/x-unix-archive") + TypeZ = newType("Z", "application/x-compress") + TypeLz = newType("lz", "application/x-lzip") + TypeRpm = newType("rpm", "application/x-rpm") + TypeElf = newType("elf", "application/x-executable") +) + +var Archive = Map{ + TypeEpub: Epub, + TypeZip: Zip, + TypeTar: Tar, + TypeRar: Rar, + TypeGz: Gz, + TypeBz2: Bz2, + Type7z: SevenZ, + TypeXz: Xz, + TypePdf: Pdf, + TypeExe: Exe, + TypeSwf: Swf, + TypeRtf: Rtf, + TypeEot: Eot, + TypePs: Ps, + TypeSqlite: Sqlite, + TypeNes: Nes, + TypeCrx: Crx, + TypeCab: Cab, + TypeDeb: Deb, + TypeAr: Ar, + TypeZ: Z, + TypeLz: Lz, + TypeRpm: Rpm, + TypeElf: Elf, +} + +func Epub(buf []byte) bool { + return len(buf) > 57 && + buf[0] == 0x50 && buf[1] == 0x4B && buf[2] == 0x3 && buf[3] == 0x4 && + buf[30] == 0x6D && buf[31] == 0x69 && buf[32] == 0x6D && buf[33] == 0x65 && + buf[34] == 0x74 && buf[35] == 0x79 && buf[36] == 0x70 && buf[37] == 0x65 && + buf[38] == 0x61 && buf[39] == 0x70 && buf[40] == 0x70 && buf[41] == 0x6C && + buf[42] == 0x69 && buf[43] == 0x63 && buf[44] == 0x61 && buf[45] == 0x74 && + buf[46] == 0x69 && buf[47] == 0x6F && buf[48] == 0x6E && buf[49] == 0x2F && + buf[50] == 0x65 && buf[51] == 0x70 && buf[52] == 0x75 && buf[53] == 0x62 && + buf[54] == 0x2B && buf[55] == 0x7A && buf[56] == 0x69 && buf[57] == 0x70 +} + +func Zip(buf []byte) bool { + return len(buf) > 3 && + buf[0] == 0x50 && buf[1] == 0x4B && + (buf[2] == 0x3 || buf[2] == 0x5 || buf[2] == 0x7) && + (buf[3] == 0x4 || buf[3] == 0x6 || buf[3] == 0x8) +} + +func Tar(buf []byte) bool { + return len(buf) > 261 && + buf[257] == 0x75 && buf[258] == 0x73 && + buf[259] == 0x74 && buf[260] == 0x61 && + buf[261] == 0x72 +} + +func Rar(buf []byte) bool { + return len(buf) > 6 && + buf[0] == 0x52 && buf[1] == 0x61 && buf[2] == 0x72 && + buf[3] == 0x21 && buf[4] == 0x1A && buf[5] == 0x7 && + (buf[6] == 0x0 || buf[6] == 0x1) +} + +func Gz(buf []byte) bool { + return len(buf) > 2 && + buf[0] == 0x1F && buf[1] == 0x8B && buf[2] == 0x8 +} + +func Bz2(buf []byte) bool { + return len(buf) > 2 && + buf[0] == 0x42 && buf[1] == 0x5A && buf[2] == 0x68 +} + +func SevenZ(buf []byte) bool { + return len(buf) > 5 && + buf[0] == 0x37 && buf[1] == 0x7A && buf[2] == 0xBC && + buf[3] == 0xAF && buf[4] == 0x27 && buf[5] == 0x1C +} + +func Pdf(buf []byte) bool { + return len(buf) > 3 && + buf[0] == 0x25 && buf[1] == 0x50 && + buf[2] == 0x44 && buf[3] == 0x46 +} + +func Exe(buf []byte) bool { + return len(buf) > 1 && + buf[0] == 0x4D && buf[1] == 0x5A +} + +func Swf(buf []byte) bool { + return len(buf) > 2 && + (buf[0] == 0x43 || buf[0] == 0x46) && + buf[1] == 0x57 && buf[2] == 0x53 +} + +func Rtf(buf []byte) bool { + return len(buf) > 4 && + buf[0] == 0x7B && buf[1] == 0x5C && + buf[2] == 0x72 && buf[3] == 0x74 && + buf[4] == 0x66 +} + +func Nes(buf []byte) bool { + return len(buf) > 3 && + buf[0] == 0x4E && buf[1] == 0x45 && + buf[2] == 0x53 && buf[3] == 0x1A +} + +func Crx(buf []byte) bool { + return len(buf) > 3 && + buf[0] == 0x43 && buf[1] == 0x72 && + buf[2] == 0x32 && buf[3] == 0x34 +} + +func Cab(buf []byte) bool { + return len(buf) > 3 && + ((buf[0] == 0x4D && buf[1] == 0x53 && buf[2] == 0x43 && buf[3] == 0x46) || + (buf[0] == 0x49 && buf[1] == 0x53 && buf[2] == 0x63 && buf[3] == 0x28)) +} + +func Eot(buf []byte) bool { + return len(buf) > 35 && + buf[34] == 0x4C && buf[35] == 0x50 && + ((buf[8] == 0x02 && buf[9] == 0x00 && + buf[10] == 0x01) || (buf[8] == 0x01 && + buf[9] == 0x00 && buf[10] == 0x00) || + (buf[8] == 0x02 && buf[9] == 0x00 && + buf[10] == 0x02)) +} + +func Ps(buf []byte) bool { + return len(buf) > 1 && + buf[0] == 0x25 && buf[1] == 0x21 +} + +func Xz(buf []byte) bool { + return len(buf) > 5 && + buf[0] == 0xFD && buf[1] == 0x37 && + buf[2] == 0x7A && buf[3] == 0x58 && + buf[4] == 0x5A && buf[5] == 0x00 +} + +func Sqlite(buf []byte) bool { + return len(buf) > 3 && + buf[0] == 0x53 && buf[1] == 0x51 && + buf[2] == 0x4C && buf[3] == 0x69 +} + +func Deb(buf []byte) bool { + return len(buf) > 20 && + buf[0] == 0x21 && buf[1] == 0x3C && buf[2] == 0x61 && + buf[3] == 0x72 && buf[4] == 0x63 && buf[5] == 0x68 && + buf[6] == 0x3E && buf[7] == 0x0A && buf[8] == 0x64 && + buf[9] == 0x65 && buf[10] == 0x62 && buf[11] == 0x69 && + buf[12] == 0x61 && buf[13] == 0x6E && buf[14] == 0x2D && + buf[15] == 0x62 && buf[16] == 0x69 && buf[17] == 0x6E && + buf[18] == 0x61 && buf[19] == 0x72 && buf[20] == 0x79 +} + +func Ar(buf []byte) bool { + return len(buf) > 6 && + buf[0] == 0x21 && buf[1] == 0x3C && + buf[2] == 0x61 && buf[3] == 0x72 && + buf[4] == 0x63 && buf[5] == 0x68 && + buf[6] == 0x3E +} + +func Z(buf []byte) bool { + return len(buf) > 1 && + ((buf[0] == 0x1F && buf[1] == 0xA0) || + (buf[0] == 0x1F && buf[1] == 0x9D)) +} + +func Lz(buf []byte) bool { + return len(buf) > 3 && + buf[0] == 0x4C && buf[1] == 0x5A && + buf[2] == 0x49 && buf[3] == 0x50 +} + +func Rpm(buf []byte) bool { + return len(buf) > 96 && + buf[0] == 0xED && buf[1] == 0xAB && + buf[2] == 0xEE && buf[3] == 0xDB +} + +func Elf(buf []byte) bool { + return len(buf) > 52 && + buf[0] == 0x7F && buf[1] == 0x45 && + buf[2] == 0x4C && buf[3] == 0x46 +} diff --git a/vendor/gopkg.in/h2non/filetype.v1/matchers/audio.go b/vendor/gopkg.in/h2non/filetype.v1/matchers/audio.go new file mode 100644 index 0000000..7b27caf --- /dev/null +++ b/vendor/gopkg.in/h2non/filetype.v1/matchers/audio.go @@ -0,0 +1,67 @@ +package matchers + +var ( + TypeMidi = newType("mid", "audio/midi") + TypeMp3 = newType("mp3", "audio/mpeg") + TypeM4a = newType("m4a", "audio/m4a") + TypeOgg = newType("ogg", "audio/ogg") + TypeFlac = newType("flac", "audio/x-flac") + TypeWav = newType("wav", "audio/x-wav") + TypeAmr = newType("amr", "audio/amr") +) + +var Audio = Map{ + TypeMidi: Midi, + TypeMp3: Mp3, + TypeM4a: M4a, + TypeOgg: Ogg, + TypeFlac: Flac, + TypeWav: Wav, + TypeAmr: Amr, +} + +func Midi(buf []byte) bool { + return len(buf) > 3 && + buf[0] == 0x4D && buf[1] == 0x54 && + buf[2] == 0x68 && buf[3] == 0x64 +} + +func Mp3(buf []byte) bool { + return len(buf) > 2 && + ((buf[0] == 0x49 && buf[1] == 0x44 && buf[2] == 0x33) || + (buf[0] == 0xFF && buf[1] == 0xfb)) +} + +func M4a(buf []byte) bool { + return len(buf) > 10 && + ((buf[4] == 0x66 && buf[5] == 0x74 && buf[6] == 0x79 && + buf[7] == 0x70 && buf[8] == 0x4D && buf[9] == 0x34 && buf[10] == 0x41) || + (buf[0] == 0x4D && buf[1] == 0x34 && buf[2] == 0x41 && buf[3] == 0x20)) +} + +func Ogg(buf []byte) bool { + return len(buf) > 3 && + buf[0] == 0x4F && buf[1] == 0x67 && + buf[2] == 0x67 && buf[3] == 0x53 +} + +func Flac(buf []byte) bool { + return len(buf) > 3 && + buf[0] == 0x66 && buf[1] == 0x4C && + buf[2] == 0x61 && buf[3] == 0x43 +} + +func Wav(buf []byte) bool { + return len(buf) > 11 && + buf[0] == 0x52 && buf[1] == 0x49 && + buf[2] == 0x46 && buf[3] == 0x46 && + buf[8] == 0x57 && buf[9] == 0x41 && + buf[10] == 0x56 && buf[11] == 0x45 +} + +func Amr(buf []byte) bool { + return len(buf) > 11 && + buf[0] == 0x23 && buf[1] == 0x21 && + buf[2] == 0x41 && buf[3] == 0x4D && + buf[4] == 0x52 && buf[5] == 0x0A +} diff --git a/vendor/gopkg.in/h2non/filetype.v1/matchers/document.go b/vendor/gopkg.in/h2non/filetype.v1/matchers/document.go new file mode 100644 index 0000000..cc5ded2 --- /dev/null +++ b/vendor/gopkg.in/h2non/filetype.v1/matchers/document.go @@ -0,0 +1,66 @@ +package matchers + +import "bytes" + +var ( + TypeDoc = newType("doc", "application/msword") + TypeDocx = newType("docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document") + TypeXls = newType("xls", "application/vnd.ms-excel") + TypeXlsx = newType("xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") + TypePpt = newType("ppt", "application/vnd.ms-powerpoint") + TypePptx = newType("pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation") +) + +var Document = Map{ + TypeDoc: Doc, + TypeDocx: Docx, + TypeXls: Xls, + TypeXlsx: Xlsx, + TypePpt: Ppt, + TypePptx: Pptx, +} + +func Doc(buf []byte) bool { + return len(buf) > 7 && + buf[0] == 0xD0 && buf[1] == 0xCF && + buf[2] == 0x11 && buf[3] == 0xE0 && + buf[4] == 0xA1 && buf[5] == 0xB1 && + buf[6] == 0x1A && buf[7] == 0xE1 +} + +func Docx(buf []byte) bool { + return len(buf) > 3 && + buf[0] == 0x50 && buf[1] == 0x4B && + buf[2] == 0x03 && buf[3] == 0x04 && + bytes.Contains(buf[:256], []byte(TypeDocx.MIME.Value)) +} + +func Xls(buf []byte) bool { + return len(buf) > 7 && + buf[0] == 0xD0 && buf[1] == 0xCF && + buf[2] == 0x11 && buf[3] == 0xE0 && + buf[4] == 0xA1 && buf[5] == 0xB1 && + buf[6] == 0x1A && buf[7] == 0xE1 +} + +func Xlsx(buf []byte) bool { + return len(buf) > 3 && + buf[0] == 0x50 && buf[1] == 0x4B && + buf[2] == 0x03 && buf[3] == 0x04 && + bytes.Contains(buf[:256], []byte(TypeXlsx.MIME.Value)) +} + +func Ppt(buf []byte) bool { + return len(buf) > 7 && + buf[0] == 0xD0 && buf[1] == 0xCF && + buf[2] == 0x11 && buf[3] == 0xE0 && + buf[4] == 0xA1 && buf[5] == 0xB1 && + buf[6] == 0x1A && buf[7] == 0xE1 +} + +func Pptx(buf []byte) bool { + return len(buf) > 3 && + buf[0] == 0x50 && buf[1] == 0x4B && + buf[2] == 0x07 && buf[3] == 0x08 && + bytes.Contains(buf[:256], []byte(TypePptx.MIME.Value)) +} diff --git a/vendor/gopkg.in/h2non/filetype.v1/matchers/font.go b/vendor/gopkg.in/h2non/filetype.v1/matchers/font.go new file mode 100644 index 0000000..f391716 --- /dev/null +++ b/vendor/gopkg.in/h2non/filetype.v1/matchers/font.go @@ -0,0 +1,45 @@ +package matchers + +var ( + TypeWoff = newType("woff", "application/font-woff") + TypeWoff2 = newType("woff2", "application/font-woff") + TypeTtf = newType("ttf", "application/font-sfnt") + TypeOtf = newType("otf", "application/font-sfnt") +) + +var Font = Map{ + TypeWoff: Woff, + TypeWoff2: Woff2, + TypeTtf: Ttf, + TypeOtf: Otf, +} + +func Woff(buf []byte) bool { + return len(buf) > 7 && + buf[0] == 0x77 && buf[1] == 0x4F && + buf[2] == 0x46 && buf[3] == 0x46 && + buf[4] == 0x00 && buf[5] == 0x01 && + buf[6] == 0x00 && buf[7] == 0x00 +} + +func Woff2(buf []byte) bool { + return len(buf) > 7 && + buf[0] == 0x77 && buf[1] == 0x4F && + buf[2] == 0x46 && buf[3] == 0x32 && + buf[4] == 0x00 && buf[5] == 0x01 && + buf[6] == 0x00 && buf[7] == 0x00 +} + +func Ttf(buf []byte) bool { + return len(buf) > 4 && + buf[0] == 0x00 && buf[1] == 0x01 && + buf[2] == 0x00 && buf[3] == 0x00 && + buf[4] == 0x00 +} + +func Otf(buf []byte) bool { + return len(buf) > 4 && + buf[0] == 0x4F && buf[1] == 0x54 && + buf[2] == 0x54 && buf[3] == 0x4F && + buf[4] == 0x00 +} diff --git a/vendor/gopkg.in/h2non/filetype.v1/matchers/image.go b/vendor/gopkg.in/h2non/filetype.v1/matchers/image.go new file mode 100644 index 0000000..bc3378d --- /dev/null +++ b/vendor/gopkg.in/h2non/filetype.v1/matchers/image.go @@ -0,0 +1,89 @@ +package matchers + +var ( + TypeJpeg = newType("jpg", "image/jpeg") + TypePng = newType("png", "image/png") + TypeGif = newType("gif", "image/gif") + TypeWebp = newType("webp", "image/webp") + TypeCR2 = newType("cr2", "image/x-canon-cr2") + TypeTiff = newType("tif", "image/tiff") + TypeBmp = newType("bmp", "image/bmp") + TypeJxr = newType("jxr", "image/vnd.ms-photo") + TypePsd = newType("psd", "image/vnd.adobe.photoshop") + TypeIco = newType("ico", "image/x-icon") +) + +var Image = Map{ + TypeJpeg: Jpeg, + TypePng: Png, + TypeGif: Gif, + TypeWebp: Webp, + TypeCR2: CR2, + TypeTiff: Tiff, + TypeBmp: Bmp, + TypeJxr: Jxr, + TypePsd: Psd, + TypeIco: Ico, +} + +func Jpeg(buf []byte) bool { + return len(buf) > 2 && + buf[0] == 0xFF && + buf[1] == 0xD8 && + buf[2] == 0xFF +} + +func Png(buf []byte) bool { + return len(buf) > 3 && + buf[0] == 0x89 && buf[1] == 0x50 && + buf[2] == 0x4E && buf[3] == 0x47 +} + +func Gif(buf []byte) bool { + return len(buf) > 2 && + buf[0] == 0x47 && buf[1] == 0x49 && buf[2] == 0x46 +} + +func Webp(buf []byte) bool { + return len(buf) > 11 && + buf[8] == 0x57 && buf[9] == 0x45 && + buf[10] == 0x42 && buf[11] == 0x50 +} + +func CR2(buf []byte) bool { + return len(buf) > 9 && + ((buf[0] == 0x49 && buf[1] == 0x49 && buf[2] == 0x2A && buf[3] == 0x0) || + (buf[0] == 0x4D && buf[1] == 0x4D && buf[2] == 0x0 && buf[3] == 0x2A)) && + buf[8] == 0x43 && buf[9] == 0x52 +} + +func Tiff(buf []byte) bool { + return len(buf) > 3 && + ((buf[0] == 0x49 && buf[1] == 0x49 && buf[2] == 0x2A && buf[3] == 0x0) || + (buf[0] == 0x4D && buf[1] == 0x4D && buf[2] == 0x0 && buf[3] == 0x2A)) +} + +func Bmp(buf []byte) bool { + return len(buf) > 1 && + buf[0] == 0x42 && + buf[1] == 0x4D +} + +func Jxr(buf []byte) bool { + return len(buf) > 2 && + buf[0] == 0x49 && + buf[1] == 0x49 && + buf[2] == 0xBC +} + +func Psd(buf []byte) bool { + return len(buf) > 3 && + buf[0] == 0x38 && buf[1] == 0x42 && + buf[2] == 0x50 && buf[3] == 0x53 +} + +func Ico(buf []byte) bool { + return len(buf) > 3 && + buf[0] == 0x00 && buf[1] == 0x00 && + buf[2] == 0x01 && buf[3] == 0x00 +} diff --git a/vendor/gopkg.in/h2non/filetype.v1/matchers/matchers.go b/vendor/gopkg.in/h2non/filetype.v1/matchers/matchers.go new file mode 100644 index 0000000..4525c02 --- /dev/null +++ b/vendor/gopkg.in/h2non/filetype.v1/matchers/matchers.go @@ -0,0 +1,44 @@ +package matchers + +import "gopkg.in/h2non/filetype.v1/types" + +// Internal shortcut to NewType +var newType = types.NewType + +// Matcher function interface as type alias +type Matcher func([]byte) bool + +// Type interface to store pairs of type with its matcher function +type Map map[types.Type]Matcher + +// Type specific matcher function interface +type TypeMatcher func([]byte) types.Type + +// Store registered file type matchers +var Matchers = make(map[types.Type]TypeMatcher) + +// Create and register a new type matcher function +func NewMatcher(kind types.Type, fn Matcher) TypeMatcher { + matcher := func(buf []byte) types.Type { + if fn(buf) { + return kind + } + return types.Unknown + } + + Matchers[kind] = matcher + return matcher +} + +func register(matchers ...Map) { + for _, m := range matchers { + for kind, matcher := range m { + NewMatcher(kind, matcher) + } + } +} + +func init() { + // Arguments order is intentional + register(Image, Video, Audio, Font, Document, Archive) +} diff --git a/vendor/gopkg.in/h2non/filetype.v1/matchers/video.go b/vendor/gopkg.in/h2non/filetype.v1/matchers/video.go new file mode 100644 index 0000000..9b8350b --- /dev/null +++ b/vendor/gopkg.in/h2non/filetype.v1/matchers/video.go @@ -0,0 +1,120 @@ +package matchers + +var ( + TypeMp4 = newType("mp4", "video/mp4") + TypeM4v = newType("m4v", "video/x-m4v") + TypeMkv = newType("mkv", "video/x-matroska") + TypeWebm = newType("webm", "video/webm") + TypeMov = newType("mov", "video/quicktime") + TypeAvi = newType("avi", "video/x-msvideo") + TypeWmv = newType("wmv", "video/x-ms-wmv") + TypeMpeg = newType("mpg", "video/mpeg") + TypeFlv = newType("flv", "video/x-flv") +) + +var Video = Map{ + TypeMp4: Mp4, + TypeM4v: M4v, + TypeMkv: Mkv, + TypeWebm: Webm, + TypeMov: Mov, + TypeAvi: Avi, + TypeWmv: Wmv, + TypeMpeg: Mpeg, + TypeFlv: Flv, +} + +func M4v(buf []byte) bool { + return len(buf) > 10 && + buf[0] == 0x0 && buf[1] == 0x0 && + buf[2] == 0x0 && buf[3] == 0x1C && + buf[4] == 0x66 && buf[5] == 0x74 && + buf[6] == 0x79 && buf[7] == 0x70 && + buf[8] == 0x4D && buf[9] == 0x34 && + buf[10] == 0x56 +} + +func Mkv(buf []byte) bool { + return (len(buf) > 15 && + buf[0] == 0x1A && buf[1] == 0x45 && + buf[2] == 0xDF && buf[3] == 0xA3 && + buf[4] == 0x93 && buf[5] == 0x42 && + buf[6] == 0x82 && buf[7] == 0x88 && + buf[8] == 0x6D && buf[9] == 0x61 && + buf[10] == 0x74 && buf[11] == 0x72 && + buf[12] == 0x6F && buf[13] == 0x73 && + buf[14] == 0x6B && buf[15] == 0x61) || + (len(buf) > 38 && + buf[31] == 0x6D && buf[32] == 0x61 && + buf[33] == 0x74 && buf[34] == 0x72 && + buf[35] == 0x6f && buf[36] == 0x73 && + buf[37] == 0x6B && buf[38] == 0x61) +} + +func Webm(buf []byte) bool { + return len(buf) > 3 && + buf[0] == 0x1A && buf[1] == 0x45 && + buf[2] == 0xDF && buf[3] == 0xA3 +} + +func Mov(buf []byte) bool { + return len(buf) > 7 && + buf[0] == 0x0 && buf[1] == 0x0 && + buf[2] == 0x0 && buf[3] == 0x14 && + buf[4] == 0x66 && buf[5] == 0x74 && + buf[6] == 0x79 && buf[7] == 0x70 +} + +func Avi(buf []byte) bool { + return len(buf) > 10 && + buf[0] == 0x52 && buf[1] == 0x49 && + buf[2] == 0x46 && buf[3] == 0x46 && + buf[8] == 0x41 && buf[9] == 0x56 && + buf[10] == 0x49 +} + +func Wmv(buf []byte) bool { + return len(buf) > 9 && + buf[0] == 0x30 && buf[1] == 0x26 && + buf[2] == 0xB2 && buf[3] == 0x75 && + buf[4] == 0x8E && buf[5] == 0x66 && + buf[6] == 0xCF && buf[7] == 0x11 && + buf[8] == 0xA6 && buf[9] == 0xD9 +} + +func Mpeg(buf []byte) bool { + return len(buf) > 3 && + buf[0] == 0x0 && buf[1] == 0x0 && + buf[2] == 0x1 && buf[3] >= 0xb0 && + buf[3] <= 0xbf +} + +func Flv(buf []byte) bool { + return len(buf) > 3 && + buf[0] == 0x46 && buf[1] == 0x4C && + buf[2] == 0x56 && buf[3] == 0x01 +} + +func Mp4(buf []byte) bool { + return len(buf) > 11 && + (buf[4] == 'f' && buf[5] == 't' && buf[6] == 'y' && buf[7] == 'p') && + ((buf[8] == 'a' && buf[9] == 'v' && buf[10] == 'c' && buf[11] == '1') || + (buf[8] == 'i' && buf[9] == 's' && buf[10] == 'o' && buf[11] == '2') || + (buf[8] == 'i' && buf[9] == 's' && buf[10] == 'o' && buf[11] == 'm') || + (buf[8] == 'm' && buf[9] == 'm' && buf[10] == 'p' && buf[11] == '4') || + (buf[8] == 'm' && buf[9] == 'p' && buf[10] == '4' && buf[11] == '1') || + (buf[8] == 'm' && buf[9] == 'p' && buf[10] == '4' && buf[11] == '2') || + (buf[8] == 'm' && buf[9] == 'p' && buf[10] == '7' && buf[11] == '1') || + (buf[8] == 'm' && buf[9] == 's' && buf[10] == 'n' && buf[11] == 'v') || + (buf[8] == 'n' && buf[9] == 'd' && buf[10] == 'a' && buf[11] == 's') || + (buf[8] == 'n' && buf[9] == 'd' && buf[10] == 's' && buf[11] == 'c') || + (buf[8] == 'n' && buf[9] == 'd' && buf[10] == 's' && buf[11] == 'h') || + (buf[8] == 'n' && buf[9] == 'd' && buf[10] == 's' && buf[11] == 'm') || + (buf[8] == 'n' && buf[9] == 'd' && buf[10] == 's' && buf[11] == 'p') || + (buf[8] == 'n' && buf[9] == 'd' && buf[10] == 's' && buf[11] == 's') || + (buf[8] == 'n' && buf[9] == 'd' && buf[10] == 'x' && buf[11] == 'c') || + (buf[8] == 'n' && buf[9] == 'd' && buf[10] == 'x' && buf[11] == 'h') || + (buf[8] == 'n' && buf[9] == 'd' && buf[10] == 'x' && buf[11] == 'm') || + (buf[8] == 'n' && buf[9] == 'd' && buf[10] == 'x' && buf[11] == 'p') || + (buf[8] == 'n' && buf[9] == 'd' && buf[10] == 'x' && buf[11] == 's')) +} diff --git a/vendor/gopkg.in/h2non/filetype.v1/types/defaults.go b/vendor/gopkg.in/h2non/filetype.v1/types/defaults.go new file mode 100644 index 0000000..bb1ea62 --- /dev/null +++ b/vendor/gopkg.in/h2non/filetype.v1/types/defaults.go @@ -0,0 +1,4 @@ +package types + +// Unkown default type +var Unknown = NewType("unknown", "") diff --git a/vendor/gopkg.in/h2non/filetype.v1/types/mime.go b/vendor/gopkg.in/h2non/filetype.v1/types/mime.go new file mode 100644 index 0000000..fe8ea82 --- /dev/null +++ b/vendor/gopkg.in/h2non/filetype.v1/types/mime.go @@ -0,0 +1,14 @@ +package types + +// MIME stores the file MIME type values +type MIME struct { + Type string + Subtype string + Value string +} + +// Creates a new MIME type +func NewMIME(mime string) MIME { + kind, subtype := splitMime(mime) + return MIME{Type: kind, Subtype: subtype, Value: mime} +} diff --git a/vendor/gopkg.in/h2non/filetype.v1/types/split.go b/vendor/gopkg.in/h2non/filetype.v1/types/split.go new file mode 100644 index 0000000..68a5a8b --- /dev/null +++ b/vendor/gopkg.in/h2non/filetype.v1/types/split.go @@ -0,0 +1,11 @@ +package types + +import "strings" + +func splitMime(s string) (string, string) { + x := strings.Split(s, "/") + if len(x) > 1 { + return x[0], x[1] + } + return x[0], "" +} diff --git a/vendor/gopkg.in/h2non/filetype.v1/types/split_test.go b/vendor/gopkg.in/h2non/filetype.v1/types/split_test.go new file mode 100644 index 0000000..b051457 --- /dev/null +++ b/vendor/gopkg.in/h2non/filetype.v1/types/split_test.go @@ -0,0 +1,27 @@ +package types + +import "testing" + +func TestSplit(t *testing.T) { + cases := []struct { + mime string + kind string + subtype string + }{ + {"image/jpeg", "image", "jpeg"}, + {"/jpeg", "", "jpeg"}, + {"image/", "image", ""}, + {"/", "", ""}, + {"image", "image", ""}, + } + + for _, test := range cases { + kind, subtype := splitMime(test.mime) + if test.kind != kind { + t.Fatalf("Invalid kind: %s", test.kind) + } + if test.subtype != subtype { + t.Fatalf("Invalid subtype: %s", test.subtype) + } + } +} diff --git a/vendor/gopkg.in/h2non/filetype.v1/types/type.go b/vendor/gopkg.in/h2non/filetype.v1/types/type.go new file mode 100644 index 0000000..5cf7dfc --- /dev/null +++ b/vendor/gopkg.in/h2non/filetype.v1/types/type.go @@ -0,0 +1,16 @@ +package types + +// Type represents a file MIME type and its extension +type Type struct { + MIME MIME + Extension string +} + +// NewType creates a new Type +func NewType(ext, mime string) Type { + t := Type{ + MIME: NewMIME(mime), + Extension: ext, + } + return Add(t) +} diff --git a/vendor/gopkg.in/h2non/filetype.v1/types/types.go b/vendor/gopkg.in/h2non/filetype.v1/types/types.go new file mode 100644 index 0000000..27d433e --- /dev/null +++ b/vendor/gopkg.in/h2non/filetype.v1/types/types.go @@ -0,0 +1,18 @@ +package types + +var Types = make(map[string]Type) + +// Add registers a new type in the package +func Add(t Type) Type { + Types[t.Extension] = t + return t +} + +// Get retrieves a Type by extension +func Get(ext string) Type { + kind := Types[ext] + if kind.Extension != "" { + return kind + } + return Unknown +} diff --git a/vendor/gopkg.in/h2non/filetype.v1/version.go b/vendor/gopkg.in/h2non/filetype.v1/version.go new file mode 100644 index 0000000..4ef1e52 --- /dev/null +++ b/vendor/gopkg.in/h2non/filetype.v1/version.go @@ -0,0 +1,4 @@ +package filetype + +// Version exposes the current package version. +const Version = "1.0.5"