summaryrefslogtreecommitdiff
path: root/vendor/github.com/h2non
diff options
context:
space:
mode:
authorLibravatar Tobi Smethurst <31960611+tsmethurst@users.noreply.github.com>2021-08-12 21:03:24 +0200
committerLibravatar GitHub <noreply@github.com>2021-08-12 21:03:24 +0200
commit98263a7de64269898a2f81207e38943b5c8e8653 (patch)
tree743c90f109a6c5d27832d1dcef2388d939f0f77a /vendor/github.com/h2non
parentText duplication fix (#137) (diff)
downloadgotosocial-98263a7de64269898a2f81207e38943b5c8e8653.tar.xz
Grand test fixup (#138)
* start fixing up tests * fix up tests + automate with drone * fiddle with linting * messing about with drone.yml * some more fiddling * hmmm * add cache * add vendor directory * verbose * ci updates * update some little things * update sig
Diffstat (limited to 'vendor/github.com/h2non')
-rw-r--r--vendor/github.com/h2non/filetype/.editorconfig12
-rw-r--r--vendor/github.com/h2non/filetype/.gitignore2
-rw-r--r--vendor/github.com/h2non/filetype/.travis.yml16
-rw-r--r--vendor/github.com/h2non/filetype/History.md148
-rw-r--r--vendor/github.com/h2non/filetype/LICENSE24
-rw-r--r--vendor/github.com/h2non/filetype/README.md292
-rw-r--r--vendor/github.com/h2non/filetype/filetype.go102
-rw-r--r--vendor/github.com/h2non/filetype/go.mod3
-rw-r--r--vendor/github.com/h2non/filetype/kind.go80
-rw-r--r--vendor/github.com/h2non/filetype/match.go90
-rw-r--r--vendor/github.com/h2non/filetype/matchers/application.go43
-rw-r--r--vendor/github.com/h2non/filetype/matchers/archive.go246
-rw-r--r--vendor/github.com/h2non/filetype/matchers/audio.go75
-rw-r--r--vendor/github.com/h2non/filetype/matchers/document.go197
-rw-r--r--vendor/github.com/h2non/filetype/matchers/font.go45
-rw-r--r--vendor/github.com/h2non/filetype/matchers/image.go143
-rw-r--r--vendor/github.com/h2non/filetype/matchers/isobmff/isobmff.go37
-rw-r--r--vendor/github.com/h2non/filetype/matchers/matchers.go51
-rw-r--r--vendor/github.com/h2non/filetype/matchers/video.go145
-rw-r--r--vendor/github.com/h2non/filetype/types/defaults.go4
-rw-r--r--vendor/github.com/h2non/filetype/types/mime.go14
-rw-r--r--vendor/github.com/h2non/filetype/types/split.go11
-rw-r--r--vendor/github.com/h2non/filetype/types/type.go16
-rw-r--r--vendor/github.com/h2non/filetype/types/types.go23
-rw-r--r--vendor/github.com/h2non/filetype/version.go4
25 files changed, 1823 insertions, 0 deletions
diff --git a/vendor/github.com/h2non/filetype/.editorconfig b/vendor/github.com/h2non/filetype/.editorconfig
new file mode 100644
index 000000000..000dc0a7a
--- /dev/null
+++ b/vendor/github.com/h2non/filetype/.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/github.com/h2non/filetype/.gitignore b/vendor/github.com/h2non/filetype/.gitignore
new file mode 100644
index 000000000..6fefe6cce
--- /dev/null
+++ b/vendor/github.com/h2non/filetype/.gitignore
@@ -0,0 +1,2 @@
+bin
+.DS_Store
diff --git a/vendor/github.com/h2non/filetype/.travis.yml b/vendor/github.com/h2non/filetype/.travis.yml
new file mode 100644
index 000000000..c9cdbc8da
--- /dev/null
+++ b/vendor/github.com/h2non/filetype/.travis.yml
@@ -0,0 +1,16 @@
+language: go
+arch:
+ - AMD64
+ - ppc64le
+go:
+ - "1.13"
+ - "1.14"
+
+before_install:
+ - go get -u -v golang.org/x/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/github.com/h2non/filetype/History.md b/vendor/github.com/h2non/filetype/History.md
new file mode 100644
index 000000000..ecace553e
--- /dev/null
+++ b/vendor/github.com/h2non/filetype/History.md
@@ -0,0 +1,148 @@
+
+v1.1.0 / 2020-06-06
+===================
+
+ * feat: version bump v1.10
+ * feat(ci): add go 1.14
+ * Merge pull request #82 from andrewstucki/sqlite-update
+ * Merge pull request #84 from evanoberholster/master
+ * Better differentiation: between image/x-canon-cr2 and image/tiff
+ * Merge pull request #1 from h2non/master
+ * Update ico filetype per https://www.iana.org/assignments/media-types/image/vnd.microsoft.icon
+ * Update rar filetype per https://www.iana.org/assignments/media-types/application/vnd.rar
+ * Update exe filetype per https://www.iana.org/assignments/media-types/application/vnd.microsoft.portable-executable
+ * Update deb filetype per https://www.iana.org/assignments/media-types/application/vnd.debian.binary-package
+ * Update sqlite filetype per https://www.iana.org/assignments/media-types/application/vnd.sqlite3
+ * Merge pull request #72 from turn88/master
+ * Update document.go
+ * Update document.go
+ * Update document.go
+ * add matchers for office 2003
+
+v1.0.10 / 2019-08-06
+====================
+
+ * Merge pull request #76 from lex-r/fix-matroska-detection
+ * fix: mkv and webm types detection
+
+v1.0.9 / 2019-07-25
+===================
+
+ * Merge pull request #75 from Trane9991/master
+ * add video/3gpp support
+ * fix: use proper iso file mime type
+ * feat: add iso image format
+ * Merge pull request #65 from Fentonz/master
+ * Merge pull request #70 from fanpei91/master
+ * add image/vnd.dwg to README
+ * add image/vnd.dwg support
+ * Added support for .iso files
+
+v1.0.8 / 2019-02-10
+===================
+
+ * refactor(images): heic -> heif
+ * feat(docs): add heif format
+ * Merge pull request #60 from rikonor/master
+ * add heif/heic support
+ * fix(docs): dicom -> dcm
+ * feat: add dicom type
+ * Merge pull request #58 from Fentonz/master
+ * Merge pull request #59 from kmanley/master
+ * fix example; related to h2non/filetype#43
+ * Added DICOM type to archive
+
+
+v1.0.7 / 2019-02-09
+===================
+
+ * Merge pull request #56 from akupila/wasm
+ * add wasm to readme
+ * detect wasm file type
+
+v1.0.6 / 2019-01-22
+===================
+
+ * Merge pull request #55 from ivanlemeshev/master
+ * Added ftypmp4v to MP4 matcher
+ * Merge pull request #54 from aofei/master
+ * chore: add support for Go modules
+ * feat: add support for AAC (audio/aac)
+ * Merge pull request #53 from lynxbyorion/check-for-docoments
+ * Added checks for documents.
+ * Merge pull request #51 from eriken/master
+ * fixed bad mime and import paths
+ * Merge pull request #50 from eriken/jpeg2000_support
+ * fix import paths
+ * jpeg2000 support
+ * Merge pull request #47 from Ma124/master
+ * Merge pull request #49 from amoore614/master
+ * more robust check for .mov files
+ * bugfix: reverse order of matcher key list so user registered matchers appear first
+ * bugfix: store ptr to MatcherKeys in case user registered matchers are used.
+ * update comment
+ * Bump buffer size to 8K to allow for more custom file matching
+ * refactor(readme): update package import path
+ * Merge pull request #48 from kumakichi/support_msooxml
+ * do not use v1
+ * ok, master already changed travis
+ * add fixtures, but MatchReader may not work for some msooxml files, 4096 bytes maybe not enough
+ * support ms ooxml, #40
+ * Fixed misspells
+ * fix(travis): use string notation for matrix items
+ * Merge pull request #42 from bruth/patch-2
+ * refactor(travis): remove Go 1.6, add Go 1.10
+ * Change maximum bytes required for detection
+ * Merge pull request #36 from yiiTT/patch-1
+ * Add MP4 dash and additional ISO formats
+ * Merge pull request #34 from RangelReale/fix-mp4-case
+ * Merge pull request #32 from yiiTT/fix-m4v
+ * Fixed mp4 detection case-sensitivity according to http://www.ftyps.com/
+ * Fix M4v matcher
+
+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/github.com/h2non/filetype/LICENSE b/vendor/github.com/h2non/filetype/LICENSE
new file mode 100644
index 000000000..30ede59b6
--- /dev/null
+++ b/vendor/github.com/h2non/filetype/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/github.com/h2non/filetype/README.md b/vendor/github.com/h2non/filetype/README.md
new file mode 100644
index 000000000..3ba06cb4e
--- /dev/null
+++ b/vendor/github.com/h2non/filetype/README.md
@@ -0,0 +1,292 @@
+# filetype [![Build Status](https://travis-ci.org/h2non/filetype.svg)](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. Python port: [filetype.py](https://github.com/h2non/filetype.py).
+
+## 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 262 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 github.com/h2non/filetype
+```
+
+## API
+
+See [Godoc](https://godoc.org/github.com/h2non/filetype) reference.
+
+### Subpackages
+
+- [`github.com/h2non/filetype/types`](https://godoc.org/github.com/h2non/filetype/types)
+- [`github.com/h2non/filetype/matchers`](https://godoc.org/github.com/h2non/filetype/matchers)
+
+## Examples
+
+#### Simple file type checking
+
+```go
+package main
+
+import (
+ "fmt"
+ "io/ioutil"
+
+ "github.com/h2non/filetype"
+)
+
+func main() {
+ buf, _ := ioutil.ReadFile("sample.jpg")
+
+ kind, _ := filetype.Match(buf)
+ if kind == filetype.Unknown {
+ fmt.Println("Unknown file type")
+ return
+ }
+
+ fmt.Printf("File type: %s. MIME: %s\n", kind.Extension, kind.MIME.Value)
+}
+```
+
+#### Check type class
+
+```go
+package main
+
+import (
+ "fmt"
+ "io/ioutil"
+
+ "github.com/h2non/filetype"
+)
+
+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"
+
+ "github.com/h2non/filetype"
+)
+
+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"
+ "io/ioutil"
+
+ "github.com/h2non/filetype"
+)
+
+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"
+
+ "github.com/h2non/filetype"
+)
+
+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`
+- **heif** - `image/heif`
+- **jxr** - `image/vnd.ms-photo`
+- **psd** - `image/vnd.adobe.photoshop`
+- **ico** - `image/vnd.microsoft.icon`
+- **dwg** - `image/vnd.dwg`
+
+#### 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`
+- **3gp** - `video/3gpp`
+
+#### Audio
+
+- **mid** - `audio/midi`
+- **mp3** - `audio/mpeg`
+- **m4a** - `audio/m4a`
+- **ogg** - `audio/ogg`
+- **flac** - `audio/x-flac`
+- **wav** - `audio/x-wav`
+- **amr** - `audio/amr`
+- **aac** - `audio/aac`
+
+#### Archive
+
+- **epub** - `application/epub+zip`
+- **zip** - `application/zip`
+- **tar** - `application/x-tar`
+- **rar** - `application/vnd.rar`
+- **gz** - `application/gzip`
+- **bz2** - `application/x-bzip2`
+- **7z** - `application/x-7z-compressed`
+- **xz** - `application/x-xz`
+- **pdf** - `application/pdf`
+- **exe** - `application/vnd.microsoft.portable-executable`
+- **swf** - `application/x-shockwave-flash`
+- **rtf** - `application/rtf`
+- **iso** - `application/x-iso9660-image`
+- **eot** - `application/octet-stream`
+- **ps** - `application/postscript`
+- **sqlite** - `application/vnd.sqlite3`
+- **nes** - `application/x-nintendo-nes-rom`
+- **crx** - `application/x-google-chrome-extension`
+- **cab** - `application/vnd.ms-cab-compressed`
+- **deb** - `application/vnd.debian.binary-package`
+- **ar** - `application/x-unix-archive`
+- **Z** - `application/x-compress`
+- **lz** - `application/x-lzip`
+- **rpm** - `application/x-rpm`
+- **elf** - `application/x-executable`
+- **dcm** - `application/dicom`
+
+#### 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`
+
+#### Application
+
+- **wasm** - `application/wasm`
+- **dex** - `application/vnd.android.dex`
+- **dey** - `application/vnd.android.dey`
+
+## 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/github.com/h2non/filetype/filetype.go b/vendor/github.com/h2non/filetype/filetype.go
new file mode 100644
index 000000000..c99691e5f
--- /dev/null
+++ b/vendor/github.com/h2non/filetype/filetype.go
@@ -0,0 +1,102 @@
+package filetype
+
+import (
+ "errors"
+
+ "github.com/h2non/filetype/matchers"
+ "github.com/h2non/filetype/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 := types.Get(ext)
+ if kind != types.Unknown {
+ 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 {
+ result := false
+ types.Types.Range(func(k, v interface{}) bool {
+ kind := v.(types.Type)
+ if kind.MIME.Value == mime {
+ matcher := matchers.Matchers[kind]
+ result = matcher(buf) != types.Unknown
+ return false
+ }
+ return true
+ })
+
+ return result
+}
+
+// IsSupported checks if a given file extension is supported
+func IsSupported(ext string) bool {
+ result := false
+ types.Types.Range(func(k, v interface{}) bool {
+ key := k.(string)
+ if key == ext {
+ result = true
+ return false
+ }
+ return true
+ })
+
+ return result
+}
+
+// IsMIMESupported checks if a given MIME type is supported
+func IsMIMESupported(mime string) bool {
+ result := false
+ types.Types.Range(func(k, v interface{}) bool {
+ kind := v.(types.Type)
+ if kind.MIME.Value == mime {
+ result = true
+ return false
+ }
+ return true
+ })
+
+ return result
+}
+
+// GetType retrieves a Type by file extension
+func GetType(ext string) types.Type {
+ return types.Get(ext)
+}
diff --git a/vendor/github.com/h2non/filetype/go.mod b/vendor/github.com/h2non/filetype/go.mod
new file mode 100644
index 000000000..071ea7320
--- /dev/null
+++ b/vendor/github.com/h2non/filetype/go.mod
@@ -0,0 +1,3 @@
+module github.com/h2non/filetype
+
+go 1.13
diff --git a/vendor/github.com/h2non/filetype/kind.go b/vendor/github.com/h2non/filetype/kind.go
new file mode 100644
index 000000000..de8473507
--- /dev/null
+++ b/vendor/github.com/h2non/filetype/kind.go
@@ -0,0 +1,80 @@
+package filetype
+
+import (
+ "github.com/h2non/filetype/matchers"
+ "github.com/h2non/filetype/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
+}
+
+// Document tries to match a file as document type
+func Document(buf []byte) (types.Type, error) {
+ return doMatchMap(buf, matchers.Document)
+}
+
+// IsDocument checks if the given buffer is an document type
+func IsDocument(buf []byte) bool {
+ kind, _ := Document(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/github.com/h2non/filetype/match.go b/vendor/github.com/h2non/filetype/match.go
new file mode 100644
index 000000000..82cf80468
--- /dev/null
+++ b/vendor/github.com/h2non/filetype/match.go
@@ -0,0 +1,90 @@
+package filetype
+
+import (
+ "io"
+ "os"
+
+ "github.com/h2non/filetype/matchers"
+ "github.com/h2non/filetype/types"
+)
+
+// Matchers is an alias to matchers.Matchers
+var Matchers = matchers.Matchers
+
+// MatcherKeys is an alias to matchers.MatcherKeys
+var MatcherKeys = &matchers.MatcherKeys
+
+// 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 _, kind := range *MatcherKeys {
+ checker := Matchers[kind]
+ 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, 8192) // 8K makes msooxml tests happy and allows for expanded custom file checks
+
+ _, 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 against 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 against a map of match functions
+func MatchesMap(buf []byte, matchers matchers.Map) bool {
+ return MatchMap(buf, matchers) != types.Unknown
+}
diff --git a/vendor/github.com/h2non/filetype/matchers/application.go b/vendor/github.com/h2non/filetype/matchers/application.go
new file mode 100644
index 000000000..67fdab3d8
--- /dev/null
+++ b/vendor/github.com/h2non/filetype/matchers/application.go
@@ -0,0 +1,43 @@
+package matchers
+
+var (
+ TypeWasm = newType("wasm", "application/wasm")
+ TypeDex = newType("dex", "application/vnd.android.dex")
+ TypeDey = newType("dey", "application/vnd.android.dey")
+)
+
+var Application = Map{
+ TypeWasm: Wasm,
+ TypeDex: Dex,
+ TypeDey: Dey,
+}
+
+// Wasm detects a Web Assembly 1.0 filetype.
+func Wasm(buf []byte) bool {
+ // WASM has starts with `\0asm`, followed by the version.
+ // http://webassembly.github.io/spec/core/binary/modules.html#binary-magic
+ return len(buf) >= 8 &&
+ buf[0] == 0x00 && buf[1] == 0x61 &&
+ buf[2] == 0x73 && buf[3] == 0x6D &&
+ buf[4] == 0x01 && buf[5] == 0x00 &&
+ buf[6] == 0x00 && buf[7] == 0x00
+}
+
+// Dex detects dalvik executable(DEX)
+func Dex(buf []byte) bool {
+ // https://source.android.com/devices/tech/dalvik/dex-format#dex-file-magic
+ return len(buf) > 36 &&
+ // magic
+ buf[0] == 0x64 && buf[1] == 0x65 && buf[2] == 0x78 && buf[3] == 0x0A &&
+ // file sise
+ buf[36] == 0x70
+}
+
+// Dey Optimized Dalvik Executable(ODEX)
+func Dey(buf []byte) bool {
+ return len(buf) > 100 &&
+ // dey magic
+ buf[0] == 0x64 && buf[1] == 0x65 && buf[2] == 0x79 && buf[3] == 0x0A &&
+ // dex
+ Dex(buf[40:100])
+}
diff --git a/vendor/github.com/h2non/filetype/matchers/archive.go b/vendor/github.com/h2non/filetype/matchers/archive.go
new file mode 100644
index 000000000..1cef8f5b5
--- /dev/null
+++ b/vendor/github.com/h2non/filetype/matchers/archive.go
@@ -0,0 +1,246 @@
+package matchers
+
+var (
+ TypeEpub = newType("epub", "application/epub+zip")
+ TypeZip = newType("zip", "application/zip")
+ TypeTar = newType("tar", "application/x-tar")
+ TypeRar = newType("rar", "application/vnd.rar")
+ 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/vnd.microsoft.portable-executable")
+ 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/vnd.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/vnd.debian.binary-package")
+ 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")
+ TypeDcm = newType("dcm", "application/dicom")
+ TypeIso = newType("iso", "application/x-iso9660-image")
+ TypeMachO = newType("macho", "application/x-mach-binary") // Mach-O binaries have no common extension.
+)
+
+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,
+ TypeDcm: Dcm,
+ TypeIso: Iso,
+ TypeMachO: MachO,
+}
+
+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
+}
+
+func Dcm(buf []byte) bool {
+ return len(buf) > 131 &&
+ buf[128] == 0x44 && buf[129] == 0x49 &&
+ buf[130] == 0x43 && buf[131] == 0x4D
+}
+
+func Iso(buf []byte) bool {
+ return len(buf) > 32773 &&
+ buf[32769] == 0x43 && buf[32770] == 0x44 &&
+ buf[32771] == 0x30 && buf[32772] == 0x30 &&
+ buf[32773] == 0x31
+}
+
+func MachO(buf []byte) bool {
+ return len(buf) > 3 && ((buf[0] == 0xFE && buf[1] == 0xED && buf[2] == 0xFA && buf[3] == 0xCF) ||
+ (buf[0] == 0xFE && buf[1] == 0xED && buf[2] == 0xFA && buf[3] == 0xCE) ||
+ (buf[0] == 0xBE && buf[1] == 0xBA && buf[2] == 0xFE && buf[3] == 0xCA) ||
+ // Big endian versions below here...
+ (buf[0] == 0xCF && buf[1] == 0xFA && buf[2] == 0xED && buf[3] == 0xFE) ||
+ (buf[0] == 0xCE && buf[1] == 0xFA && buf[2] == 0xED && buf[3] == 0xFE) ||
+ (buf[0] == 0xCA && buf[1] == 0xFE && buf[2] == 0xBA && buf[3] == 0xBE))
+}
diff --git a/vendor/github.com/h2non/filetype/matchers/audio.go b/vendor/github.com/h2non/filetype/matchers/audio.go
new file mode 100644
index 000000000..6d532630a
--- /dev/null
+++ b/vendor/github.com/h2non/filetype/matchers/audio.go
@@ -0,0 +1,75 @@
+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")
+ TypeAac = newType("aac", "audio/aac")
+)
+
+var Audio = Map{
+ TypeMidi: Midi,
+ TypeMp3: Mp3,
+ TypeM4a: M4a,
+ TypeOgg: Ogg,
+ TypeFlac: Flac,
+ TypeWav: Wav,
+ TypeAmr: Amr,
+ TypeAac: Aac,
+}
+
+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
+}
+
+func Aac(buf []byte) bool {
+ return len(buf) > 1 &&
+ ((buf[0] == 0xFF && buf[1] == 0xF1) ||
+ (buf[0] == 0xFF && buf[1] == 0xF9))
+}
diff --git a/vendor/github.com/h2non/filetype/matchers/document.go b/vendor/github.com/h2non/filetype/matchers/document.go
new file mode 100644
index 000000000..b898c0ff7
--- /dev/null
+++ b/vendor/github.com/h2non/filetype/matchers/document.go
@@ -0,0 +1,197 @@
+package matchers
+
+import (
+ "bytes"
+ "encoding/binary"
+)
+
+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,
+}
+
+type docType int
+
+const (
+ TYPE_DOC docType = iota
+ TYPE_DOCX
+ TYPE_XLS
+ TYPE_XLSX
+ TYPE_PPT
+ TYPE_PPTX
+ TYPE_OOXML
+)
+
+//reference: https://bz.apache.org/ooo/show_bug.cgi?id=111457
+func Doc(buf []byte) bool {
+ if len(buf) > 513 {
+ return buf[0] == 0xD0 && buf[1] == 0xCF &&
+ buf[2] == 0x11 && buf[3] == 0xE0 &&
+ buf[512] == 0xEC && buf[513] == 0xA5
+ } else {
+ return len(buf) > 3 &&
+ buf[0] == 0xD0 && buf[1] == 0xCF &&
+ buf[2] == 0x11 && buf[3] == 0xE0
+ }
+}
+
+func Docx(buf []byte) bool {
+ typ, ok := msooxml(buf)
+ return ok && typ == TYPE_DOCX
+}
+
+func Xls(buf []byte) bool {
+ if len(buf) > 513 {
+ return buf[0] == 0xD0 && buf[1] == 0xCF &&
+ buf[2] == 0x11 && buf[3] == 0xE0 &&
+ buf[512] == 0x09 && buf[513] == 0x08
+ } else {
+ return len(buf) > 3 &&
+ buf[0] == 0xD0 && buf[1] == 0xCF &&
+ buf[2] == 0x11 && buf[3] == 0xE0
+ }
+}
+
+func Xlsx(buf []byte) bool {
+ typ, ok := msooxml(buf)
+ return ok && typ == TYPE_XLSX
+}
+
+func Ppt(buf []byte) bool {
+ if len(buf) > 513 {
+ return buf[0] == 0xD0 && buf[1] == 0xCF &&
+ buf[2] == 0x11 && buf[3] == 0xE0 &&
+ buf[512] == 0xA0 && buf[513] == 0x46
+ } else {
+ return len(buf) > 3 &&
+ buf[0] == 0xD0 && buf[1] == 0xCF &&
+ buf[2] == 0x11 && buf[3] == 0xE0
+ }
+}
+
+func Pptx(buf []byte) bool {
+ typ, ok := msooxml(buf)
+ return ok && typ == TYPE_PPTX
+}
+
+func msooxml(buf []byte) (typ docType, found bool) {
+ signature := []byte{'P', 'K', 0x03, 0x04}
+
+ // start by checking for ZIP local file header signature
+ if ok := compareBytes(buf, signature, 0); !ok {
+ return
+ }
+
+ // make sure the first file is correct
+ if v, ok := checkMSOoml(buf, 0x1E); ok {
+ return v, ok
+ }
+
+ if !compareBytes(buf, []byte("[Content_Types].xml"), 0x1E) &&
+ !compareBytes(buf, []byte("_rels/.rels"), 0x1E) &&
+ !compareBytes(buf, []byte("docProps"), 0x1E) {
+ return
+ }
+
+ // skip to the second local file header
+ // since some documents include a 520-byte extra field following the file
+ // header, we need to scan for the next header
+ startOffset := int(binary.LittleEndian.Uint32(buf[18:22]) + 49)
+ idx := search(buf, startOffset, 6000)
+ if idx == -1 {
+ return
+ }
+
+ // now skip to the *third* local file header; again, we need to scan due to a
+ // 520-byte extra field following the file header
+ startOffset += idx + 4 + 26
+ idx = search(buf, startOffset, 6000)
+ if idx == -1 {
+ return
+ }
+
+ // and check the subdirectory name to determine which type of OOXML
+ // file we have. Correct the mimetype with the registered ones:
+ // http://technet.microsoft.com/en-us/library/cc179224.aspx
+ startOffset += idx + 4 + 26
+ if typ, ok := checkMSOoml(buf, startOffset); ok {
+ return typ, ok
+ }
+
+ // OpenOffice/Libreoffice orders ZIP entry differently, so check the 4th file
+ startOffset += 26
+ idx = search(buf, startOffset, 6000)
+ if idx == -1 {
+ return TYPE_OOXML, true
+ }
+
+ startOffset += idx + 4 + 26
+ if typ, ok := checkMSOoml(buf, startOffset); ok {
+ return typ, ok
+ } else {
+ return TYPE_OOXML, true
+ }
+}
+
+func compareBytes(slice, subSlice []byte, startOffset int) bool {
+ sl := len(subSlice)
+
+ if startOffset+sl > len(slice) {
+ return false
+ }
+
+ s := slice[startOffset : startOffset+sl]
+ for i := range s {
+ if subSlice[i] != s[i] {
+ return false
+ }
+ }
+
+ return true
+}
+
+func checkMSOoml(buf []byte, offset int) (typ docType, ok bool) {
+ ok = true
+
+ switch {
+ case compareBytes(buf, []byte("word/"), offset):
+ typ = TYPE_DOCX
+ case compareBytes(buf, []byte("ppt/"), offset):
+ typ = TYPE_PPTX
+ case compareBytes(buf, []byte("xl/"), offset):
+ typ = TYPE_XLSX
+ default:
+ ok = false
+ }
+
+ return
+}
+
+func search(buf []byte, start, rangeNum int) int {
+ length := len(buf)
+ end := start + rangeNum
+ signature := []byte{'P', 'K', 0x03, 0x04}
+
+ if end > length {
+ end = length
+ }
+
+ if start >= end {
+ return -1
+ }
+
+ return bytes.Index(buf[start:end], signature)
+}
diff --git a/vendor/github.com/h2non/filetype/matchers/font.go b/vendor/github.com/h2non/filetype/matchers/font.go
new file mode 100644
index 000000000..f39171675
--- /dev/null
+++ b/vendor/github.com/h2non/filetype/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/github.com/h2non/filetype/matchers/image.go b/vendor/github.com/h2non/filetype/matchers/image.go
new file mode 100644
index 000000000..0465d0d68
--- /dev/null
+++ b/vendor/github.com/h2non/filetype/matchers/image.go
@@ -0,0 +1,143 @@
+package matchers
+
+import "github.com/h2non/filetype/matchers/isobmff"
+
+var (
+ TypeJpeg = newType("jpg", "image/jpeg")
+ TypeJpeg2000 = newType("jp2", "image/jp2")
+ 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/vnd.microsoft.icon")
+ TypeHeif = newType("heif", "image/heif")
+ TypeDwg = newType("dwg", "image/vnd.dwg")
+)
+
+var Image = Map{
+ TypeJpeg: Jpeg,
+ TypeJpeg2000: Jpeg2000,
+ TypePng: Png,
+ TypeGif: Gif,
+ TypeWebp: Webp,
+ TypeCR2: CR2,
+ TypeTiff: Tiff,
+ TypeBmp: Bmp,
+ TypeJxr: Jxr,
+ TypePsd: Psd,
+ TypeIco: Ico,
+ TypeHeif: Heif,
+ TypeDwg: Dwg,
+}
+
+func Jpeg(buf []byte) bool {
+ return len(buf) > 2 &&
+ buf[0] == 0xFF &&
+ buf[1] == 0xD8 &&
+ buf[2] == 0xFF
+}
+
+func Jpeg2000(buf []byte) bool {
+ return len(buf) > 12 &&
+ buf[0] == 0x0 &&
+ buf[1] == 0x0 &&
+ buf[2] == 0x0 &&
+ buf[3] == 0xC &&
+ buf[4] == 0x6A &&
+ buf[5] == 0x50 &&
+ buf[6] == 0x20 &&
+ buf[7] == 0x20 &&
+ buf[8] == 0xD &&
+ buf[9] == 0xA &&
+ buf[10] == 0x87 &&
+ buf[11] == 0xA &&
+ buf[12] == 0x0
+}
+
+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) > 10 &&
+ ((buf[0] == 0x49 && buf[1] == 0x49 && buf[2] == 0x2A && buf[3] == 0x0) || // Little Endian
+ (buf[0] == 0x4D && buf[1] == 0x4D && buf[2] == 0x0 && buf[3] == 0x2A)) && // Big Endian
+ buf[8] == 0x43 && buf[9] == 0x52 && // CR2 magic word
+ buf[10] == 0x02 // CR2 major version
+}
+
+func Tiff(buf []byte) bool {
+ return len(buf) > 10 &&
+ ((buf[0] == 0x49 && buf[1] == 0x49 && buf[2] == 0x2A && buf[3] == 0x0) || // Little Endian
+ (buf[0] == 0x4D && buf[1] == 0x4D && buf[2] == 0x0 && buf[3] == 0x2A)) && // Big Endian
+ !CR2(buf) // To avoid conflicts differentiate Tiff from CR2
+}
+
+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
+}
+
+func Heif(buf []byte) bool {
+ if !isobmff.IsISOBMFF(buf) {
+ return false
+ }
+
+ majorBrand, _, compatibleBrands := isobmff.GetFtyp(buf)
+ if majorBrand == "heic" {
+ return true
+ }
+
+ if majorBrand == "mif1" || majorBrand == "msf1" {
+ for _, compatibleBrand := range compatibleBrands {
+ if compatibleBrand == "heic" {
+ return true
+ }
+ }
+ }
+
+ return false
+}
+
+func Dwg(buf []byte) bool {
+ return len(buf) > 3 &&
+ buf[0] == 0x41 && buf[1] == 0x43 &&
+ buf[2] == 0x31 && buf[3] == 0x30
+}
diff --git a/vendor/github.com/h2non/filetype/matchers/isobmff/isobmff.go b/vendor/github.com/h2non/filetype/matchers/isobmff/isobmff.go
new file mode 100644
index 000000000..b3e39bf59
--- /dev/null
+++ b/vendor/github.com/h2non/filetype/matchers/isobmff/isobmff.go
@@ -0,0 +1,37 @@
+package isobmff
+
+import "encoding/binary"
+
+// IsISOBMFF checks whether the given buffer represents ISO Base Media File Format data
+func IsISOBMFF(buf []byte) bool {
+ if len(buf) < 16 || string(buf[4:8]) != "ftyp" {
+ return false
+ }
+
+ if ftypLength := binary.BigEndian.Uint32(buf[0:4]); len(buf) < int(ftypLength) {
+ return false
+ }
+
+ return true
+}
+
+// GetFtyp returns the major brand, minor version and compatible brands of the ISO-BMFF data
+func GetFtyp(buf []byte) (string, string, []string) {
+ if len(buf) < 17 {
+ return "", "", []string{""}
+ }
+
+ ftypLength := binary.BigEndian.Uint32(buf[0:4])
+
+ majorBrand := string(buf[8:12])
+ minorVersion := string(buf[12:16])
+
+ compatibleBrands := []string{}
+ for i := 16; i < int(ftypLength); i += 4 {
+ if len(buf) >= (i + 4) {
+ compatibleBrands = append(compatibleBrands, string(buf[i:i+4]))
+ }
+ }
+
+ return majorBrand, minorVersion, compatibleBrands
+}
diff --git a/vendor/github.com/h2non/filetype/matchers/matchers.go b/vendor/github.com/h2non/filetype/matchers/matchers.go
new file mode 100644
index 000000000..20d74d080
--- /dev/null
+++ b/vendor/github.com/h2non/filetype/matchers/matchers.go
@@ -0,0 +1,51 @@
+package matchers
+
+import (
+ "github.com/h2non/filetype/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)
+var MatcherKeys []types.Type
+
+// 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
+ // prepend here so any user defined matchers get added first
+ MatcherKeys = append([]types.Type{kind}, MatcherKeys...)
+ return matcher
+}
+
+func register(matchers ...Map) {
+ MatcherKeys = MatcherKeys[:0]
+ for _, m := range matchers {
+ for kind, matcher := range m {
+ NewMatcher(kind, matcher)
+ }
+ }
+}
+
+func init() {
+ // Arguments order is intentional
+ // Archive files will be checked last due to prepend above in func NewMatcher
+ register(Archive, Document, Font, Audio, Video, Image, Application)
+}
diff --git a/vendor/github.com/h2non/filetype/matchers/video.go b/vendor/github.com/h2non/filetype/matchers/video.go
new file mode 100644
index 000000000..e97cf28a1
--- /dev/null
+++ b/vendor/github.com/h2non/filetype/matchers/video.go
@@ -0,0 +1,145 @@
+package matchers
+
+import "bytes"
+
+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")
+ Type3gp = newType("3gp", "video/3gpp")
+)
+
+var Video = Map{
+ TypeMp4: Mp4,
+ TypeM4v: M4v,
+ TypeMkv: Mkv,
+ TypeWebm: Webm,
+ TypeMov: Mov,
+ TypeAvi: Avi,
+ TypeWmv: Wmv,
+ TypeMpeg: Mpeg,
+ TypeFlv: Flv,
+ Type3gp: Match3gp,
+}
+
+func M4v(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] == 0x56
+}
+
+func Mkv(buf []byte) bool {
+ return len(buf) > 3 &&
+ buf[0] == 0x1A && buf[1] == 0x45 &&
+ buf[2] == 0xDF && buf[3] == 0xA3 &&
+ containsMatroskaSignature(buf, []byte{'m', 'a', 't', 'r', 'o', 's', 'k', 'a'})
+}
+
+func Webm(buf []byte) bool {
+ return len(buf) > 3 &&
+ buf[0] == 0x1A && buf[1] == 0x45 &&
+ buf[2] == 0xDF && buf[3] == 0xA3 &&
+ containsMatroskaSignature(buf, []byte{'w', 'e', 'b', 'm'})
+}
+
+func Mov(buf []byte) bool {
+ return len(buf) > 15 && ((buf[0] == 0x0 && buf[1] == 0x0 &&
+ buf[2] == 0x0 && buf[3] == 0x14 &&
+ buf[4] == 0x66 && buf[5] == 0x74 &&
+ buf[6] == 0x79 && buf[7] == 0x70) ||
+ (buf[4] == 0x6d && buf[5] == 0x6f && buf[6] == 0x6f && buf[7] == 0x76) ||
+ (buf[4] == 0x6d && buf[5] == 0x64 && buf[6] == 0x61 && buf[7] == 0x74) ||
+ (buf[12] == 0x6d && buf[13] == 0x64 && buf[14] == 0x61 && buf[15] == 0x74))
+}
+
+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] == 'd' && buf[9] == 'a' && buf[10] == 's' && buf[11] == 'h') ||
+ (buf[8] == 'i' && buf[9] == 's' && buf[10] == 'o' && buf[11] == '2') ||
+ (buf[8] == 'i' && buf[9] == 's' && buf[10] == 'o' && buf[11] == '3') ||
+ (buf[8] == 'i' && buf[9] == 's' && buf[10] == 'o' && buf[11] == '4') ||
+ (buf[8] == 'i' && buf[9] == 's' && buf[10] == 'o' && buf[11] == '5') ||
+ (buf[8] == 'i' && buf[9] == 's' && buf[10] == 'o' && buf[11] == '6') ||
+ (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] == '4' && buf[11] == 'v') ||
+ (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] == 'S' && buf[10] == 'D' && 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') ||
+ (buf[8] == 'F' && buf[9] == '4' && buf[10] == 'V' && buf[11] == ' ') ||
+ (buf[8] == 'F' && buf[9] == '4' && buf[10] == 'P' && buf[11] == ' '))
+}
+
+func Match3gp(buf []byte) bool {
+ return len(buf) > 10 &&
+ buf[4] == 0x66 && buf[5] == 0x74 && buf[6] == 0x79 &&
+ buf[7] == 0x70 && buf[8] == 0x33 && buf[9] == 0x67 &&
+ buf[10] == 0x70
+}
+
+func containsMatroskaSignature(buf, subType []byte) bool {
+ limit := 4096
+ if len(buf) < limit {
+ limit = len(buf)
+ }
+
+ index := bytes.Index(buf[:limit], subType)
+ if index < 3 {
+ return false
+ }
+
+ return buf[index-3] == 0x42 && buf[index-2] == 0x82
+}
diff --git a/vendor/github.com/h2non/filetype/types/defaults.go b/vendor/github.com/h2non/filetype/types/defaults.go
new file mode 100644
index 000000000..0d985a05d
--- /dev/null
+++ b/vendor/github.com/h2non/filetype/types/defaults.go
@@ -0,0 +1,4 @@
+package types
+
+// Unknown default type
+var Unknown = NewType("unknown", "")
diff --git a/vendor/github.com/h2non/filetype/types/mime.go b/vendor/github.com/h2non/filetype/types/mime.go
new file mode 100644
index 000000000..fe8ea822e
--- /dev/null
+++ b/vendor/github.com/h2non/filetype/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/github.com/h2non/filetype/types/split.go b/vendor/github.com/h2non/filetype/types/split.go
new file mode 100644
index 000000000..68a5a8b3b
--- /dev/null
+++ b/vendor/github.com/h2non/filetype/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/github.com/h2non/filetype/types/type.go b/vendor/github.com/h2non/filetype/types/type.go
new file mode 100644
index 000000000..5cf7dfc4b
--- /dev/null
+++ b/vendor/github.com/h2non/filetype/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/github.com/h2non/filetype/types/types.go b/vendor/github.com/h2non/filetype/types/types.go
new file mode 100644
index 000000000..f59e256f0
--- /dev/null
+++ b/vendor/github.com/h2non/filetype/types/types.go
@@ -0,0 +1,23 @@
+package types
+
+import "sync"
+
+// Types Support concurrent map writes
+var Types sync.Map
+
+// Add registers a new type in the package
+func Add(t Type) Type {
+ Types.Store(t.Extension, t)
+ return t
+}
+
+// Get retrieves a Type by extension
+func Get(ext string) Type {
+ if tmp, ok := Types.Load(ext); ok {
+ kind := tmp.(Type)
+ if kind.Extension != "" {
+ return kind
+ }
+ }
+ return Unknown
+}
diff --git a/vendor/github.com/h2non/filetype/version.go b/vendor/github.com/h2non/filetype/version.go
new file mode 100644
index 000000000..116e4c78e
--- /dev/null
+++ b/vendor/github.com/h2non/filetype/version.go
@@ -0,0 +1,4 @@
+package filetype
+
+// Version exposes the current package version.
+const Version = "1.1.1"