def is_zipfile(filename): # patched to accept a file that is already open we use the # _EndRecData method directly, we're all grown-ups here try: if is_text(filename): fpin = open(filename, "rb") endrec = zipfile._EndRecData(fpin) fpin.close() else: endrec = zipfile._EndRecData(filename) if endrec: return True except IOError: pass return False
def is_zipstream(data): """ just like zipfile.is_zipfile, but works upon buffers and streams rather than filenames. If data supports the read method, it will be treated as a stream and read from to test whether it is a valid ZipFile. If data also supports the tell and seek methods, it will be rewound after being tested. """ if isinstance(data, (str, buffer)): data = StringIO(data) if hasattr(data, "read"): tell = 0 if hasattr(data, "tell"): tell = data.tell() try: result = bool(_EndRecData(data)) except IOError: result = False if hasattr(data, "seek"): data.seek(tell) else: raise TypeError("requies str, buffer, or stream-like object") return result
def is_zipstream(data): """ just like zipfile.is_zipfile, but works upon buffers and streams rather than filenames. If data supports the read method, it will be treated as a stream and read from to test whether it is a valid ZipFile. If data also supports the tell and seek methods, it will be rewound after being tested. """ if isinstance(data, (str, buffer)): data = BytesIO(data) if hasattr(data, "read"): tell = 0 if hasattr(data, "tell"): tell = data.tell() try: result = bool(_EndRecData(data)) except IOError: result = False if hasattr(data, "seek"): data.seek(tell) else: raise TypeError("requies str, buffer, or stream-like object") return result
def _check_zipfile(fp): try: if _EndRecData(fp): return True # file has correct magic number except IOError: pass return False
def is_zip_fp(fp): from zipfile import _EndRecData try: here = fp.tell() ret = _EndRecData(fp) fp.seek(here) return ret except IOError: pass return False
def is_zipfile(fp): """ This is a version of zipfile.is_zipfile, adjusted to only work for file pointers, but to work in both python 2.6 and 2.7. """ try: if zipfile._EndRecData(fp): return True # file has correct magic number except IOError: pass return False
def get_endrec(file): ''' Look up and return the end of central directory record move the file stream cursor to the end of central directory record ''' pos = file.tell() # return end of central directory record content endrec = _EndRecData(file) # move file stream cursor to the end of central directory record file.seek(pos) # return end of central directory record return endrec
def __v2_zipfindsig(self): ret_sig_start = -1 ret_offset_cd = -1 ret_cd_end = -1 filesize = -1 apk_sig_block_min_size = 32 ret_v2sigs = {} break_goto_fail = True while break_goto_fail: break_goto_fail = False endrec = _EndRecData(self.zip_file.fp) size_cd = endrec[_ECD_SIZE] # bytes in central directory offset_cd = endrec[_ECD_OFFSET] # offset of central directory if offset_cd < apk_sig_block_min_size: break self.zip_file.fp.seek(0, 2) filesize = self.zip_file.fp.tell() if offset_cd + size_cd > filesize: break ret_offset_cd = offset_cd ret_cd_end = offset_cd + size_cd self.zip_file.fp.seek(offset_cd - 24) buf = self.zip_file.fp.read(24) if buf[8:] != b'APK Sig Block 42': break sigin_foot = struct.unpack('<Q', buf[:8])[0] if sigin_foot < 24 or sigin_foot > filesize: break ret_sig_start = offset_cd - sigin_foot - 8 if ret_sig_start < 0 or ret_sig_start > filesize: break self.zip_file.fp.seek(ret_sig_start) buf = self.zip_file.fp.read(sigin_foot + 8) sigin_head = struct.unpack('<Q', buf[:8])[0] if sigin_foot != sigin_head: break idx = 8 while idx + 12 <= sigin_head - 24: length = struct.unpack('<Q', buf[idx:idx + 8])[0] index = struct.unpack('<L', buf[idx + 8:idx + 12])[0] s = buf[idx + 12:idx + 12 + length - 4] ret_v2sigs[index] = s idx += 12 idx += length - 4 # buff2 = buf[idx:] # print(repr(buff2)) # print(v2sig) return ret_v2sigs, ret_sig_start, ret_offset_cd, ret_cd_end, filesize
def __v2_zipfindsig(self): ret_sig_start = -1 ret_offset_cd = -1 ret_cd_end = -1 filesize = -1 apk_sig_block_min_size = 32 ret_v2sigs = {} break_goto_fail = True while break_goto_fail: break_goto_fail = False endrec = _EndRecData(self.zip_file.fp) size_cd = endrec[_ECD_SIZE] # bytes in central directory offset_cd = endrec[_ECD_OFFSET] # offset of central directory if offset_cd < apk_sig_block_min_size: break self.zip_file.fp.seek(0, 2) filesize = self.zip_file.fp.tell() if offset_cd + size_cd > filesize: break ret_offset_cd = offset_cd ret_cd_end = offset_cd + size_cd self.zip_file.fp.seek(offset_cd - 24) buf = self.zip_file.fp.read(24) if buf[8:] != b'APK Sig Block 42': break sigin_foot = struct.unpack(b'<Q', buf[:8])[0] if sigin_foot < 24 or sigin_foot > filesize: break ret_sig_start = offset_cd - sigin_foot - 8 if ret_sig_start < 0 or ret_sig_start > filesize: break self.zip_file.fp.seek(ret_sig_start) buf = self.zip_file.fp.read(sigin_foot + 8) sigin_head = struct.unpack(b'<Q', buf[:8])[0] if sigin_foot != sigin_head: break idx = 8 while idx + 12 <= sigin_head - 24: length = struct.unpack(b'<Q', buf[idx:idx + 8])[0] index = struct.unpack(b'<L', buf[idx + 8:idx + 12])[0] s = buf[idx + 12:idx + 12 + length - 4] ret_v2sigs[index] = s idx += 12 idx += length - 4 # buff2 = buf[idx:] # print(repr(buff2)) # print(v2sig) return ret_v2sigs, ret_sig_start, ret_offset_cd, ret_cd_end, filesize
def _read_central_directory_offsets(zfile): """Read in the table of contents for the ZIP file.""" fp = zfile.fp try: endrec = zipfile._EndRecData(fp) except IOError: raise zipfile.BadZipfile("File is not a zip file") if not endrec: raise zipfile.BadZipfile, "File is not a zip file" size_cd = endrec[_ECD_SIZE] # bytes in central directory offset_cd = endrec[_ECD_OFFSET] # offset of central directory # "concat" is zero, unless zip was concatenated to another file concat = endrec[_ECD_LOCATION] - size_cd - offset_cd if endrec[_ECD_SIGNATURE] == stringEndArchive64: # If Zip64 extension structures are present, account for them concat -= (sizeEndCentDir64 + sizeEndCentDir64Locator) # Go to start of central directory fp.seek(offset_cd + concat, 0) data = fp.read(size_cd) fp = cStringIO.StringIO(data) total = 0 offsets = [] while total < size_cd: # Tell gives use the offset inside the CD. We want the offset relative # to the beginning of file. offsets.append(fp.tell() + offset_cd + concat) centdir = fp.read(sizeCentralDir) if len(centdir) != sizeCentralDir: raise zipfile.BadZipfile("Truncated central directory") centdir = struct.unpack(structCentralDir, centdir) if centdir[_CD_SIGNATURE] != stringCentralDir: raise zipfile.BadZipfile("Bad magic number for central directory") # Skip everything else fp.seek(centdir[_CD_FILENAME_LENGTH] + centdir[_CD_EXTRA_FIELD_LENGTH] + centdir[_CD_COMMENT_LENGTH], 1) # update total bytes read from central directory total = (total + sizeCentralDir + centdir[_CD_FILENAME_LENGTH] + centdir[_CD_EXTRA_FIELD_LENGTH] + centdir[_CD_COMMENT_LENGTH]) return offsets
def h5_open_zip(filename, file_obj=None, mode='rb', **kw): """ Open a NeXus file, even if it is in a zip file, or if it is a NeXus-zip file. If the filename ends in '.zip', it will be unzipped to a temporary directory before opening and deleted on :func:`closezip`. If opened for writing, then the file will be created in a temporary directory, then zipped and deleted on :func:`closezip`. If it is a zipfile but doesn't end in '.zip', it is assumed to be a NeXus-zip file and is opened with that library. Arguments are the same as for :func:`open`. """ if file_obj is None: file_obj = open(filename, mode=mode, buffering=-1) is_zip = _EndRecData( file_obj) # is_zipfile(file_obj) doens't work in py2.6 if is_zip and '.attrs' in ZipFile(file_obj).namelist(): # then it's a nexus-zip file, rather than # a zipped hdf5 nexus file f = hzf.File(filename, file_obj) f.delete_on_close = False f.zip_on_close = False else: zip_on_close = None if is_zip: path = tempfile.gettempdir() if mode == 'r': zf = ZipFile(filename) members = zf.namelist() assert len(members) == 1 zf.extract(members[0], path) filename = os.path.join(path, members[0]) elif mode == 'w': zip_on_close = filename filename = os.path.join(path, os.path.basename(filename)[:-4]) else: raise TypeError("zipped nexus files only support mode r and w") f = h5.File(filename, mode=mode, **kw) f.delete_on_close = is_zip f.zip_on_close = zip_on_close return f
def h5_open_zip(filename, file_obj=None, mode="r", **kw): """ Open a NeXus file, even if it is in a zip file, or if it is a NeXus-zip file. If the filename ends in '.zip', it will be unzipped to a temporary directory before opening and deleted on :func:`closezip`. If opened for writing, then the file will be created in a temporary directory, then zipped and deleted on :func:`closezip`. If it is a zipfile but doesn't end in '.zip', it is assumed to be a NeXus-zip file and is opened with that library. Arguments are the same as for :func:`open`. """ if file_obj is None: file_obj = open(filename, mode=mode) is_zip = _EndRecData(file_obj) # is_zipfile(file_obj) doens't work in py2.6 if is_zip and not filename.endswith(".zip"): # then it's a nexus-zip file, rather than # a zipped hdf5 nexus file f = hzf.File(filename, file_obj) f.delete_on_close = False f.zip_on_close = False else: zip_on_close = None if is_zip: path = tempfile.gettempdir() if mode == "r": zf = ZipFile(filename) members = zf.namelist() assert len(members) == 1 zf.extract(members[0], path) filename = os.path.join(path, members[0]) elif mode == "w": zip_on_close = filename filename = os.path.join(path, os.path.basename(filename)[:-4]) else: raise TypeError("zipped nexus files only support mode r and w") f = h5.File(filename, mode=mode, **kw) f.delete_on_close = is_zip f.zip_on_close = zip_on_close return f
def get_last_zip_begin(fname): with zipfile.ZipFile(fname) as zfin: central_directory_begin = zfin.start_dir last_zip_first_file_entity_begin = min( (info.header_offset for info in zfin.infolist()), default=None) # NOTE: # * when infolist is empty # * when there are some deleted file entry in front of last zip file with open(fname, 'rb') as fin: endrec = _EndRecData(fin) # [b'PK\x05\x06', 0, 0, 2, 2, 183, 32592, 0, b'', 65296] offset_cd = endrec[_ECD_OFFSET] # offset of central directory # offset_cd is the old central_directory_begin # central_directory_begin is new, i.e. prefix_size + offset_cd concat_prefix_file_size = central_directory_begin - offset_cd if last_zip_first_file_entity_begin is not None: assert concat_prefix_file_size <= last_zip_first_file_entity_begin last_zip_begin = concat_prefix_file_size return last_zip_begin
def get_endrec(file): pos = file.tell() endrec = _EndRecData(file) file.seek(pos) return endrec
def _RealGetContents(self): """Read in the table of contents for the ZIP file.""" fp = self.fp try: endrec = zipfile._EndRecData(fp) except OSError: raise zipfile.BadZipFile("File is not a zip file") if not endrec: raise zipfile.BadZipFile("File is not a zip file") if self.debug > 1: print(endrec) size_cd = endrec[zipfile._ECD_SIZE] # bytes in central directory offset_cd = endrec[zipfile._ECD_OFFSET] # offset of central directory self._comment = endrec[zipfile._ECD_COMMENT] # archive comment # "concat" is zero, unless zip was concatenated to another file concat = endrec[zipfile._ECD_LOCATION] - size_cd - offset_cd if endrec[zipfile._ECD_SIGNATURE] == zipfile.stringEndArchive64: # If Zip64 extension structures are present, account for them concat -= zipfile.sizeEndCentDir64 + zipfile.sizeEndCentDir64Locator if self.debug > 2: inferred = concat + offset_cd print("given, inferred, offset", offset_cd, inferred, concat) # self.start_dir: Position of start of central directory self.start_dir = offset_cd + concat fp.seek(self.start_dir, 0) data = fp.read(size_cd) fp = io.BytesIO(data) total = 0 while total < size_cd: centdir = fp.read(zipfile.sizeCentralDir) if len(centdir) != zipfile.sizeCentralDir: raise zipfile.BadZipFile("Truncated central directory") centdir = struct.unpack(zipfile.structCentralDir, centdir) if centdir[zipfile._CD_SIGNATURE] != zipfile.stringCentralDir: raise zipfile.BadZipFile( "Bad magic number for central directory") if self.debug > 2: print(centdir) filename = fp.read(centdir[zipfile._CD_FILENAME_LENGTH]) flags = centdir[5] if flags & 0x800: # UTF-8 file names extension filename = filename.decode("utf-8") else: # Historical ZIP filename encoding filename = filename.decode("cp437") # Create ZipInfo instance to store file information x = P4KInfo(filename) x.extra = fp.read(centdir[zipfile._CD_EXTRA_FIELD_LENGTH]) x.comment = fp.read(centdir[zipfile._CD_COMMENT_LENGTH]) x.header_offset = centdir[zipfile._CD_LOCAL_HEADER_OFFSET] ( x.create_version, x.create_system, x.extract_version, x.reserved, x.flag_bits, x.compress_type, t, d, x.CRC, x.compress_size, x.file_size, ) = centdir[1:12] if x.extract_version > zipfile.MAX_EXTRACT_VERSION: raise NotImplementedError("zip file version %.1f" % (x.extract_version / 10)) x.volume, x.internal_attr, x.external_attr = centdir[15:18] # Convert date/time code to (year, month, day, hour, min, sec) x._raw_time = t x.date_time = ( (d >> 9) + 1980, (d >> 5) & 0xF, d & 0x1F, t >> 11, (t >> 5) & 0x3F, (t & 0x1F) * 2, ) x._decodeExtra() x.header_offset = x.header_offset + concat self.filelist.append(x) self.NameToInfo[x.filename] = x # update total bytes read from central directory total = (total + zipfile.sizeCentralDir + centdir[zipfile._CD_FILENAME_LENGTH] + centdir[zipfile._CD_EXTRA_FIELD_LENGTH] + centdir[zipfile._CD_COMMENT_LENGTH]) if self.debug > 2: print("total", total)
def _RealGetContents1(self,filename_to_open): """Read in the table of contents for the ZIP file.""" fp = self.fp endrec = zipfile._EndRecData(fp) if not endrec: raise BadZipfile, "File is not a zip file" if self.debug > 1: print endrec size_cd = endrec[5] # bytes in central directory offset_cd = endrec[6] # offset of central directory self.comment = endrec[8] # archive comment # endrec[9] is the offset of the "End of Central Dir" record x = endrec[9] - size_cd # "concat" is zero, unless zip was concatenated to another file concat = x - offset_cd if self.debug > 2: print "given, inferred, offset", offset_cd, x, concat # self.start_dir: Position of start of central directory self.start_dir = offset_cd + concat fp.seek(self.start_dir, 0) total = 0 # >>>create just once instance of ZipInfo x = zipfile.ZipInfo('_') while total < size_cd: centdir = fp.read(46) total = total + 46 if centdir[0:4] != stringCentralDir: raise BadZipfile, "Bad magic number for central directory" centdir = struct.unpack(structCentralDir, centdir) if self.debug > 2: print centdir filename = fp.read(centdir[_CD_FILENAME_LENGTH]) # Create ZipInfo instance to store file information #x = ZipInfo(filename) # >>>Initialize x assuming it will match filename_to_open x.orig_filename = filename # >>>Below includes filename cleanup code is borrowed from ZipFile.__init__ # Terminate the file name at the first null byte. Null bytes in file # names are used as tricks by viruses in archives. null_byte = filename.find(chr(0)) if null_byte >= 0: filename = filename[0:null_byte] # This is used to ensure paths in generated ZIP files always use # forward slashes as the directory separator, as required by the # ZIP format specification. if os.sep != "/": filename = filename.replace(os.sep, "/") x.filename = filename x.extra = fp.read(centdir[_CD_EXTRA_FIELD_LENGTH]) x.comment = fp.read(centdir[_CD_COMMENT_LENGTH]) total = (total + centdir[_CD_FILENAME_LENGTH] + centdir[_CD_EXTRA_FIELD_LENGTH] + centdir[_CD_COMMENT_LENGTH]) x.header_offset = centdir[_CD_LOCAL_HEADER_OFFSET] + concat # file_offset must be computed below... (x.create_version, x.create_system, x.extract_version, x.reserved, x.flag_bits, x.compress_type, t, d, x.CRC, x.compress_size, x.file_size) = centdir[1:12] x.volume, x.internal_attr, x.external_attr = centdir[15:18] # Convert date/time code to (year, month, day, hour, min, sec) x.date_time = ( (d>>9)+1980, (d>>5)&0xF, d&0x1F, t>>11, (t>>5)&0x3F, (t&0x1F) * 2 ) #self.filelist.append(x) #self.NameToInfo[x.filename] = x #if self.debug > 2: # print "total", total #>>> break the loop as soon as we find a matching filename if filename == filename_to_open: break else: raise KeyError, filename_to_open #>>>Use x as data. No need to loop all files data = x #for data in self.filelist: fp.seek(data.header_offset, 0) fheader = fp.read(30) if fheader[0:4] != stringFileHeader: raise BadZipfile, "Bad magic number for file header" fheader = struct.unpack(structFileHeader, fheader) # file_offset is computed here, since the extra field for # the central directory and for the local file header # refer to different fields, and they can have different # lengths data.file_offset = (data.header_offset + 30 + fheader[_FH_FILENAME_LENGTH] + fheader[_FH_EXTRA_FIELD_LENGTH]) fname = fp.read(fheader[_FH_FILENAME_LENGTH]) if fname != data.orig_filename: raise RuntimeError, \ 'File name in directory "%s" and header "%s" differ.' % ( data.orig_filename, fname) return data
def update_event(self, inp=-1): self.set_output_val(0, zipfile._EndRecData(self.input(0)))
with zipfile.ZipFile(zpayload, 'w', zipfile.ZIP_DEFLATED) as zipf: for i in xrange(10): fn = uuid.uuid4() data = os.urandom(512) zipf.writestr(str(fn), data) fs.append((fn, SHA.new(data).hexdigest())) zipblob = zpayload.getvalue() crxpayload = iofactory() cf = CRXFile.CRXFile(crxpayload, mode='w', log=log.getChild('wcrx')) cf.setprivatekey(k) sha1sum = '\n'.join(["%s %s" % (fn, ss) for fn, ss in fs]) cf.setsha1sum(sha1sum) _endrec = zipfile._EndRecData(zpayload) zpayload.seek(_endrec[zipfile._ECD_OFFSET]) zipdir = zpayload.read(zipfile._ECD_SIZE) cf.setzcd(zipdir) cf.setpayloadblob(zipblob) cf.write_crx_header() cf.write_payload() # REWIND THE TAPE WHIRR WHIRR WHIRR crxpayload.seek(0) rcf = CRXFile.CRXFile(crxpayload, log=log.getChild('rcrx')) rzip = zipfile.ZipFile(rcf) code.interact(local=locals())
def get_zip_infos(self, *filenames): """Read in the table of contents for the ZIP file.""" fp = self.fp max_file_count = self.max_file_count if not fp: raise RuntimeError( "Attempt to read ZIP archive that was already closed") filenames = set(filenames) if len(filenames) == 0: return try: endrec = _EndRecData(fp) except OSError: raise BadZipFile("File is not a zip file") if not endrec: raise BadZipFile("File is not a zip file") size_cd = endrec[_ECD_SIZE] # bytes in central directory offset_cd = endrec[_ECD_OFFSET] # offset of central directory # "concat" is zero, unless zip was concatenated to another file concat = endrec[_ECD_LOCATION] - size_cd - offset_cd if endrec[_ECD_SIGNATURE] == stringEndArchive64: # If Zip64 extension structures are present, account for them concat -= (sizeEndCentDir64 + sizeEndCentDir64Locator) # start_dir: Position of start of central directory start_dir = offset_cd + concat fp.seek(start_dir, 0) data = fp.read(size_cd) fp = BytesIO(data) total = 0 file_count = 0 while total < size_cd: centdir = fp.read(sizeCentralDir) if len(centdir) != sizeCentralDir: raise BadZipFile("Truncated central directory") centdir = struct.unpack(structCentralDir, centdir) if centdir[_CD_SIGNATURE] != stringCentralDir: raise BadZipFile("Bad magic number for central directory") filename = fp.read(centdir[_CD_FILENAME_LENGTH]) flags = centdir[5] if flags & _UTF8_EXTENSION_FLAG: # UTF-8 file names extension filename = filename.decode('utf-8') else: # Historical ZIP filename encoding filename = filename.decode('cp437') # Create ZipInfo instance to store file information x = ZipInfo(filename) x.extra = fp.read(centdir[_CD_EXTRA_FIELD_LENGTH]) x.comment = fp.read(centdir[_CD_COMMENT_LENGTH]) x.header_offset = centdir[_CD_LOCAL_HEADER_OFFSET] (x.create_version, x.create_system, x.extract_version, x.reserved, x.flag_bits, x.compress_type, t, d, x.CRC, x.compress_size, x.file_size) = centdir[1:12] if x.extract_version > MAX_EXTRACT_VERSION: raise NotImplementedError("zip file version %.1f" % (x.extract_version / 10)) x.volume, x.internal_attr, x.external_attr = centdir[15:18] # Convert date/time code to (year, month, day, hour, min, sec) x._raw_time = t x.date_time = ((d >> 9) + 1980, (d >> 5) & 0xF, d & 0x1F, t >> 11, (t >> 5) & 0x3F, (t & 0x1F) * 2) x._decodeExtra() x.header_offset = x.header_offset + concat # update total bytes read from central directory total = (total + sizeCentralDir + centdir[_CD_FILENAME_LENGTH] + centdir[_CD_EXTRA_FIELD_LENGTH] + centdir[_CD_COMMENT_LENGTH]) file_count += 1 if max_file_count is not None and file_count > max_file_count: raise TooManyFiles('Too many files in egg') if x.filename in filenames: filenames.discard(x.filename) yield x if len(filenames) == 0: return