#!/usr/bin/env python3 # -*- coding: utf-8 -*- # zipfix.py # Copyright © 2010-2020 by Apprentice Harper et al. # Released under the terms of the GNU General Public Licence, version 3 # # Revision history: # 1.0 - Initial release # 1.1 - Updated to handle zip file metadata correctly # 2.0 - Python 3 for calibre 5.0 """ Re-write zip (or ePub) fixing problems with file names (and mimetype entry). """ __license__ = 'GPL v3' __version__ = "1.1" import sys, os # Calibre stuff - so we can import from our ZIP without absolute module name sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) import zlib import zipfilerugged import getopt from struct import unpack _FILENAME_LEN_OFFSET = 26 _EXTRA_LEN_OFFSET = 28 _FILENAME_OFFSET = 30 _MAX_SIZE = 64 * 1024 _MIMETYPE = 'application/epub+zip' class ZipInfo(zipfilerugged.ZipInfo): def __init__(self, *args, **kwargs): if 'compress_type' in kwargs: compress_type = kwargs.pop('compress_type') super(ZipInfo, self).__init__(*args, **kwargs) self.compress_type = compress_type class fixZip: def __init__(self, zinput, zoutput): self.ztype = 'zip' if zinput.lower().find('.epub') >= 0 : self.ztype = 'epub' self.inzip = zipfilerugged.ZipFile(zinput,'r') self.outzip = zipfilerugged.ZipFile(zoutput,'w') # open the input zip for reading only as a raw file self.bzf = open(zinput,'rb') def getlocalname(self, zi): local_header_offset = zi.header_offset self.bzf.seek(local_header_offset + _FILENAME_LEN_OFFSET) leninfo = self.bzf.read(2) local_name_length, = unpack(' 0: if len(cmpdata) > _MAX_SIZE : newdata = cmpdata[0:_MAX_SIZE] cmpdata = cmpdata[_MAX_SIZE:] else: newdata = cmpdata cmpdata = b'' newdata = dc.decompress(newdata) unprocessed = dc.unconsumed_tail if len(unprocessed) == 0: newdata += dc.flush() data += newdata cmpdata += unprocessed unprocessed = b'' return data def getfiledata(self, zi): # get file name length and exta data length to find start of file data local_header_offset = zi.header_offset self.bzf.seek(local_header_offset + _FILENAME_LEN_OFFSET) leninfo = self.bzf.read(2) local_name_length, = unpack('