summaryrefslogtreecommitdiff
path: root/libmat2/exiftool.py
diff options
context:
space:
mode:
Diffstat (limited to 'libmat2/exiftool.py')
-rw-r--r--libmat2/exiftool.py61
1 files changed, 61 insertions, 0 deletions
diff --git a/libmat2/exiftool.py b/libmat2/exiftool.py
new file mode 100644
index 0000000..e17d31b
--- /dev/null
+++ b/libmat2/exiftool.py
@@ -0,0 +1,61 @@
1import json
2import os
3import re
4import shutil
5import subprocess
6import tempfile
7
8from typing import Dict, Union, Set
9
10from . import abstract
11
12# Make pyflakes happy
13assert Set
14
15
16class ExiftoolParser(abstract.AbstractParser):
17 """ Exiftool is often the easiest way to get all the metadata
18 from a import file, hence why several parsers are re-using its `get_meta`
19 method.
20 """
21 meta_whitelist = set() # type: Set[str]
22
23 @staticmethod
24 def __handle_problematic_filename(filename: str, callback) -> bytes:
25 """ This method takes a filename with a problematic name,
26 and safely applies it a `callback`."""
27 tmpdirname = tempfile.mkdtemp()
28 fname = os.path.join(tmpdirname, "temp_file")
29 shutil.copy(filename, fname)
30 out = callback(fname)
31 shutil.rmtree(tmpdirname)
32 return out
33
34 def get_meta(self) -> Dict[str, Union[str, dict]]:
35 """ There is no way to escape the leading(s) dash(es) of the current
36 self.filename to prevent parameter injections, so we need to take care
37 of this.
38 """
39 fun = lambda f: subprocess.check_output([_get_exiftool_path(), '-json', f])
40 if re.search('^[a-z0-9/]', self.filename) is None:
41 out = self.__handle_problematic_filename(self.filename, fun)
42 else:
43 out = fun(self.filename)
44 meta = json.loads(out.decode('utf-8'))[0]
45 for key in self.meta_whitelist:
46 meta.pop(key, None)
47 return meta
48
49def _get_exiftool_path() -> str: # pragma: no cover
50 exiftool_path = '/usr/bin/exiftool'
51 if os.path.isfile(exiftool_path):
52 if os.access(exiftool_path, os.X_OK):
53 return exiftool_path
54
55 # ArchLinux
56 exiftool_path = '/usr/bin/vendor_perl/exiftool'
57 if os.path.isfile(exiftool_path):
58 if os.access(exiftool_path, os.X_OK):
59 return exiftool_path
60
61 raise RuntimeError("Unable to find exiftool")