Commit e252fd75 authored by Sascha Steinbiss's avatar Sascha Steinbiss

New upstream version 0.0~git20180208.aff138d

parents
Copyright (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 #
## Go library for getting MIME type using libmagic ##
### Installing ###
```
go get github.com/vimeo/go-magic/magic
```
### Dependencies ###
**libmagic**<br />
*URL*: [http://www.darwinsys.com/file/](http://www.darwinsys.com/file/)<br />
*Ubuntu*: `apt-get install libmagic-dev`<br />
*CentOS*: `yum install file-devel`<br />
### 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)
package magic
/*
#cgo LDFLAGS: -lmagic
#include <magic.h>
#include <stdlib.h>
*/
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))
}
package 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
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment