1267843Sdelphij#!/usr/bin/env python
2267843Sdelphij'''
3267843SdelphijPython bindings for libmagic
4267843Sdelphij'''
5267843Sdelphij
6267843Sdelphijimport ctypes
7267843Sdelphij
8267843Sdelphijfrom ctypes import *
9267843Sdelphijfrom ctypes.util import find_library
10267843Sdelphij
11267843Sdelphij
12267843Sdelphijdef _init():
13267843Sdelphij    """
14267843Sdelphij    Loads the shared library through ctypes and returns a library
15267843Sdelphij    L{ctypes.CDLL} instance
16267843Sdelphij    """
17267843Sdelphij    return ctypes.cdll.LoadLibrary(find_library('magic'))
18267843Sdelphij
19267843Sdelphij_libraries = {}
20267843Sdelphij_libraries['magic'] = _init()
21267843Sdelphij
22267843Sdelphij# Flag constants for open and setflags
23267843SdelphijMAGIC_NONE = NONE = 0
24267843SdelphijMAGIC_DEBUG = DEBUG = 1
25267843SdelphijMAGIC_SYMLINK = SYMLINK = 2
26267843SdelphijMAGIC_COMPRESS = COMPRESS = 4
27267843SdelphijMAGIC_DEVICES = DEVICES = 8
28267843SdelphijMAGIC_MIME_TYPE = MIME_TYPE = 16
29267843SdelphijMAGIC_CONTINUE = CONTINUE = 32
30267843SdelphijMAGIC_CHECK = CHECK = 64
31267843SdelphijMAGIC_PRESERVE_ATIME = PRESERVE_ATIME = 128
32267843SdelphijMAGIC_RAW = RAW = 256
33267843SdelphijMAGIC_ERROR = ERROR = 512
34267843SdelphijMAGIC_MIME_ENCODING = MIME_ENCODING = 1024
35267843SdelphijMAGIC_MIME = MIME = 1040
36267843SdelphijMAGIC_APPLE = APPLE = 2048
37267843Sdelphij
38267843SdelphijMAGIC_NO_CHECK_COMPRESS = NO_CHECK_COMPRESS = 4096
39267843SdelphijMAGIC_NO_CHECK_TAR = NO_CHECK_TAR = 8192
40267843SdelphijMAGIC_NO_CHECK_SOFT = NO_CHECK_SOFT = 16384
41267843SdelphijMAGIC_NO_CHECK_APPTYPE = NO_CHECK_APPTYPE = 32768
42267843SdelphijMAGIC_NO_CHECK_ELF = NO_CHECK_ELF = 65536
43267843SdelphijMAGIC_NO_CHECK_TEXT = NO_CHECK_TEXT = 131072
44267843SdelphijMAGIC_NO_CHECK_CDF = NO_CHECK_CDF = 262144
45267843SdelphijMAGIC_NO_CHECK_TOKENS = NO_CHECK_TOKENS = 1048576
46267843SdelphijMAGIC_NO_CHECK_ENCODING = NO_CHECK_ENCODING = 2097152
47267843Sdelphij
48267843SdelphijMAGIC_NO_CHECK_BUILTIN = NO_CHECK_BUILTIN = 4173824
49267843Sdelphij
50267843Sdelphij
51267843Sdelphijclass magic_set(Structure):
52267843Sdelphij    pass
53267843Sdelphijmagic_set._fields_ = []
54267843Sdelphijmagic_t = POINTER(magic_set)
55267843Sdelphij
56267843Sdelphij_open = _libraries['magic'].magic_open
57267843Sdelphij_open.restype = magic_t
58267843Sdelphij_open.argtypes = [c_int]
59267843Sdelphij
60267843Sdelphij_close = _libraries['magic'].magic_close
61267843Sdelphij_close.restype = None
62267843Sdelphij_close.argtypes = [magic_t]
63267843Sdelphij
64267843Sdelphij_file = _libraries['magic'].magic_file
65267843Sdelphij_file.restype = c_char_p
66267843Sdelphij_file.argtypes = [magic_t, c_char_p]
67267843Sdelphij
68267843Sdelphij_descriptor = _libraries['magic'].magic_descriptor
69267843Sdelphij_descriptor.restype = c_char_p
70267843Sdelphij_descriptor.argtypes = [magic_t, c_int]
71267843Sdelphij
72267843Sdelphij_buffer = _libraries['magic'].magic_buffer
73267843Sdelphij_buffer.restype = c_char_p
74267843Sdelphij_buffer.argtypes = [magic_t, c_void_p, c_size_t]
75267843Sdelphij
76267843Sdelphij_error = _libraries['magic'].magic_error
77267843Sdelphij_error.restype = c_char_p
78267843Sdelphij_error.argtypes = [magic_t]
79267843Sdelphij
80267843Sdelphij_setflags = _libraries['magic'].magic_setflags
81267843Sdelphij_setflags.restype = c_int
82267843Sdelphij_setflags.argtypes = [magic_t, c_int]
83267843Sdelphij
84267843Sdelphij_load = _libraries['magic'].magic_load
85267843Sdelphij_load.restype = c_int
86267843Sdelphij_load.argtypes = [magic_t, c_char_p]
87267843Sdelphij
88267843Sdelphij_compile = _libraries['magic'].magic_compile
89267843Sdelphij_compile.restype = c_int
90267843Sdelphij_compile.argtypes = [magic_t, c_char_p]
91267843Sdelphij
92267843Sdelphij_check = _libraries['magic'].magic_check
93267843Sdelphij_check.restype = c_int
94267843Sdelphij_check.argtypes = [magic_t, c_char_p]
95267843Sdelphij
96267843Sdelphij_list = _libraries['magic'].magic_list
97267843Sdelphij_list.restype = c_int
98267843Sdelphij_list.argtypes = [magic_t, c_char_p]
99267843Sdelphij
100267843Sdelphij_errno = _libraries['magic'].magic_errno
101267843Sdelphij_errno.restype = c_int
102267843Sdelphij_errno.argtypes = [magic_t]
103267843Sdelphij
104267843Sdelphij
105267843Sdelphijclass Magic(object):
106267843Sdelphij    def __init__(self, ms):
107267843Sdelphij        self._magic_t = ms
108267843Sdelphij
109267843Sdelphij    def close(self):
110267843Sdelphij        """
111267843Sdelphij        Closes the magic database and deallocates any resources used.
112267843Sdelphij        """
113267843Sdelphij        _close(self._magic_t)
114267843Sdelphij
115267843Sdelphij    def file(self, filename):
116267843Sdelphij        """
117267843Sdelphij        Returns a textual description of the contents of the argument passed
118267843Sdelphij        as a filename or None if an error occurred and the MAGIC_ERROR flag
119267843Sdelphij        is set.  A call to errno() will return the numeric error code.
120267843Sdelphij        """
121267843Sdelphij        try:  # attempt python3 approach first
122267843Sdelphij            if isinstance(filename, bytes):
123267843Sdelphij                bi = filename
124267843Sdelphij            else:
125267843Sdelphij                bi = bytes(filename, 'utf-8')
126267843Sdelphij            return str(_file(self._magic_t, bi), 'utf-8')
127267843Sdelphij        except:
128267843Sdelphij            return _file(self._magic_t, filename.encode('utf-8'))
129267843Sdelphij
130267843Sdelphij    def descriptor(self, fd):
131267843Sdelphij        """
132267843Sdelphij        Like the file method, but the argument is a file descriptor.
133267843Sdelphij        """
134267843Sdelphij        return _descriptor(self._magic_t, fd)
135267843Sdelphij
136267843Sdelphij    def buffer(self, buf):
137267843Sdelphij        """
138267843Sdelphij        Returns a textual description of the contents of the argument passed
139267843Sdelphij        as a buffer or None if an error occurred and the MAGIC_ERROR flag
140267843Sdelphij        is set. A call to errno() will return the numeric error code.
141267843Sdelphij        """
142267843Sdelphij        try:  # attempt python3 approach first
143267843Sdelphij            return str(_buffer(self._magic_t, buf, len(buf)), 'utf-8')
144267843Sdelphij        except:
145267843Sdelphij            return _buffer(self._magic_t, buf, len(buf))
146267843Sdelphij
147267843Sdelphij    def error(self):
148267843Sdelphij        """
149267843Sdelphij        Returns a textual explanation of the last error or None
150267843Sdelphij        if there was no error.
151267843Sdelphij        """
152267843Sdelphij        try:  # attempt python3 approach first
153267843Sdelphij            return str(_error(self._magic_t), 'utf-8')
154267843Sdelphij        except:
155267843Sdelphij            return _error(self._magic_t)
156267843Sdelphij
157267843Sdelphij    def setflags(self, flags):
158267843Sdelphij        """
159267843Sdelphij        Set flags on the magic object which determine how magic checking
160267843Sdelphij        behaves; a bitwise OR of the flags described in libmagic(3), but
161267843Sdelphij        without the MAGIC_ prefix.
162267843Sdelphij
163267843Sdelphij        Returns -1 on systems that don't support utime(2) or utimes(2)
164267843Sdelphij        when PRESERVE_ATIME is set.
165267843Sdelphij        """
166267843Sdelphij        return _setflags(self._magic_t, flags)
167267843Sdelphij
168267843Sdelphij    def load(self, filename=None):
169267843Sdelphij        """
170267843Sdelphij        Must be called to load entries in the colon separated list of database
171267843Sdelphij        files passed as argument or the default database file if no argument
172267843Sdelphij        before any magic queries can be performed.
173267843Sdelphij
174267843Sdelphij        Returns 0 on success and -1 on failure.
175267843Sdelphij        """
176267843Sdelphij        return _load(self._magic_t, filename)
177267843Sdelphij
178267843Sdelphij    def compile(self, dbs):
179267843Sdelphij        """
180267843Sdelphij        Compile entries in the colon separated list of database files
181267843Sdelphij        passed as argument or the default database file if no argument.
182267843Sdelphij        Returns 0 on success and -1 on failure.
183267843Sdelphij        The compiled files created are named from the basename(1) of each file
184267843Sdelphij        argument with ".mgc" appended to it.
185267843Sdelphij        """
186267843Sdelphij        return _compile(self._magic_t, dbs)
187267843Sdelphij
188267843Sdelphij    def check(self, dbs):
189267843Sdelphij        """
190267843Sdelphij        Check the validity of entries in the colon separated list of
191267843Sdelphij        database files passed as argument or the default database file
192267843Sdelphij        if no argument.
193267843Sdelphij        Returns 0 on success and -1 on failure.
194267843Sdelphij        """
195267843Sdelphij        return _check(self._magic_t, dbs)
196267843Sdelphij
197267843Sdelphij    def list(self, dbs):
198267843Sdelphij        """
199267843Sdelphij        Check the validity of entries in the colon separated list of
200267843Sdelphij        database files passed as argument or the default database file
201267843Sdelphij        if no argument.
202267843Sdelphij        Returns 0 on success and -1 on failure.
203267843Sdelphij        """
204267843Sdelphij        return _list(self._magic_t, dbs)
205267843Sdelphij
206267843Sdelphij    def errno(self):
207267843Sdelphij        """
208267843Sdelphij        Returns a numeric error code. If return value is 0, an internal
209267843Sdelphij        magic error occurred. If return value is non-zero, the value is
210267843Sdelphij        an OS error code. Use the errno module or os.strerror() can be used
211267843Sdelphij        to provide detailed error information.
212267843Sdelphij        """
213267843Sdelphij        return _errno(self._magic_t)
214267843Sdelphij
215267843Sdelphij
216267843Sdelphijdef open(flags):
217267843Sdelphij    """
218267843Sdelphij    Returns a magic object on success and None on failure.
219267843Sdelphij    Flags argument as for setflags.
220267843Sdelphij    """
221267843Sdelphij    return Magic(_open(flags))
222