pax_global_header00006660000000000000000000000064133601560710014514gustar00rootroot0000000000000052 comment=06ccb9c7b3570544930d826f22561c3facd1deda go-magic-1.0.0/000077500000000000000000000000001336015607100131755ustar00rootroot00000000000000go-magic-1.0.0/LICENSE000066400000000000000000000027401336015607100142050ustar00rootroot00000000000000Copyright (c) 2014, Vimeo, LLC. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of Vimeo, LLC. go-magic-1.0.0/README.md000066400000000000000000000014441336015607100144570ustar00rootroot00000000000000# go-magic # ## Go library for getting MIME type using libmagic ## ### Installing ### ``` go get github.com/vimeo/go-magic/magic ``` ### Dependencies ### **libmagic**
*URL*: [http://www.darwinsys.com/file/](http://www.darwinsys.com/file/)
*Ubuntu*: `apt-get install libmagic-dev`
*CentOS*: `yum install file-devel`
### Usage ### - Create some custom magic files (e.g. ~/magicfiles) - Add the default system magic file dir - magic.AddMagicDir(magic.GetDefaultDir()) - Add the custom magic file dir - magic.AddMagicDir("~/magicfiles") - Get MIME type with either one of: - magic.MimeFromFile(filename) - magic.MimeFromBytes(data) ### API Documentation ### [http://godoc.org/github.com/vimeo/go-magic/magic](http://godoc.org/github.com/vimeo/go-magic/magic) go-magic-1.0.0/go.mod000066400000000000000000000000411336015607100142760ustar00rootroot00000000000000module github.com/vimeo/go-magic go-magic-1.0.0/magic/000077500000000000000000000000001336015607100142555ustar00rootroot00000000000000go-magic-1.0.0/magic/magic.go000066400000000000000000000067101336015607100156700ustar00rootroot00000000000000package magic /* #cgo LDFLAGS: -lmagic #include #include */ import "C" import ( "os" "path" "unsafe" ) const ( MAGIC_NONE = C.MAGIC_NONE MAGIC_DEBUG = C.MAGIC_DEBUG MAGIC_SYMLINK = C.MAGIC_SYMLINK MAGIC_COMPRESS = C.MAGIC_COMPRESS MAGIC_DEVICES = C.MAGIC_DEVICES MAGIC_MIME_TYPE = C.MAGIC_MIME_TYPE MAGIC_CONTINUE = C.MAGIC_CONTINUE MAGIC_CHECK = C.MAGIC_CHECK MAGIC_PRESERVE_ATIME = C.MAGIC_PRESERVE_ATIME MAGIC_RAW = C.MAGIC_RAW MAGIC_ERROR = C.MAGIC_ERROR MAGIC_MIME_ENCODING = C.MAGIC_MIME_ENCODING MAGIC_MIME = C.MAGIC_MIME MAGIC_APPLE = C.MAGIC_APPLE MAGIC_NO_CHECK_COMPRESS = C.MAGIC_NO_CHECK_COMPRESS MAGIC_NO_CHECK_TAR = C.MAGIC_NO_CHECK_TAR MAGIC_NO_CHECK_SOFT = C.MAGIC_NO_CHECK_SOFT MAGIC_NO_CHECK_APPTYPE = C.MAGIC_NO_CHECK_APPTYPE MAGIC_NO_CHECK_ELF = C.MAGIC_NO_CHECK_ELF MAGIC_NO_CHECK_TEXT = C.MAGIC_NO_CHECK_TEXT MAGIC_NO_CHECK_CDF = C.MAGIC_NO_CHECK_CDF MAGIC_NO_CHECK_TOKENS = C.MAGIC_NO_CHECK_TOKENS MAGIC_NO_CHECK_ENCODING = C.MAGIC_NO_CHECK_ENCODING MAGIC_NO_CHECK_ASCII = C.MAGIC_NO_CHECK_ASCII MAGIC_NO_CHECK_FORTRAN = C.MAGIC_NO_CHECK_FORTRAN MAGIC_NO_CHECK_TROFF = C.MAGIC_NO_CHECK_TROFF ) const ( MAGIC_NO_CHECK_BUILTIN = MAGIC_NO_CHECK_COMPRESS | MAGIC_NO_CHECK_TAR | MAGIC_NO_CHECK_APPTYPE | MAGIC_NO_CHECK_ELF | MAGIC_NO_CHECK_TEXT | MAGIC_NO_CHECK_CDF | MAGIC_NO_CHECK_TOKENS | MAGIC_NO_CHECK_ENCODING ) type Magic C.magic_t var system_mgc_locations = []string{ "/usr/share/misc/magic.mgc", "/usr/share/file/magic.mgc", "/usr/share/magic/magic.mgc", } /* Find the real magic file location */ func GetDefaultDir() string { var f string found_mgc := false for _, f = range system_mgc_locations { fi, err := os.Lstat(f) if err == nil && fi.Mode()&os.ModeSymlink != os.ModeSymlink { found_mgc = true break } } if found_mgc { return path.Dir(f) } else { return "" } } func Open(flags int) Magic { cookie := (Magic)(C.magic_open(C.int(flags))) return cookie } func Close(cookie Magic) { C.magic_close((C.magic_t)(cookie)) } func Error(cookie Magic) string { s := (C.magic_error((C.magic_t)(cookie))) return C.GoString(s) } func Errno(cookie Magic) int { return (int)(C.magic_errno((C.magic_t)(cookie))) } func File(cookie Magic, filename string) string { cfilename := C.CString(filename) defer C.free(unsafe.Pointer(cfilename)) return C.GoString(C.magic_file((C.magic_t)(cookie), cfilename)) } func Buffer(cookie Magic, b []byte) string { length := C.size_t(len(b)) return C.GoString(C.magic_buffer((C.magic_t)(cookie), unsafe.Pointer(&b[0]), length)) } func SetFlags(cookie Magic, flags int) int { return (int)(C.magic_setflags((C.magic_t)(cookie), C.int(flags))) } func Check(cookie Magic, filename string) int { cfilename := C.CString(filename) defer C.free(unsafe.Pointer(cfilename)) return (int)(C.magic_check((C.magic_t)(cookie), cfilename)) } func Compile(cookie Magic, filename string) int { cfilename := C.CString(filename) defer C.free(unsafe.Pointer(cfilename)) return (int)(C.magic_compile((C.magic_t)(cookie), cfilename)) } func Load(cookie Magic, filename string) int { if filename == "" { return (int)(C.magic_load((C.magic_t)(cookie), nil)) } cfilename := C.CString(filename) defer C.free(unsafe.Pointer(cfilename)) return (int)(C.magic_load((C.magic_t)(cookie), cfilename)) } go-magic-1.0.0/magic/mime.go000066400000000000000000000047061336015607100155420ustar00rootroot00000000000000package magic import ( "fmt" "io/ioutil" "os" "path/filepath" "strings" "sync" ) var magicFiles map[string]bool var mutex sync.Mutex func init() { magicFiles = make(map[string]bool) } func compileToMgc(file string) { cookie := Open(MAGIC_NONE) defer Close(cookie) Compile(cookie, file) } func compileMagicFiles(dir string, files []string) { // for some reason libmagic puts compiled files in the current working dir // instead of the dir of the source file, so switch to the source dir, // compile, then switch back pwd, err := os.Getwd() if err != nil { return } err = os.Chdir(dir) if err != nil { return } defer os.Chdir(pwd) for _, f := range files { compileToMgc(f) } } /* Add a directory for libmagic to search for .mgc databases. */ func AddMagicDir(dir string) error { var err error dir, err = filepath.Abs(dir) if err != nil { return err } fi, err := os.Stat(dir) if err != nil { return err } if fi.IsDir() == false { return fmt.Errorf("Not a directory: %s", dir) } // get list of .magic files that need to be compiled to .mgc var srcFiles []string files, err := ioutil.ReadDir(dir) if err != nil { return err } for _, fi = range files { if filepath.Ext(fi.Name()) == ".magic" { mgcSrc := filepath.Join(dir, fi.Name()) _, err := os.Stat(mgcSrc + ".mgc") if err != nil { srcFiles = append(srcFiles, mgcSrc) } } } // compile .magic files if len(srcFiles) > 0 { compileMagicFiles(dir, srcFiles) } files, err = ioutil.ReadDir(dir) if err != nil { return err } mutex.Lock() for _, fi = range files { if filepath.Ext(fi.Name()) == ".mgc" { mgcFile := filepath.Join(dir, fi.Name()) magicFiles[mgcFile] = true } } mutex.Unlock() return nil } /* Get mimetype from a file. */ func MimeFromFile(path string) string { cookie := Open(MAGIC_ERROR | MAGIC_MIME_TYPE) defer Close(cookie) mutex.Lock() var mf []string for f := range magicFiles { mf = append(mf, f) } mutex.Unlock() ret := Load(cookie, strings.Join(mf, ":")) if ret != 0 { return "application/octet-stream" } r := File(cookie, path) return r } /* Get mimetype from a buffer. */ func MimeFromBytes(b []byte) string { cookie := Open(MAGIC_ERROR | MAGIC_MIME_TYPE) defer Close(cookie) mutex.Lock() var mf []string for f := range magicFiles { mf = append(mf, f) } mutex.Unlock() ret := Load(cookie, strings.Join(mf, ":")) if ret != 0 { return "application/octet-stream" } r := Buffer(cookie, b) return r }