From 6c8dcd46a59deb550f96c8910f1d6199c6db14e2 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Wed, 22 Nov 2023 21:21:56 -0300 Subject: [PATCH] PEExtractor: Add Inno Setup (used by NEC) extraction --- Dockerfile | 2 +- biostools/extractors.py | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 2beff13..561977b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -47,7 +47,7 @@ FROM debian:bullseye # Install runtime dependencies. RUN sed -i -e 's/main/main contrib non-free/' /etc/apt/sources.list && \ apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get install -y python3 python3-pip p7zip-full p7zip-rar unshield qemu-system-x86 && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y python3 python3-pip p7zip-full p7zip-rar innoextract unshield qemu-system-x86 && \ apt-get clean && \ rm -rf /var/lib/apt/lists diff --git a/biostools/extractors.py b/biostools/extractors.py index a9105be..4b518aa 100644 --- a/biostools/extractors.py +++ b/biostools/extractors.py @@ -2300,6 +2300,13 @@ class PEExtractor(ArchiveExtractor): if ret: return ret + # Cover Inno Setup installers. + if file_header[48:52] == b'Inno': + # Determine if this executable can be extracted with innoextract. + ret = self._extract_inno(file_path, file_header, dest_dir) + if ret: + return ret + # Read up to 16 MB as a safety net. file_header += util.read_complement(file_path, file_header) @@ -2455,6 +2462,32 @@ class PEExtractor(ArchiveExtractor): # Return destination directory path. return dest_dir + def _extract_inno(self, file_path, file_header, dest_dir): + # Create destination directory and stop if it couldn't be created. + if not util.try_makedirs(dest_dir): + return True + + # Run innoextract command. + try: + subprocess.run(['innoextract', '-e', os.path.abspath(file_path)], stdout=self._devnull, stderr=subprocess.STDOUT, cwd=dest_dir) + except: + pass + + # Assume failure if nothing was extracted. + files_extracted = os.listdir(dest_dir) + if len(files_extracted) < 1: + self.debug_print('Extraction produced no files:', file_path) + return False + + # Remove file. + try: + os.remove(file_path) + except: + pass + + # Return destination directory path. + return dest_dir + class TarExtractor(ArchiveExtractor): """Extract tar archives."""