From 8cf9aeeb67b9de77434acf9dbd8cc4b3792f8741 Mon Sep 17 00:00:00 2001 From: jvoisin Date: Mon, 21 May 2018 22:49:40 +0200 Subject: Rename mat2.py to mat2 --- README.md | 2 +- mat2 | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++ mat2.py | 121 -------------------------------------------------- tests/test_climat2.py | 44 +++++++++--------- 4 files changed, 144 insertions(+), 144 deletions(-) create mode 100755 mat2 delete mode 100755 mat2.py diff --git a/README.md b/README.md index 0499372..6d976c1 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ $ python3 -m unittest discover -v # Supported formats ```bash -$ python3 ./mat2.py -l +$ python3 ./mat2 -l ``` # Related softwares diff --git a/mat2 b/mat2 new file mode 100755 index 0000000..aa213ab --- /dev/null +++ b/mat2 @@ -0,0 +1,121 @@ +#!/usr/bin/python3 + +import os +from typing import Tuple +import sys +import itertools +import mimetypes +import argparse +import multiprocessing + +from libmat2 import parser_factory, unsupported_extensions + +__version__ = '0.1.1' + +def __check_file(filename: str, mode: int = os.R_OK) -> bool: + if not os.path.isfile(filename): + print("[-] %s is not a regular file." % filename) + return False + elif not os.access(filename, mode): + print("[-] %s is not readable and writeable." % filename) + return False + return True + + +def create_arg_parser(): + parser = argparse.ArgumentParser(description='Metadata anonymisation toolkit 2') + parser.add_argument('files', nargs='*') + parser.add_argument('-v', '--version', action='version', + version='MAT2 %s' % __version__) + parser.add_argument('-l', '--list', action='store_true', + help='list all supported fileformats') + + info = parser.add_mutually_exclusive_group() + info.add_argument('-c', '--check', action='store_true', + help='check if a file is free of harmful metadatas') + info.add_argument('-s', '--show', action='store_true', + help='list all the harmful metadata of a file without removing them') + info.add_argument('-L', '--lightweight', action='store_true', + help='remove SOME metadata') + return parser + + +def show_meta(filename: str): + if not __check_file(filename): + return + + p, mtype = parser_factory.get_parser(filename) + if p is None: + print("[-] %s's format (%s) is not supported" % (filename, mtype)) + return + + print("[+] Metadata for %s:" % filename) + for k, v in p.get_meta().items(): + try: # FIXME this is ugly. + print(" %s: %s" % (k, v)) + except UnicodeEncodeError: + print(" %s: harmful content" % k) + +def clean_meta(params: Tuple[str, bool]) -> bool: + filename, is_lightweigth = params + if not __check_file(filename, os.R_OK|os.W_OK): + return False + + p, mtype = parser_factory.get_parser(filename) + if p is None: + print("[-] %s's format (%s) is not supported" % (filename, mtype)) + return False + if is_lightweigth: + return p.remove_all_lightweight() + return p.remove_all() + + +def show_parsers(): + print('[+] Supported formats:') + for parser in parser_factory._get_parsers(): + for mtype in parser.mimetypes: + extensions = set() + for extension in mimetypes.guess_all_extensions(mtype): + if extension[1:] not in unsupported_extensions: # skip the dot + extensions.add(extension) + if not extensions: + # we're not supporting a single extension in the current + # mimetype, so there is not point in showing the mimetype at all + continue + print(' - %s (%s)' % (mtype, ', '.join(extensions))) + + +def __get_files_recursively(files): + for f in files: + if os.path.isfile(f): + yield f + else: + for path, _, _files in os.walk(f): + for _f in _files: + yield os.path.join(path, _f) + +def main(): + arg_parser = create_arg_parser() + args = arg_parser.parse_args() + + if not args.files: + if not args.list: + return arg_parser.print_help() + show_parsers() + return 0 + + elif args.show: + for f in __get_files_recursively(args.files): + show_meta(f) + return 0 + + else: + p = multiprocessing.Pool() + mode = (args.lightweight is True) + l = zip(__get_files_recursively(args.files), itertools.repeat(mode)) + + ret = list(p.imap_unordered(clean_meta, list(l))) + return 0 if all(ret) else -1 + +if __name__ == '__main__': + sys.exit(main()) diff --git a/mat2.py b/mat2.py deleted file mode 100755 index aa213ab..0000000 --- a/mat2.py +++ /dev/null @@ -1,121 +0,0 @@ -#!/usr/bin/python3 - -import os -from typing import Tuple -import sys -import itertools -import mimetypes -import argparse -import multiprocessing - -from libmat2 import parser_factory, unsupported_extensions - -__version__ = '0.1.1' - -def __check_file(filename: str, mode: int = os.R_OK) -> bool: - if not os.path.isfile(filename): - print("[-] %s is not a regular file." % filename) - return False - elif not os.access(filename, mode): - print("[-] %s is not readable and writeable." % filename) - return False - return True - - -def create_arg_parser(): - parser = argparse.ArgumentParser(description='Metadata anonymisation toolkit 2') - parser.add_argument('files', nargs='*') - parser.add_argument('-v', '--version', action='version', - version='MAT2 %s' % __version__) - parser.add_argument('-l', '--list', action='store_true', - help='list all supported fileformats') - - info = parser.add_mutually_exclusive_group() - info.add_argument('-c', '--check', action='store_true', - help='check if a file is free of harmful metadatas') - info.add_argument('-s', '--show', action='store_true', - help='list all the harmful metadata of a file without removing them') - info.add_argument('-L', '--lightweight', action='store_true', - help='remove SOME metadata') - return parser - - -def show_meta(filename: str): - if not __check_file(filename): - return - - p, mtype = parser_factory.get_parser(filename) - if p is None: - print("[-] %s's format (%s) is not supported" % (filename, mtype)) - return - - print("[+] Metadata for %s:" % filename) - for k, v in p.get_meta().items(): - try: # FIXME this is ugly. - print(" %s: %s" % (k, v)) - except UnicodeEncodeError: - print(" %s: harmful content" % k) - -def clean_meta(params: Tuple[str, bool]) -> bool: - filename, is_lightweigth = params - if not __check_file(filename, os.R_OK|os.W_OK): - return False - - p, mtype = parser_factory.get_parser(filename) - if p is None: - print("[-] %s's format (%s) is not supported" % (filename, mtype)) - return False - if is_lightweigth: - return p.remove_all_lightweight() - return p.remove_all() - - -def show_parsers(): - print('[+] Supported formats:') - for parser in parser_factory._get_parsers(): - for mtype in parser.mimetypes: - extensions = set() - for extension in mimetypes.guess_all_extensions(mtype): - if extension[1:] not in unsupported_extensions: # skip the dot - extensions.add(extension) - if not extensions: - # we're not supporting a single extension in the current - # mimetype, so there is not point in showing the mimetype at all - continue - print(' - %s (%s)' % (mtype, ', '.join(extensions))) - - -def __get_files_recursively(files): - for f in files: - if os.path.isfile(f): - yield f - else: - for path, _, _files in os.walk(f): - for _f in _files: - yield os.path.join(path, _f) - -def main(): - arg_parser = create_arg_parser() - args = arg_parser.parse_args() - - if not args.files: - if not args.list: - return arg_parser.print_help() - show_parsers() - return 0 - - elif args.show: - for f in __get_files_recursively(args.files): - show_meta(f) - return 0 - - else: - p = multiprocessing.Pool() - mode = (args.lightweight is True) - l = zip(__get_files_recursively(args.files), itertools.repeat(mode)) - - ret = list(p.imap_unordered(clean_meta, list(l))) - return 0 if all(ret) else -1 - -if __name__ == '__main__': - sys.exit(main()) diff --git a/tests/test_climat2.py b/tests/test_climat2.py index 36973bf..fd72278 100644 --- a/tests/test_climat2.py +++ b/tests/test_climat2.py @@ -6,43 +6,43 @@ import unittest class TestHelp(unittest.TestCase): def test_help(self): - proc = subprocess.Popen(['./mat2.py', '--help'], stdout=subprocess.PIPE) + proc = subprocess.Popen(['./mat2', '--help'], stdout=subprocess.PIPE) stdout, _ = proc.communicate() - self.assertIn(b'usage: mat2.py [-h] [-v] [-l] [-c | -s | -L] [files [files ...]]', stdout) + self.assertIn(b'usage: mat2 [-h] [-v] [-l] [-c | -s | -L] [files [files ...]]', stdout) def test_no_arg(self): - proc = subprocess.Popen(['./mat2.py'], stdout=subprocess.PIPE) + proc = subprocess.Popen(['./mat2'], stdout=subprocess.PIPE) stdout, _ = proc.communicate() - self.assertIn(b'usage: mat2.py [-h] [-v] [-l] [-c | -s | -L] [files [files ...]]', stdout) + self.assertIn(b'usage: mat2 [-h] [-v] [-l] [-c | -s | -L] [files [files ...]]', stdout) class TestVersion(unittest.TestCase): def test_version(self): - proc = subprocess.Popen(['./mat2.py', '--version'], stdout=subprocess.PIPE) + proc = subprocess.Popen(['./mat2', '--version'], stdout=subprocess.PIPE) stdout, _ = proc.communicate() self.assertTrue(stdout.startswith(b'MAT2 ')) class TestExclusiveArgs(unittest.TestCase): def test_version(self): - proc = subprocess.Popen(['./mat2.py', '-s', '-c'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + proc = subprocess.Popen(['./mat2', '-s', '-c'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = proc.communicate() - self.assertIn(b'mat2.py: error: argument -c/--check: not allowed with argument -s/--show', stderr) + self.assertIn(b'mat2: error: argument -c/--check: not allowed with argument -s/--show', stderr) class TestReturnValue(unittest.TestCase): def test_nonzero(self): - ret = subprocess.call(['./mat2.py', './mat2.py'], stdout=subprocess.DEVNULL) + ret = subprocess.call(['./mat2', './mat2'], stdout=subprocess.DEVNULL) self.assertEqual(255, ret) - ret = subprocess.call(['./mat2.py', '--whololo'], stderr=subprocess.DEVNULL) + ret = subprocess.call(['./mat2', '--whololo'], stderr=subprocess.DEVNULL) self.assertEqual(2, ret) def test_zero(self): - ret = subprocess.call(['./mat2.py'], stdout=subprocess.DEVNULL) + ret = subprocess.call(['./mat2'], stdout=subprocess.DEVNULL) self.assertEqual(0, ret) - ret = subprocess.call(['./mat2.py', '--show', './mat2.py'], stdout=subprocess.DEVNULL) + ret = subprocess.call(['./mat2', '--show', './mat2'], stdout=subprocess.DEVNULL) self.assertEqual(0, ret) @@ -50,16 +50,16 @@ class TestCleanMeta(unittest.TestCase): def test_jpg(self): shutil.copy('./tests/data/dirty.jpg', './tests/data/clean.jpg') - proc = subprocess.Popen(['./mat2.py', '--show', './tests/data/clean.jpg'], + proc = subprocess.Popen(['./mat2', '--show', './tests/data/clean.jpg'], stdout=subprocess.PIPE) stdout, _ = proc.communicate() self.assertIn(b'Comment: Created with GIMP', stdout) - proc = subprocess.Popen(['./mat2.py', './tests/data/clean.jpg'], + proc = subprocess.Popen(['./mat2', './tests/data/clean.jpg'], stdout=subprocess.PIPE) stdout, _ = proc.communicate() - proc = subprocess.Popen(['./mat2.py', '--show', './tests/data/clean.cleaned.jpg'], + proc = subprocess.Popen(['./mat2', '--show', './tests/data/clean.cleaned.jpg'], stdout=subprocess.PIPE) stdout, _ = proc.communicate() self.assertNotIn(b'Comment: Created with GIMP', stdout) @@ -69,25 +69,25 @@ class TestCleanMeta(unittest.TestCase): class TestGetMeta(unittest.TestCase): def test_pdf(self): - proc = subprocess.Popen(['./mat2.py', '--show', './tests/data/dirty.pdf'], + proc = subprocess.Popen(['./mat2', '--show', './tests/data/dirty.pdf'], stdout=subprocess.PIPE) stdout, _ = proc.communicate() self.assertIn(b'producer: pdfTeX-1.40.14', stdout) def test_png(self): - proc = subprocess.Popen(['./mat2.py', '--show', './tests/data/dirty.png'], + proc = subprocess.Popen(['./mat2', '--show', './tests/data/dirty.png'], stdout=subprocess.PIPE) stdout, _ = proc.communicate() self.assertIn(b'Comment: This is a comment, be careful!', stdout) def test_jpg(self): - proc = subprocess.Popen(['./mat2.py', '--show', './tests/data/dirty.jpg'], + proc = subprocess.Popen(['./mat2', '--show', './tests/data/dirty.jpg'], stdout=subprocess.PIPE) stdout, _ = proc.communicate() self.assertIn(b'Comment: Created with GIMP', stdout) def test_docx(self): - proc = subprocess.Popen(['./mat2.py', '--show', './tests/data/dirty.docx'], + proc = subprocess.Popen(['./mat2', '--show', './tests/data/dirty.docx'], stdout=subprocess.PIPE) stdout, _ = proc.communicate() self.assertIn(b'Application: LibreOffice/5.4.5.1$Linux_X86_64', stdout) @@ -95,7 +95,7 @@ class TestGetMeta(unittest.TestCase): self.assertIn(b'revision: 1', stdout) def test_odt(self): - proc = subprocess.Popen(['./mat2.py', '--show', './tests/data/dirty.odt'], + proc = subprocess.Popen(['./mat2', '--show', './tests/data/dirty.odt'], stdout=subprocess.PIPE) stdout, _ = proc.communicate() self.assertIn(b'generator: LibreOffice/3.3$Unix', stdout) @@ -103,14 +103,14 @@ class TestGetMeta(unittest.TestCase): self.assertIn(b'date_time: 2011-07-26 02:40:16', stdout) def test_mp3(self): - proc = subprocess.Popen(['./mat2.py', '--show', './tests/data/dirty.mp3'], + proc = subprocess.Popen(['./mat2', '--show', './tests/data/dirty.mp3'], stdout=subprocess.PIPE) stdout, _ = proc.communicate() self.assertIn(b'TALB: harmfull', stdout) self.assertIn(b'COMM::: Thank you for using MAT !', stdout) def test_flac(self): - proc = subprocess.Popen(['./mat2.py', '--show', './tests/data/dirty.flac'], + proc = subprocess.Popen(['./mat2', '--show', './tests/data/dirty.flac'], stdout=subprocess.PIPE) stdout, _ = proc.communicate() self.assertIn(b'comments: Thank you for using MAT !', stdout) @@ -118,7 +118,7 @@ class TestGetMeta(unittest.TestCase): self.assertIn(b'title: I am so', stdout) def test_ogg(self): - proc = subprocess.Popen(['./mat2.py', '--show', './tests/data/dirty.ogg'], + proc = subprocess.Popen(['./mat2', '--show', './tests/data/dirty.ogg'], stdout=subprocess.PIPE) stdout, _ = proc.communicate() self.assertIn(b'comments: Thank you for using MAT !', stdout) -- cgit v1.3