"Fossies" - the Fresh Open Source Software Archive

Member "file-5.35/python/magic.py" (9 Jul 2018, 8440 Bytes) of package /linux/misc/file-5.35.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "magic.py" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 5.33_vs_5.34.

    1 # coding: utf-8
    2 
    3 '''
    4 Python bindings for libmagic
    5 '''
    6 
    7 import ctypes
    8 
    9 from collections import namedtuple
   10 
   11 from ctypes import *
   12 from ctypes.util import find_library
   13 
   14 
   15 def _init():
   16     """
   17     Loads the shared library through ctypes and returns a library
   18     L{ctypes.CDLL} instance
   19     """
   20     return ctypes.cdll.LoadLibrary(find_library('magic'))
   21 
   22 _libraries = {}
   23 _libraries['magic'] = _init()
   24 
   25 # Flag constants for open and setflags
   26 MAGIC_NONE = NONE = 0
   27 MAGIC_DEBUG = DEBUG = 1
   28 MAGIC_SYMLINK = SYMLINK = 2
   29 MAGIC_COMPRESS = COMPRESS = 4
   30 MAGIC_DEVICES = DEVICES = 8
   31 MAGIC_MIME_TYPE = MIME_TYPE = 16
   32 MAGIC_CONTINUE = CONTINUE = 32
   33 MAGIC_CHECK = CHECK = 64
   34 MAGIC_PRESERVE_ATIME = PRESERVE_ATIME = 128
   35 MAGIC_RAW = RAW = 256
   36 MAGIC_ERROR = ERROR = 512
   37 MAGIC_MIME_ENCODING = MIME_ENCODING = 1024
   38 MAGIC_MIME = MIME = 1040  # MIME_TYPE + MIME_ENCODING
   39 MAGIC_APPLE = APPLE = 2048
   40 
   41 MAGIC_NO_CHECK_COMPRESS = NO_CHECK_COMPRESS = 4096
   42 MAGIC_NO_CHECK_TAR = NO_CHECK_TAR = 8192
   43 MAGIC_NO_CHECK_SOFT = NO_CHECK_SOFT = 16384
   44 MAGIC_NO_CHECK_APPTYPE = NO_CHECK_APPTYPE = 32768
   45 MAGIC_NO_CHECK_ELF = NO_CHECK_ELF = 65536
   46 MAGIC_NO_CHECK_TEXT = NO_CHECK_TEXT = 131072
   47 MAGIC_NO_CHECK_CDF = NO_CHECK_CDF = 262144
   48 MAGIC_NO_CHECK_TOKENS = NO_CHECK_TOKENS = 1048576
   49 MAGIC_NO_CHECK_ENCODING = NO_CHECK_ENCODING = 2097152
   50 
   51 MAGIC_NO_CHECK_BUILTIN = NO_CHECK_BUILTIN = 4173824
   52 
   53 FileMagic = namedtuple('FileMagic', ('mime_type', 'encoding', 'name'))
   54 
   55 
   56 class magic_set(Structure):
   57     pass
   58 magic_set._fields_ = []
   59 magic_t = POINTER(magic_set)
   60 
   61 _open = _libraries['magic'].magic_open
   62 _open.restype = magic_t
   63 _open.argtypes = [c_int]
   64 
   65 _close = _libraries['magic'].magic_close
   66 _close.restype = None
   67 _close.argtypes = [magic_t]
   68 
   69 _file = _libraries['magic'].magic_file
   70 _file.restype = c_char_p
   71 _file.argtypes = [magic_t, c_char_p]
   72 
   73 _descriptor = _libraries['magic'].magic_descriptor
   74 _descriptor.restype = c_char_p
   75 _descriptor.argtypes = [magic_t, c_int]
   76 
   77 _buffer = _libraries['magic'].magic_buffer
   78 _buffer.restype = c_char_p
   79 _buffer.argtypes = [magic_t, c_void_p, c_size_t]
   80 
   81 _error = _libraries['magic'].magic_error
   82 _error.restype = c_char_p
   83 _error.argtypes = [magic_t]
   84 
   85 _setflags = _libraries['magic'].magic_setflags
   86 _setflags.restype = c_int
   87 _setflags.argtypes = [magic_t, c_int]
   88 
   89 _load = _libraries['magic'].magic_load
   90 _load.restype = c_int
   91 _load.argtypes = [magic_t, c_char_p]
   92 
   93 _compile = _libraries['magic'].magic_compile
   94 _compile.restype = c_int
   95 _compile.argtypes = [magic_t, c_char_p]
   96 
   97 _check = _libraries['magic'].magic_check
   98 _check.restype = c_int
   99 _check.argtypes = [magic_t, c_char_p]
  100 
  101 _list = _libraries['magic'].magic_list
  102 _list.restype = c_int
  103 _list.argtypes = [magic_t, c_char_p]
  104 
  105 _errno = _libraries['magic'].magic_errno
  106 _errno.restype = c_int
  107 _errno.argtypes = [magic_t]
  108 
  109 
  110 class Magic(object):
  111     def __init__(self, ms):
  112         self._magic_t = ms
  113 
  114     def close(self):
  115         """
  116         Closes the magic database and deallocates any resources used.
  117         """
  118         _close(self._magic_t)
  119 
  120     @staticmethod
  121     def __tostr(s):
  122         if s is None:
  123             return None
  124         if isinstance(s, str):
  125             return s
  126         try:  # keep Python 2 compatibility
  127             return str(s, 'utf-8')
  128         except TypeError:
  129             return str(s)
  130 
  131     @staticmethod
  132     def __tobytes(b):
  133         if b is None:
  134             return None
  135         if isinstance(b, bytes):
  136             return b
  137         try:  # keep Python 2 compatibility
  138             return bytes(b, 'utf-8')
  139         except TypeError:
  140             return bytes(b)
  141 
  142     def file(self, filename):
  143         """
  144         Returns a textual description of the contents of the argument passed
  145         as a filename or None if an error occurred and the MAGIC_ERROR flag
  146         is set. A call to errno() will return the numeric error code.
  147         """
  148         return Magic.__tostr(_file(self._magic_t, Magic.__tobytes(filename)))
  149 
  150     def descriptor(self, fd):
  151         """
  152         Returns a textual description of the contents of the argument passed
  153         as a file descriptor or None if an error occurred and the MAGIC_ERROR
  154         flag is set. A call to errno() will return the numeric error code.
  155         """
  156         return Magic.__tostr(_descriptor(self._magic_t, fd))
  157 
  158     def buffer(self, buf):
  159         """
  160         Returns a textual description of the contents of the argument passed
  161         as a buffer or None if an error occurred and the MAGIC_ERROR flag
  162         is set. A call to errno() will return the numeric error code.
  163         """
  164         return Magic.__tostr(_buffer(self._magic_t, buf, len(buf)))
  165 
  166     def error(self):
  167         """
  168         Returns a textual explanation of the last error or None
  169         if there was no error.
  170         """
  171         return Magic.__tostr(_error(self._magic_t))
  172 
  173     def setflags(self, flags):
  174         """
  175         Set flags on the magic object which determine how magic checking
  176         behaves; a bitwise OR of the flags described in libmagic(3), but
  177         without the MAGIC_ prefix.
  178 
  179         Returns -1 on systems that don't support utime(2) or utimes(2)
  180         when PRESERVE_ATIME is set.
  181         """
  182         return _setflags(self._magic_t, flags)
  183 
  184     def load(self, filename=None):
  185         """
  186         Must be called to load entries in the colon separated list of database
  187         files passed as argument or the default database file if no argument
  188         before any magic queries can be performed.
  189 
  190         Returns 0 on success and -1 on failure.
  191         """
  192         return _load(self._magic_t, Magic.__tobytes(filename))
  193 
  194     def compile(self, dbs):
  195         """
  196         Compile entries in the colon separated list of database files
  197         passed as argument or the default database file if no argument.
  198         The compiled files created are named from the basename(1) of each file
  199         argument with ".mgc" appended to it.
  200 
  201         Returns 0 on success and -1 on failure.
  202         """
  203         return _compile(self._magic_t, Magic.__tobytes(dbs))
  204 
  205     def check(self, dbs):
  206         """
  207         Check the validity of entries in the colon separated list of
  208         database files passed as argument or the default database file
  209         if no argument.
  210 
  211         Returns 0 on success and -1 on failure.
  212         """
  213         return _check(self._magic_t, Magic.__tobytes(dbs))
  214 
  215     def list(self, dbs):
  216         """
  217         Check the validity of entries in the colon separated list of
  218         database files passed as argument or the default database file
  219         if no argument.
  220 
  221         Returns 0 on success and -1 on failure.
  222         """
  223         return _list(self._magic_t, Magic.__tobytes(dbs))
  224 
  225     def errno(self):
  226         """
  227         Returns a numeric error code. If return value is 0, an internal
  228         magic error occurred. If return value is non-zero, the value is
  229         an OS error code. Use the errno module or os.strerror() can be used
  230         to provide detailed error information.
  231         """
  232         return _errno(self._magic_t)
  233 
  234 
  235 def open(flags):
  236     """
  237     Returns a magic object on success and None on failure.
  238     Flags argument as for setflags.
  239     """
  240     return Magic(_open(flags))
  241 
  242 
  243 # Objects used by `detect_from_` functions
  244 mime_magic = Magic(_open(MAGIC_MIME))
  245 mime_magic.load()
  246 none_magic = Magic(_open(MAGIC_NONE))
  247 none_magic.load()
  248 
  249 
  250 def _create_filemagic(mime_detected, type_detected):
  251     try:
  252         mime_type, mime_encoding = mime_detected.split('; ')
  253     except ValueError:
  254         raise ValueError(mime_detected)
  255 
  256     return FileMagic(name=type_detected, mime_type=mime_type,
  257                      encoding=mime_encoding.replace('charset=', ''))
  258 
  259 
  260 def detect_from_filename(filename):
  261     '''Detect mime type, encoding and file type from a filename
  262 
  263     Returns a `FileMagic` namedtuple.
  264     '''
  265 
  266     return _create_filemagic(mime_magic.file(filename),
  267                              none_magic.file(filename))
  268 
  269 
  270 def detect_from_fobj(fobj):
  271     '''Detect mime type, encoding and file type from file-like object
  272 
  273     Returns a `FileMagic` namedtuple.
  274     '''
  275 
  276     file_descriptor = fobj.fileno()
  277     return _create_filemagic(mime_magic.descriptor(file_descriptor),
  278                              none_magic.descriptor(file_descriptor))
  279 
  280 
  281 def detect_from_content(byte_content):
  282     '''Detect mime type, encoding and file type from bytes
  283 
  284     Returns a `FileMagic` namedtuple.
  285     '''
  286 
  287     return _create_filemagic(mime_magic.buffer(byte_content),
  288                              none_magic.buffer(byte_content))