Source code for stouputils.dont_look.zip_file_override
"""This module provides a zip file override to handle some corrupted zip files.For instance, some Minecraft servers resource packs are slightly corrupted and cannot be opened with the standard zipfile module.See the archive.py module for more information."""# ImportsfromzipfileimportZipFile,ZipInfo,ZipExtFile,_SharedFile,sizeFileHeader,struct,structFileHeader,_FH_EXTRA_FIELD_LENGTH,crc32# type: ignore# Class overrides
[docs]classZipExtFileOverride(ZipExtFile):""" Override of the ZipExtFile class """
[docs]def_update_crc(self,newdata)->None:# type: ignore""" Override of the _update_crc method """# Update the CRC using the given data.ifself._expected_crcisNone:# type: ignore# No need to compute the CRC if we don't have a reference valuereturnself._running_crc=crc32(newdata,self._running_crc)# type: ignore
[docs]classZipFileOverride(ZipFile):""" Override of the ZipFile class """
[docs]defopen(self,name,mode="r",pwd=None,*,force_zip64=False):# type: ignore"""Return file-like object for 'name'. name is a string for the file name within the ZIP file, or a ZipInfo object. mode should be 'r' to read a file already in the ZIP file, or 'w' to write to a file newly added to the archive. pwd is the password to decrypt files (only used for reading). When writing, if the file size is not known in advance but may exceed 2 GiB, pass force_zip64 to use the ZIP64 format, which can handle large files. If the size is known in advance, it is best to pass a ZipInfo instance for name, with zinfo.file_size set. """ifmodenotin{"r","w"}:raiseValueError('open() requires mode "r" or "w"')ifpwdand(mode=="w"):raiseValueError("pwd is only supported for reading files")ifnotself.fp:raiseValueError("Attempt to use ZIP archive that was already closed")# Make sure we have an info objectifisinstance(name,ZipInfo):# 'name' is already an info objectzinfo=nameelifmode=='w':zinfo=ZipInfo(name)zinfo.compress_type=self.compressionzinfo._compresslevel=self.compresslevel# type: ignoreelse:# Get info object for namezinfo=self.getinfo(name)ifmode=='w':returnself._open_to_write(zinfo,force_zip64=force_zip64)# type: ignoreifself._writing:# type: ignoreraiseValueError("Can't read from the ZIP file while there ""is an open writing handle on it. ""Close the writing handle before trying to read.")# Open for reading:self._fileRefCnt+=1# type: ignorezef_file=_SharedFile(self.fp,zinfo.header_offset,# type: ignoreself._fpclose,self._lock,lambda:self._writing)# type: ignoretry:# Skip the file header:fheader=zef_file.read(sizeFileHeader)# type: ignorefheader=struct.unpack(structFileHeader,fheader)# type: ignoreiffheader[_FH_EXTRA_FIELD_LENGTH]:zef_file.seek(fheader[_FH_EXTRA_FIELD_LENGTH],whence=1)# type: ignoreifzinfo.flag_bits&0x20:# Zip 2.7: compressed patched dataraiseNotImplementedError("compressed patched data (flag bit 5)")ifzinfo.flag_bits&0x40:# strong encryptionraiseNotImplementedError("strong encryption (flag bit 6)")# if (zinfo._end_offset is not None and# zef_file.tell() + zinfo.compress_size > zinfo._end_offset):# raise BadZipFile(f"Overlapped entries: {zinfo.orig_filename!r} (possible zip bomb)")# check for encrypted flag & handle passwordis_encrypted=zinfo.flag_bits&0x1ifis_encrypted:ifnotpwd:pwd=self.pwdifpwdandnotisinstance(pwd,bytes):# type: ignoreraiseTypeError("pwd: expected bytes, got %s"%type(pwd).__name__)ifnotpwd:raiseRuntimeError("File %r is encrypted, password ""required for extraction"%name)else:pwd=NonereturnZipExtFileOverride(zef_file,mode,zinfo,pwd,True)# type: ignoreexcept:zef_file.close()# type: ignoreraise