Module refinery.units.formats.archive.xtinno
Expand source code Browse git
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from __future__ import annotations
import re
from refinery.units.formats.archive import ArchiveUnit
from refinery.lib.mime import FileMagicInfo as magic
from refinery.lib.json import BytesAsArrayEncoder
from refinery.lib.inno.archive import InnoArchive, InvalidPassword, SetupFileFlags
class xtinno(ArchiveUnit):
"""
Extract files from InnoSetup archives.
"""
_STREAM_NAMES = 'meta/TSetup', 'meta/TData', 'embedded/uninstaller.exe'
_ISCRIPT_NAME = 'embedded/script'
_LICENSE_NAME = 'embedded/license.rtf'
def unpack(self, data: bytearray):
inno = InnoArchive(data, self)
password: bytes = self.args.pwd
password = password.decode(self.codec) if password else ''
if any(file.encrypted for file in inno.files) and password is None:
self.log_info('some files are password-protected and no password was given')
yield self._pack(self._STREAM_NAMES[0], None, inno.streams.TSetup.data)
with BytesAsArrayEncoder as encoder:
yield self._pack(F'{self._STREAM_NAMES[0]}.json', None,
encoder.dumps(inno.setup_info.json()).encode(self.codec))
yield self._pack(self._STREAM_NAMES[1], None, inno.streams.TData.data)
with BytesAsArrayEncoder as encoder:
yield self._pack(F'{self._STREAM_NAMES[1]}.json', None,
encoder.dumps(inno.setup_data.json()).encode(self.codec))
def _uninstaller(i=inno):
return i.read_stream(i.streams.Uninstaller)
yield self._pack(self._STREAM_NAMES[2], None, _uninstaller)
if license := inno.setup_info.Header.get_license():
yield self._pack(self._LICENSE_NAME, None, license.encode(self.codec))
if script := inno.setup_info.Header.get_script():
yield self._pack(F'{self._ISCRIPT_NAME}.bin', None, script)
yield self._pack(F'{self._ISCRIPT_NAME}.ps', None,
lambda i=inno: i.ifps.disassembly().encode(self.codec))
if dll := inno.setup_info.get_decompress_dll():
yield self._pack(F'embedded/decompress.{magic(dll).extension}', None, dll)
if dll := inno.setup_info.get_decryption_dll():
yield self._pack(F'embedded/decryption.{magic(dll).extension}', None, dll)
for size, images in (
('small', inno.setup_info.get_wizard_images_small()),
('large', inno.setup_info.get_wizard_images_large()),
):
_formatting = len(str(len(images) + 1))
for k, img in enumerate(images, 1):
yield self._pack(F'embedded/images/{size}{k:0{_formatting}d}.{magic(img).extension}', None, img)
for file in inno.files:
if file.dupe:
continue
def _read(i=inno, f=file, p=password):
if self.leniency > 0:
return i.read_file(f, p)
try:
return i.read_file_and_check(f, p)
except InvalidPassword:
raise
except Exception as E:
raise ValueError(F'{E!s} [ignore this check with -L]') from E
yield self._pack(file.path, file.date, _read,
tags=[t.name for t in SetupFileFlags if t & file.tags])
@classmethod
def handles(self, data):
if data[:2] != B'MZ':
return False
if re.search(re.escape(InnoArchive.ChunkPrefix), data) is None:
return False
return bool(
re.search(BR'Inno Setup Setup Data \(\d+\.\d+\.', data))
Classes
class xtinno (*paths, list=False, join_path=False, drop_path=False, fuzzy=0, exact=False, regex=False, path=b'path', date=b'date', pwd=b'')
-
Extract files from InnoSetup archives.
Expand source code Browse git
class xtinno(ArchiveUnit): """ Extract files from InnoSetup archives. """ _STREAM_NAMES = 'meta/TSetup', 'meta/TData', 'embedded/uninstaller.exe' _ISCRIPT_NAME = 'embedded/script' _LICENSE_NAME = 'embedded/license.rtf' def unpack(self, data: bytearray): inno = InnoArchive(data, self) password: bytes = self.args.pwd password = password.decode(self.codec) if password else '' if any(file.encrypted for file in inno.files) and password is None: self.log_info('some files are password-protected and no password was given') yield self._pack(self._STREAM_NAMES[0], None, inno.streams.TSetup.data) with BytesAsArrayEncoder as encoder: yield self._pack(F'{self._STREAM_NAMES[0]}.json', None, encoder.dumps(inno.setup_info.json()).encode(self.codec)) yield self._pack(self._STREAM_NAMES[1], None, inno.streams.TData.data) with BytesAsArrayEncoder as encoder: yield self._pack(F'{self._STREAM_NAMES[1]}.json', None, encoder.dumps(inno.setup_data.json()).encode(self.codec)) def _uninstaller(i=inno): return i.read_stream(i.streams.Uninstaller) yield self._pack(self._STREAM_NAMES[2], None, _uninstaller) if license := inno.setup_info.Header.get_license(): yield self._pack(self._LICENSE_NAME, None, license.encode(self.codec)) if script := inno.setup_info.Header.get_script(): yield self._pack(F'{self._ISCRIPT_NAME}.bin', None, script) yield self._pack(F'{self._ISCRIPT_NAME}.ps', None, lambda i=inno: i.ifps.disassembly().encode(self.codec)) if dll := inno.setup_info.get_decompress_dll(): yield self._pack(F'embedded/decompress.{magic(dll).extension}', None, dll) if dll := inno.setup_info.get_decryption_dll(): yield self._pack(F'embedded/decryption.{magic(dll).extension}', None, dll) for size, images in ( ('small', inno.setup_info.get_wizard_images_small()), ('large', inno.setup_info.get_wizard_images_large()), ): _formatting = len(str(len(images) + 1)) for k, img in enumerate(images, 1): yield self._pack(F'embedded/images/{size}{k:0{_formatting}d}.{magic(img).extension}', None, img) for file in inno.files: if file.dupe: continue def _read(i=inno, f=file, p=password): if self.leniency > 0: return i.read_file(f, p) try: return i.read_file_and_check(f, p) except InvalidPassword: raise except Exception as E: raise ValueError(F'{E!s} [ignore this check with -L]') from E yield self._pack(file.path, file.date, _read, tags=[t.name for t in SetupFileFlags if t & file.tags]) @classmethod def handles(self, data): if data[:2] != B'MZ': return False if re.search(re.escape(InnoArchive.ChunkPrefix), data) is None: return False return bool( re.search(BR'Inno Setup Setup Data \(\d+\.\d+\.', data))
Ancestors
Class variables
var required_dependencies
var optional_dependencies
Methods
def unpack(self, data)
-
Expand source code Browse git
def unpack(self, data: bytearray): inno = InnoArchive(data, self) password: bytes = self.args.pwd password = password.decode(self.codec) if password else '' if any(file.encrypted for file in inno.files) and password is None: self.log_info('some files are password-protected and no password was given') yield self._pack(self._STREAM_NAMES[0], None, inno.streams.TSetup.data) with BytesAsArrayEncoder as encoder: yield self._pack(F'{self._STREAM_NAMES[0]}.json', None, encoder.dumps(inno.setup_info.json()).encode(self.codec)) yield self._pack(self._STREAM_NAMES[1], None, inno.streams.TData.data) with BytesAsArrayEncoder as encoder: yield self._pack(F'{self._STREAM_NAMES[1]}.json', None, encoder.dumps(inno.setup_data.json()).encode(self.codec)) def _uninstaller(i=inno): return i.read_stream(i.streams.Uninstaller) yield self._pack(self._STREAM_NAMES[2], None, _uninstaller) if license := inno.setup_info.Header.get_license(): yield self._pack(self._LICENSE_NAME, None, license.encode(self.codec)) if script := inno.setup_info.Header.get_script(): yield self._pack(F'{self._ISCRIPT_NAME}.bin', None, script) yield self._pack(F'{self._ISCRIPT_NAME}.ps', None, lambda i=inno: i.ifps.disassembly().encode(self.codec)) if dll := inno.setup_info.get_decompress_dll(): yield self._pack(F'embedded/decompress.{magic(dll).extension}', None, dll) if dll := inno.setup_info.get_decryption_dll(): yield self._pack(F'embedded/decryption.{magic(dll).extension}', None, dll) for size, images in ( ('small', inno.setup_info.get_wizard_images_small()), ('large', inno.setup_info.get_wizard_images_large()), ): _formatting = len(str(len(images) + 1)) for k, img in enumerate(images, 1): yield self._pack(F'embedded/images/{size}{k:0{_formatting}d}.{magic(img).extension}', None, img) for file in inno.files: if file.dupe: continue def _read(i=inno, f=file, p=password): if self.leniency > 0: return i.read_file(f, p) try: return i.read_file_and_check(f, p) except InvalidPassword: raise except Exception as E: raise ValueError(F'{E!s} [ignore this check with -L]') from E yield self._pack(file.path, file.date, _read, tags=[t.name for t in SetupFileFlags if t & file.tags])
Inherited members