1300899Sdelphij# coding: utf-8 2300899Sdelphij 3267843Sdelphij''' 4267843SdelphijPython bindings for libmagic 5267843Sdelphij''' 6267843Sdelphij 7267843Sdelphijimport ctypes 8267843Sdelphij 9300899Sdelphijfrom collections import namedtuple 10300899Sdelphij 11267843Sdelphijfrom ctypes import * 12267843Sdelphijfrom ctypes.util import find_library 13267843Sdelphij 14267843Sdelphij 15267843Sdelphijdef _init(): 16267843Sdelphij """ 17267843Sdelphij Loads the shared library through ctypes and returns a library 18267843Sdelphij L{ctypes.CDLL} instance 19267843Sdelphij """ 20267843Sdelphij return ctypes.cdll.LoadLibrary(find_library('magic')) 21267843Sdelphij 22267843Sdelphij_libraries = {} 23267843Sdelphij_libraries['magic'] = _init() 24267843Sdelphij 25267843Sdelphij# Flag constants for open and setflags 26267843SdelphijMAGIC_NONE = NONE = 0 27267843SdelphijMAGIC_DEBUG = DEBUG = 1 28267843SdelphijMAGIC_SYMLINK = SYMLINK = 2 29267843SdelphijMAGIC_COMPRESS = COMPRESS = 4 30267843SdelphijMAGIC_DEVICES = DEVICES = 8 31267843SdelphijMAGIC_MIME_TYPE = MIME_TYPE = 16 32267843SdelphijMAGIC_CONTINUE = CONTINUE = 32 33267843SdelphijMAGIC_CHECK = CHECK = 64 34267843SdelphijMAGIC_PRESERVE_ATIME = PRESERVE_ATIME = 128 35267843SdelphijMAGIC_RAW = RAW = 256 36267843SdelphijMAGIC_ERROR = ERROR = 512 37267843SdelphijMAGIC_MIME_ENCODING = MIME_ENCODING = 1024 38300899SdelphijMAGIC_MIME = MIME = 1040 # MIME_TYPE + MIME_ENCODING 39267843SdelphijMAGIC_APPLE = APPLE = 2048 40267843Sdelphij 41267843SdelphijMAGIC_NO_CHECK_COMPRESS = NO_CHECK_COMPRESS = 4096 42267843SdelphijMAGIC_NO_CHECK_TAR = NO_CHECK_TAR = 8192 43267843SdelphijMAGIC_NO_CHECK_SOFT = NO_CHECK_SOFT = 16384 44267843SdelphijMAGIC_NO_CHECK_APPTYPE = NO_CHECK_APPTYPE = 32768 45267843SdelphijMAGIC_NO_CHECK_ELF = NO_CHECK_ELF = 65536 46267843SdelphijMAGIC_NO_CHECK_TEXT = NO_CHECK_TEXT = 131072 47267843SdelphijMAGIC_NO_CHECK_CDF = NO_CHECK_CDF = 262144 48267843SdelphijMAGIC_NO_CHECK_TOKENS = NO_CHECK_TOKENS = 1048576 49267843SdelphijMAGIC_NO_CHECK_ENCODING = NO_CHECK_ENCODING = 2097152 50267843Sdelphij 51267843SdelphijMAGIC_NO_CHECK_BUILTIN = NO_CHECK_BUILTIN = 4173824 52267843Sdelphij 53300899SdelphijFileMagic = namedtuple('FileMagic', ('mime_type', 'encoding', 'name')) 54267843Sdelphij 55300899Sdelphij 56267843Sdelphijclass magic_set(Structure): 57267843Sdelphij pass 58267843Sdelphijmagic_set._fields_ = [] 59267843Sdelphijmagic_t = POINTER(magic_set) 60267843Sdelphij 61267843Sdelphij_open = _libraries['magic'].magic_open 62267843Sdelphij_open.restype = magic_t 63267843Sdelphij_open.argtypes = [c_int] 64267843Sdelphij 65267843Sdelphij_close = _libraries['magic'].magic_close 66267843Sdelphij_close.restype = None 67267843Sdelphij_close.argtypes = [magic_t] 68267843Sdelphij 69267843Sdelphij_file = _libraries['magic'].magic_file 70267843Sdelphij_file.restype = c_char_p 71267843Sdelphij_file.argtypes = [magic_t, c_char_p] 72267843Sdelphij 73267843Sdelphij_descriptor = _libraries['magic'].magic_descriptor 74267843Sdelphij_descriptor.restype = c_char_p 75267843Sdelphij_descriptor.argtypes = [magic_t, c_int] 76267843Sdelphij 77267843Sdelphij_buffer = _libraries['magic'].magic_buffer 78267843Sdelphij_buffer.restype = c_char_p 79267843Sdelphij_buffer.argtypes = [magic_t, c_void_p, c_size_t] 80267843Sdelphij 81267843Sdelphij_error = _libraries['magic'].magic_error 82267843Sdelphij_error.restype = c_char_p 83267843Sdelphij_error.argtypes = [magic_t] 84267843Sdelphij 85267843Sdelphij_setflags = _libraries['magic'].magic_setflags 86267843Sdelphij_setflags.restype = c_int 87267843Sdelphij_setflags.argtypes = [magic_t, c_int] 88267843Sdelphij 89267843Sdelphij_load = _libraries['magic'].magic_load 90267843Sdelphij_load.restype = c_int 91267843Sdelphij_load.argtypes = [magic_t, c_char_p] 92267843Sdelphij 93267843Sdelphij_compile = _libraries['magic'].magic_compile 94267843Sdelphij_compile.restype = c_int 95267843Sdelphij_compile.argtypes = [magic_t, c_char_p] 96267843Sdelphij 97267843Sdelphij_check = _libraries['magic'].magic_check 98267843Sdelphij_check.restype = c_int 99267843Sdelphij_check.argtypes = [magic_t, c_char_p] 100267843Sdelphij 101267843Sdelphij_list = _libraries['magic'].magic_list 102267843Sdelphij_list.restype = c_int 103267843Sdelphij_list.argtypes = [magic_t, c_char_p] 104267843Sdelphij 105267843Sdelphij_errno = _libraries['magic'].magic_errno 106267843Sdelphij_errno.restype = c_int 107267843Sdelphij_errno.argtypes = [magic_t] 108267843Sdelphij 109267843Sdelphij 110267843Sdelphijclass Magic(object): 111267843Sdelphij def __init__(self, ms): 112267843Sdelphij self._magic_t = ms 113267843Sdelphij 114267843Sdelphij def close(self): 115267843Sdelphij """ 116267843Sdelphij Closes the magic database and deallocates any resources used. 117267843Sdelphij """ 118267843Sdelphij _close(self._magic_t) 119267843Sdelphij 120328875Seadler @staticmethod 121328875Seadler def __tostr(s): 122328875Seadler if s is None: 123328875Seadler return None 124328875Seadler if isinstance(s, str): 125328875Seadler return s 126328875Seadler try: # keep Python 2 compatibility 127328875Seadler return str(s, 'utf-8') 128328875Seadler except TypeError: 129328875Seadler return str(s) 130328875Seadler 131328875Seadler @staticmethod 132328875Seadler def __tobytes(b): 133328875Seadler if b is None: 134328875Seadler return None 135328875Seadler if isinstance(b, bytes): 136328875Seadler return b 137328875Seadler try: # keep Python 2 compatibility 138328875Seadler return bytes(b, 'utf-8') 139328875Seadler except TypeError: 140328875Seadler return bytes(b) 141328875Seadler 142267843Sdelphij def file(self, filename): 143267843Sdelphij """ 144267843Sdelphij Returns a textual description of the contents of the argument passed 145267843Sdelphij as a filename or None if an error occurred and the MAGIC_ERROR flag 146328875Seadler is set. A call to errno() will return the numeric error code. 147267843Sdelphij """ 148328875Seadler return Magic.__tostr(_file(self._magic_t, Magic.__tobytes(filename))) 149267843Sdelphij 150267843Sdelphij def descriptor(self, fd): 151267843Sdelphij """ 152328875Seadler Returns a textual description of the contents of the argument passed 153328875Seadler as a file descriptor or None if an error occurred and the MAGIC_ERROR 154328875Seadler flag is set. A call to errno() will return the numeric error code. 155267843Sdelphij """ 156328875Seadler return Magic.__tostr(_descriptor(self._magic_t, fd)) 157267843Sdelphij 158267843Sdelphij def buffer(self, buf): 159267843Sdelphij """ 160267843Sdelphij Returns a textual description of the contents of the argument passed 161267843Sdelphij as a buffer or None if an error occurred and the MAGIC_ERROR flag 162267843Sdelphij is set. A call to errno() will return the numeric error code. 163267843Sdelphij """ 164328875Seadler return Magic.__tostr(_buffer(self._magic_t, buf, len(buf))) 165267843Sdelphij 166267843Sdelphij def error(self): 167267843Sdelphij """ 168267843Sdelphij Returns a textual explanation of the last error or None 169267843Sdelphij if there was no error. 170267843Sdelphij """ 171328875Seadler return Magic.__tostr(_error(self._magic_t)) 172267843Sdelphij 173267843Sdelphij def setflags(self, flags): 174267843Sdelphij """ 175267843Sdelphij Set flags on the magic object which determine how magic checking 176267843Sdelphij behaves; a bitwise OR of the flags described in libmagic(3), but 177267843Sdelphij without the MAGIC_ prefix. 178267843Sdelphij 179267843Sdelphij Returns -1 on systems that don't support utime(2) or utimes(2) 180267843Sdelphij when PRESERVE_ATIME is set. 181267843Sdelphij """ 182267843Sdelphij return _setflags(self._magic_t, flags) 183267843Sdelphij 184267843Sdelphij def load(self, filename=None): 185267843Sdelphij """ 186267843Sdelphij Must be called to load entries in the colon separated list of database 187267843Sdelphij files passed as argument or the default database file if no argument 188267843Sdelphij before any magic queries can be performed. 189267843Sdelphij 190267843Sdelphij Returns 0 on success and -1 on failure. 191267843Sdelphij """ 192328875Seadler return _load(self._magic_t, Magic.__tobytes(filename)) 193267843Sdelphij 194267843Sdelphij def compile(self, dbs): 195267843Sdelphij """ 196267843Sdelphij Compile entries in the colon separated list of database files 197267843Sdelphij passed as argument or the default database file if no argument. 198267843Sdelphij The compiled files created are named from the basename(1) of each file 199267843Sdelphij argument with ".mgc" appended to it. 200328875Seadler 201328875Seadler Returns 0 on success and -1 on failure. 202267843Sdelphij """ 203328875Seadler return _compile(self._magic_t, Magic.__tobytes(dbs)) 204267843Sdelphij 205267843Sdelphij def check(self, dbs): 206267843Sdelphij """ 207267843Sdelphij Check the validity of entries in the colon separated list of 208267843Sdelphij database files passed as argument or the default database file 209267843Sdelphij if no argument. 210328875Seadler 211267843Sdelphij Returns 0 on success and -1 on failure. 212267843Sdelphij """ 213328875Seadler return _check(self._magic_t, Magic.__tobytes(dbs)) 214267843Sdelphij 215267843Sdelphij def list(self, dbs): 216267843Sdelphij """ 217267843Sdelphij Check the validity of entries in the colon separated list of 218267843Sdelphij database files passed as argument or the default database file 219267843Sdelphij if no argument. 220328875Seadler 221267843Sdelphij Returns 0 on success and -1 on failure. 222267843Sdelphij """ 223328875Seadler return _list(self._magic_t, Magic.__tobytes(dbs)) 224267843Sdelphij 225267843Sdelphij def errno(self): 226267843Sdelphij """ 227267843Sdelphij Returns a numeric error code. If return value is 0, an internal 228267843Sdelphij magic error occurred. If return value is non-zero, the value is 229267843Sdelphij an OS error code. Use the errno module or os.strerror() can be used 230267843Sdelphij to provide detailed error information. 231267843Sdelphij """ 232267843Sdelphij return _errno(self._magic_t) 233267843Sdelphij 234267843Sdelphij 235267843Sdelphijdef open(flags): 236267843Sdelphij """ 237267843Sdelphij Returns a magic object on success and None on failure. 238267843Sdelphij Flags argument as for setflags. 239267843Sdelphij """ 240267843Sdelphij return Magic(_open(flags)) 241300899Sdelphij 242300899Sdelphij 243300899Sdelphij# Objects used by `detect_from_` functions 244300899Sdelphijmime_magic = Magic(_open(MAGIC_MIME)) 245300899Sdelphijmime_magic.load() 246300899Sdelphijnone_magic = Magic(_open(MAGIC_NONE)) 247300899Sdelphijnone_magic.load() 248300899Sdelphij 249300899Sdelphij 250300899Sdelphijdef _create_filemagic(mime_detected, type_detected): 251300899Sdelphij mime_type, mime_encoding = mime_detected.split('; ') 252300899Sdelphij 253300899Sdelphij return FileMagic(name=type_detected, mime_type=mime_type, 254300899Sdelphij encoding=mime_encoding.replace('charset=', '')) 255300899Sdelphij 256300899Sdelphij 257300899Sdelphijdef detect_from_filename(filename): 258300899Sdelphij '''Detect mime type, encoding and file type from a filename 259300899Sdelphij 260300899Sdelphij Returns a `FileMagic` namedtuple. 261300899Sdelphij ''' 262300899Sdelphij 263300899Sdelphij return _create_filemagic(mime_magic.file(filename), 264300899Sdelphij none_magic.file(filename)) 265300899Sdelphij 266300899Sdelphij 267300899Sdelphijdef detect_from_fobj(fobj): 268300899Sdelphij '''Detect mime type, encoding and file type from file-like object 269300899Sdelphij 270300899Sdelphij Returns a `FileMagic` namedtuple. 271300899Sdelphij ''' 272300899Sdelphij 273300899Sdelphij file_descriptor = fobj.fileno() 274300899Sdelphij return _create_filemagic(mime_magic.descriptor(file_descriptor), 275300899Sdelphij none_magic.descriptor(file_descriptor)) 276300899Sdelphij 277300899Sdelphij 278300899Sdelphijdef detect_from_content(byte_content): 279300899Sdelphij '''Detect mime type, encoding and file type from bytes 280300899Sdelphij 281300899Sdelphij Returns a `FileMagic` namedtuple. 282300899Sdelphij ''' 283300899Sdelphij 284300899Sdelphij return _create_filemagic(mime_magic.buffer(byte_content), 285300899Sdelphij none_magic.buffer(byte_content)) 286