import io from .matcher import SignatureMatcher, Match class Zip(SignatureMatcher): """ Zip files are read from the bottom The signature PK is the local file header https://medium.com/@felixstridsberg/the-zip-file-format-6c8a160d1c34 """ def __init__(self, file): self.name = "Zip" self.signature = b'PK\x03\x04' super().__init__(file) def is_valid(self): for match in self.search(): start = match header = io.BytesIO(self.file[start:start+4*4 + 2*7]) magic = header.read(4) min_version = header.read(2) bitflag = header.read(2) compression_method = header.read(2) last_modification_time = header.read(2) last_modification_data = header.read(2) crc = header.read(4) compressed_size = header.read(4) uncompressed_size = header.read(4) file_name_length = header.read(2) extra_field_length = header.read(2) as_num = lambda x: int.from_bytes(x, 'little') file_name_length = as_num(file_name_length) extra_field_length = as_num(extra_field_length) compressed_size = as_num(compressed_size) header_size = 4*4 + 2*7 data = { 'name': self.file[start+header_size:start+header_size+file_name_length] } size = 4*4 + 2*7 + file_name_length + extra_field_length + compressed_size self.matches += [Match(start, size, data)] return len(self.matches) != 0