|
- #!/usr/bin/env python
- # Copyright 2006 John-Mark Gurney <gurney_j@resnet.uoregon.edu>
-
- __version__ = '$Change$'
- # $Id$
-
- import binascii
- import os
- import zipfile
- from zipfile import *
- try:
- import zlib # We may need its compression method
- except ImportError:
- zlib = None
-
- __all__ = zipfile.__all__
-
- def dupfile(fp):
- if not hasattr(fp, 'fileno'):
- raise ValueError, 'must be operating on real file'
- newfp = os.fdopen(os.dup(fp.fileno()))
- return newfp
-
- class ZipFile(ZipFile):
- def readiter(self, name, blksize=16384):
- """Return file bytes (as a string) for name."""
-
- if self.mode not in ("r", "a"):
- raise RuntimeError, 'read() requires mode "r" or "a"'
- if not self.fp:
- raise RuntimeError, "Attempt to read ZIP archive " \
- "that was already closed"
- zinfo = self.getinfo(name)
- fp = dupfile(self.fp)
- fp.seek(zinfo.file_offset, 0)
- if zinfo.compress_type == ZIP_STORED:
- assert zinfo.file_size == zinfo.compress_size
- i = 0
- while i < zinfo.file_size:
- yield fp.read(min(blksize, zinfo.file_size - i))
- elif zinfo.compress_type == ZIP_DEFLATED:
- if not zlib:
- raise RuntimeError, "De-compression requires " \
- "the (missing) zlib module"
- # zlib compress/decompress code by Jeremy Hylton of CNRI
- uncomp = 0
- comp = 0
- dc = zlib.decompressobj(-15)
- crc = None
- doflush = False
- while uncomp < zinfo.file_size:
- if not dc.unconsumed_tail:
- compread = min(blksize,
- zinfo.compress_size - comp)
- bytes = fp.read(compread)
- comp += compread
- if compread == 0:
- doflush = True
- else:
- bytes = dc.unconsumed_tail
- if doflush:
- # need to feed in unused pad byte so
- # that zlib won't choke
- bytes = dc.decompress('Z') + dc.flush()
- else:
- bytes = dc.decompress(bytes, blksize)
- yield bytes
- uncomp += len(bytes)
- if crc is None:
- crc = binascii.crc32(bytes)
- else:
- crc = binascii.crc32(bytes, crc)
- if crc != zinfo.CRC:
- raise BadZipfile, "Bad CRC-32 for file %s" % \
- name
- else:
- raise BadZipfile, "Unsupported compression method " \
- "%d for file %s" % (zinfo.compress_type, name)
|